buildovanie cez task a verzia na jednom mieste
This commit is contained in:
4
.devcontainer/.env
Normal file
4
.devcontainer/.env
Normal 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
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
9
.devcontainer/docker-compose.yml
Normal file
9
.devcontainer/docker-compose.yml
Normal 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
3
.gitignore
vendored
@@ -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
30
.vscode/tasks.json
vendored
Normal 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": []
|
||||
}
|
||||
]
|
||||
}
|
||||
91
README.md
91
README.md
@@ -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.
|
||||
|
||||
74
scripts/publish-devcontainer-image.ps1
Normal file
74
scripts/publish-devcontainer-image.ps1
Normal 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
|
||||
}
|
||||
Reference in New Issue
Block a user