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,25 +1,15 @@
|
|||||||
{
|
{
|
||||||
"name": "Python Dev",
|
"name": "Python Dev",
|
||||||
// !! nezabudni nastaviť aj verziu python pre aplikáciu
|
"dockerComposeFile": "docker-compose.yml",
|
||||||
"image": "docker.masara.eu/python:3.13-0.1-devcontainer",
|
"service": "dev",
|
||||||
// "build": {
|
|
||||||
// "dockerfile": "Dockerfile",
|
|
||||||
// "context": ".",
|
|
||||||
// "args": {
|
|
||||||
// "PYTHON_VERSION": "3.13"
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
"containerEnv": {
|
"containerEnv": {
|
||||||
"PIP_INDEX_URL": "https://dv.masara.eu/repository/pypi-group/simple",
|
"PIP_INDEX_URL": "https://dv.masara.eu/repository/pypi-group/simple",
|
||||||
"PIP_ROOT_USER_ACTION": "ignore"
|
"PIP_ROOT_USER_ACTION": "ignore"
|
||||||
},
|
},
|
||||||
"remoteEnv": {
|
"remoteEnv": {
|
||||||
"DOCKER_BUILDKIT": "1",
|
"DOCKER_BUILDKIT": "1"
|
||||||
// verzia python pre aplikáciu
|
|
||||||
"PYTHON_BASE": "3.13"
|
|
||||||
},
|
},
|
||||||
"workspaceFolder": "/workspace",
|
"workspaceFolder": "/workspace",
|
||||||
"workspaceMount": "source=${localWorkspaceFolder},target=/workspace,type=bind",
|
|
||||||
"remoteUser": "root",
|
"remoteUser": "root",
|
||||||
"customizations": {
|
"customizations": {
|
||||||
"vscode": {
|
"vscode": {
|
||||||
@@ -34,18 +24,13 @@
|
|||||||
"settings": {
|
"settings": {
|
||||||
"python.formatting.provider": "black",
|
"python.formatting.provider": "black",
|
||||||
"python.analysis.extraPaths": [
|
"python.analysis.extraPaths": [
|
||||||
"${workspaceFolder}/.venv/lib/python3.13/site-packages",
|
"${workspaceFolder}/app"
|
||||||
"${workspaceFolder}/app"
|
],
|
||||||
],
|
|
||||||
"editor.formatOnSave": true,
|
"editor.formatOnSave": true,
|
||||||
// "python.defaultInterpreterPath": "/workspace/.venv/bin/python",
|
|
||||||
"python.terminal.activateEnvironment": true,
|
"python.terminal.activateEnvironment": true,
|
||||||
"python.defaultInterpreterPath": ".venv/bin/python",
|
"python.defaultInterpreterPath": ".venv/bin/python",
|
||||||
// nechceme obnovovať staré porty z predchádzajúcich session
|
|
||||||
"remote.restoreForwardedPorts": false,
|
"remote.restoreForwardedPorts": false,
|
||||||
// auto-forward portov len na základe outputu, nie procesov
|
|
||||||
"remote.autoForwardPortsSource": "output",
|
"remote.autoForwardPortsSource": "output",
|
||||||
// vypni auto-attach JS debug (často generuje ghost porty)
|
|
||||||
"debug.javascript.autoAttachFilter": "disabled"
|
"debug.javascript.autoAttachFilter": "disabled"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -55,18 +40,8 @@
|
|||||||
],
|
],
|
||||||
"postCreateCommand": "bash .devcontainer/post_create.sh",
|
"postCreateCommand": "bash .devcontainer/post_create.sh",
|
||||||
"forwardPorts": [
|
"forwardPorts": [
|
||||||
// 8000,
|
|
||||||
// 8080
|
|
||||||
],
|
],
|
||||||
"portsAttributes": {
|
"portsAttributes": {
|
||||||
// "8000": {
|
|
||||||
// "label": "App",
|
|
||||||
// "onAutoForward": "openBrowser"
|
|
||||||
// },
|
|
||||||
// "8080": {
|
|
||||||
// "label": "Debug",
|
|
||||||
// "onAutoForward": "silent"
|
|
||||||
// },
|
|
||||||
"*": {
|
"*": {
|
||||||
"onAutoForward": "ignore"
|
"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
|
# Built Visual Studio Code Extensions
|
||||||
*.vsix
|
*.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": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
77
README.md
77
README.md
@@ -1,21 +1,70 @@
|
|||||||
# Template projektu pre Python 3.13
|
# Python Project Template
|
||||||
|
|
||||||
## Template obsahuje
|
Template pre Python projekt s Dev Container workflow, kde sa devcontainer image taha z registry a nebuildi sa pri kazdom otvoreni.
|
||||||
|
|
||||||
* definíciu docker kontajnera s podporu docker a git
|
## Co projekt obsahuje
|
||||||
* 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.
|
- 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`)
|
||||||
|
|
||||||
## Vytvorenie devcontainera
|
## Centralne nastavenie verzie a repo
|
||||||
|
|
||||||
Pri vytvorení devkontajnera sa automaticky:
|
Vsetko sa riadi cez `.devcontainer/.env`:
|
||||||
|
|
||||||
* kontroluje, či je vytvorené venv, ak nie, vytvorí sa a aktualizuje pip
|
- `PYTHON_BASE` - verzia Pythonu pre devcontainer image
|
||||||
* aktualizujú sa závislosti
|
- `DEVCONTAINER_IMAGE_PULL_REPO` - odkial sa image taha pri otvoreni devcontainera (napr. `docker.masara.eu/python`)
|
||||||
* nastaví sa git credential helper
|
- `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