buildovanie cez task a verzia na jednom mieste

This commit is contained in:
Alojz Masár
2026-02-15 17:12:24 +01:00
parent a1628f04a3
commit b962c1be7f
7 changed files with 239 additions and 95 deletions

4
.devcontainer/.env Normal file
View File

@@ -0,0 +1,4 @@
PYTHON_BASE=3.13
DEVCONTAINER_IMAGE_PULL_REPO=docker.masara.eu/python
DEVCONTAINER_IMAGE_PUSH_REPO=repo.masara.eu/python
DEVCONTAINER_IMAGE_REV=0.1

View File

@@ -1,74 +1,49 @@
{
"name": "Python Dev",
// !! nezabudni nastaviť aj verziu python pre aplikáciu
"image": "docker.masara.eu/python:3.13-0.1-devcontainer",
// "build": {
// "dockerfile": "Dockerfile",
// "context": ".",
// "args": {
// "PYTHON_VERSION": "3.13"
// }
// },
"containerEnv": {
"PIP_INDEX_URL": "https://dv.masara.eu/repository/pypi-group/simple",
"PIP_ROOT_USER_ACTION": "ignore"
},
"remoteEnv": {
"DOCKER_BUILDKIT": "1",
// verzia python pre aplikáciu
"PYTHON_BASE": "3.13"
},
"workspaceFolder": "/workspace",
"workspaceMount": "source=${localWorkspaceFolder},target=/workspace,type=bind",
"remoteUser": "root",
"customizations": {
"vscode": {
"extensions": [
"ms-python.python",
"ms-python.vscode-pylance",
"ms-toolsai.jupyter",
"ms-python.black-formatter",
"ms-python.isort",
"ms-azuretools.vscode-docker"
],
"settings": {
"python.formatting.provider": "black",
"python.analysis.extraPaths": [
"${workspaceFolder}/.venv/lib/python3.13/site-packages",
"${workspaceFolder}/app"
],
"editor.formatOnSave": true,
// "python.defaultInterpreterPath": "/workspace/.venv/bin/python",
"python.terminal.activateEnvironment": true,
"python.defaultInterpreterPath": ".venv/bin/python",
// nechceme obnovovať staré porty z predchádzajúcich session
"remote.restoreForwardedPorts": false,
// auto-forward portov len na základe outputu, nie procesov
"remote.autoForwardPortsSource": "output",
// vypni auto-attach JS debug (často generuje ghost porty)
"debug.javascript.autoAttachFilter": "disabled"
}
}
},
"mounts": [
"type=bind,source=/var/run/docker.sock,target=/var/run/docker.sock"
],
"postCreateCommand": "bash .devcontainer/post_create.sh",
"forwardPorts": [
// 8000,
// 8080
],
"portsAttributes": {
// "8000": {
// "label": "App",
// "onAutoForward": "openBrowser"
// },
// "8080": {
// "label": "Debug",
// "onAutoForward": "silent"
// },
"*": {
"onAutoForward": "ignore"
}
}
}
{
"name": "Python Dev",
"dockerComposeFile": "docker-compose.yml",
"service": "dev",
"containerEnv": {
"PIP_INDEX_URL": "https://dv.masara.eu/repository/pypi-group/simple",
"PIP_ROOT_USER_ACTION": "ignore"
},
"remoteEnv": {
"DOCKER_BUILDKIT": "1"
},
"workspaceFolder": "/workspace",
"remoteUser": "root",
"customizations": {
"vscode": {
"extensions": [
"ms-python.python",
"ms-python.vscode-pylance",
"ms-toolsai.jupyter",
"ms-python.black-formatter",
"ms-python.isort",
"ms-azuretools.vscode-docker"
],
"settings": {
"python.formatting.provider": "black",
"python.analysis.extraPaths": [
"${workspaceFolder}/app"
],
"editor.formatOnSave": true,
"python.terminal.activateEnvironment": true,
"python.defaultInterpreterPath": ".venv/bin/python",
"remote.restoreForwardedPorts": false,
"remote.autoForwardPortsSource": "output",
"debug.javascript.autoAttachFilter": "disabled"
}
}
},
"mounts": [
"type=bind,source=/var/run/docker.sock,target=/var/run/docker.sock"
],
"postCreateCommand": "bash .devcontainer/post_create.sh",
"forwardPorts": [
],
"portsAttributes": {
"*": {
"onAutoForward": "ignore"
}
}
}

View File

@@ -0,0 +1,9 @@
services:
dev:
image: ${DEVCONTAINER_IMAGE_PULL_REPO}:${PYTHON_BASE}-${DEVCONTAINER_IMAGE_REV}-devcontainer
pull_policy: always
init: true
volumes:
- ..:/workspace:cached
environment:
PYTHON_BASE: ${PYTHON_BASE}

3
.gitignore vendored
View File

@@ -227,3 +227,6 @@ __marimo__/
# Built Visual Studio Code Extensions
*.vsix
# Track devcontainer version source of truth
!.devcontainer/.env

30
.vscode/tasks.json vendored Normal file
View File

@@ -0,0 +1,30 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "devcontainer: build image",
"type": "shell",
"command": "powershell",
"args": [
"-ExecutionPolicy",
"Bypass",
"-File",
"scripts/publish-devcontainer-image.ps1"
],
"problemMatcher": []
},
{
"label": "devcontainer: build and push image",
"type": "shell",
"command": "powershell",
"args": [
"-ExecutionPolicy",
"Bypass",
"-File",
"scripts/publish-devcontainer-image.ps1",
"-Push"
],
"problemMatcher": []
}
]
}

View File

@@ -1,21 +1,70 @@
# Template projektu pre Python 3.13
## Template obsahuje
* definíciu docker kontajnera s podporu docker a git
* python 3.13
* Nastavenie vscode
* .dockerignore a .gitignore
* Hello world aplikáciu
* vzorový Dockerfile pre aplikáciu
> Prvé otvorenie projektu môže trvať aj 10 min. Musí sa buildovať image.
## Vytvorenie devcontainera
Pri vytvorení devkontajnera sa automaticky:
* kontroluje, či je vytvorené venv, ak nie, vytvorí sa a aktualizuje pip
* aktualizujú sa závislosti
* nastaví sa git credential helper
# Python Project Template
Template pre Python projekt s Dev Container workflow, kde sa devcontainer image taha z registry a nebuildi sa pri kazdom otvoreni.
## Co projekt obsahuje
- devcontainer konfiguraciu (`.devcontainer/devcontainer.json`)
- compose definiciu pre devcontainer (`.devcontainer/docker-compose.yml`)
- centralne nastavenie verzie Pythonu a image tagov (`.devcontainer/.env`)
- skript na build/push devcontainer image (`scripts/publish-devcontainer-image.ps1`)
- VS Code tasky na build/push (`.vscode/tasks.json`)
- vzorovy `Dockerfile` pre aplikaciu (`Dockerfile`)
## Centralne nastavenie verzie a repo
Vsetko sa riadi cez `.devcontainer/.env`:
- `PYTHON_BASE` - verzia Pythonu pre devcontainer image
- `DEVCONTAINER_IMAGE_PULL_REPO` - odkial sa image taha pri otvoreni devcontainera (napr. `docker.masara.eu/python`)
- `DEVCONTAINER_IMAGE_PUSH_REPO` - kam sa image pushuje pri publikovani (napr. `repo.masara.eu/python`)
- `DEVCONTAINER_IMAGE_REV` - revizia image (napr. `0.1`)
## Build a publish devcontainer image
Predpoklady:
- Docker je nainstalovany a bezi
- mas pristup do push registry (`repo.masara.eu`)
### Cez VS Code task
1. Spusti task `devcontainer: build and push image`.
2. Task zavola skript `scripts/publish-devcontainer-image.ps1 -Push`.
### Cez terminal
```powershell
# iba build
powershell -ExecutionPolicy Bypass -File scripts/publish-devcontainer-image.ps1
# build + push
powershell -ExecutionPolicy Bypass -File scripts/publish-devcontainer-image.ps1 -Push
```
Poznamka:
- Ak `docker push` zlyha (napr. neautorizovany pristup), skript spravi fallback `docker login <registry>` a push zopakuje este raz.
## Pouzitie pri vytvoreni/otvoreni projektu
1. Naklonuj alebo vytvor projekt z tejto sablony.
2. Nastav hodnoty v `.devcontainer/.env` (hlavne `PYTHON_BASE`, pull/push repo, revision).
3. Ak menis base image (napr. Python verziu), publikuj novu verziu devcontainer image do push registry.
4. Otvor projekt vo VS Code a pouzi `Reopen in Container`.
Devcontainer sa spusti z image definovaneho v `.devcontainer/docker-compose.yml`:
- image sa taha z `DEVCONTAINER_IMAGE_PULL_REPO`
- workspace je pripojeny bind mountom do `/workspace`
- `postCreateCommand` vytvori `.venv` a nainstaluje zavislosti z `requirements.txt`
## Bezne scenare
- Chcem iba zmenit Python verziu:
1. Zmen `PYTHON_BASE` v `.devcontainer/.env`.
2. Spusti `devcontainer: build and push image`.
3. Vo VS Code daj `Rebuild/Reopen in Container`.
- Chcem zmenit iba aplikacny kod:
- Nerebuildi sa devcontainer image, staci reopen/restart kontajnera podla potreby.

View File

@@ -0,0 +1,74 @@
param(
[switch]$Push,
[string]$EnvFile = ".devcontainer/.env",
[string]$Dockerfile = ".devcontainer/Dockerfile"
)
$ErrorActionPreference = "Stop"
if (!(Test-Path $EnvFile)) {
throw "Env file not found: $EnvFile"
}
$vars = @{}
Get-Content $EnvFile | ForEach-Object {
$line = $_.Trim()
if ($line -and -not $line.StartsWith("#")) {
$pair = $line -split "=", 2
if ($pair.Count -eq 2) {
$vars[$pair[0].Trim()] = $pair[1].Trim()
}
}
}
$required = @("PYTHON_BASE", "DEVCONTAINER_IMAGE_PUSH_REPO", "DEVCONTAINER_IMAGE_REV")
foreach ($key in $required) {
if (-not $vars.ContainsKey($key) -or [string]::IsNullOrWhiteSpace($vars[$key])) {
throw "Missing required key '$key' in $EnvFile"
}
}
$pythonBase = $vars["PYTHON_BASE"]
$pushRepo = $vars["DEVCONTAINER_IMAGE_PUSH_REPO"]
$rev = $vars["DEVCONTAINER_IMAGE_REV"]
$versionTag = "${pushRepo}:${pythonBase}-${rev}-devcontainer"
$channelTag = "${pushRepo}:${pythonBase}-devcontainer"
$registry = ($pushRepo -split "/", 2)[0]
function Invoke-DockerPushWithLoginFallback {
param(
[Parameter(Mandatory = $true)]
[string]$Tag,
[Parameter(Mandatory = $true)]
[string]$Registry
)
Write-Host "Pushing $Tag"
docker push $Tag
if ($LASTEXITCODE -eq 0) {
return
}
Write-Warning "docker push failed for $Tag. Trying docker login to $Registry and retrying once."
docker login $Registry
if ($LASTEXITCODE -ne 0) {
throw "docker login failed for $Registry"
}
docker push $Tag
if ($LASTEXITCODE -ne 0) {
throw "docker push failed for $Tag after login fallback"
}
}
Write-Host "Building $versionTag"
docker build -f $Dockerfile --build-arg "PYTHON_VERSION=$pythonBase" -t $versionTag -t $channelTag .
if ($LASTEXITCODE -ne 0) {
throw "docker build failed"
}
if ($Push) {
Invoke-DockerPushWithLoginFallback -Tag $versionTag -Registry $registry
Invoke-DockerPushWithLoginFallback -Tag $channelTag -Registry $registry
}