Compare commits

..
3 Commits
Author SHA1 Message Date
Rafał Tyński 179ad953cb docs(readme): document registry pull workflow and image publish script 2026-10-03 21:16:20 +02:00
Rafał Tyński 9d28d23e45 build(docker): pull image from Gitea registry in compose template
Switch the compose example from local build to pulling the full registry path git.rtynski.pl/rtynski/hy2026, default the host port to 8075 and add a commented external ovh_net network.
2026-10-03 21:16:11 +02:00
Rafał Tyński 46178d915a build(scripts): add Docker image publish script for Gitea registry 2026-10-03 21:16:08 +02:00
4 changed files with 200 additions and 16 deletions
+37 -5
View File
@@ -14,6 +14,11 @@ Platforma Małopolskiego Hubu Innowacji Społecznych (MVP hackathonu).
- .NET SDK 10+ - .NET SDK 10+
- Node.js 22+ (npm) - Node.js 22+ (npm)
- PowerShell Core 7+ (`pwsh`) — wymagany do uruchomienia `scripts/*.ps1`.
Windows nie kojarzy domyślnie plików `.ps1`, dlatego skrypty uruchamiaj przez
`pwsh` (np. `pwsh ./scripts/docker-push.ps1`), a nie przez dwuklik / samo
`./scripts/docker-push.ps1`. Instalacja: https://aka.ms/powershell
## Praca lokalna ## Praca lokalna
@@ -39,19 +44,46 @@ node scripts/build.mjs # buduje całość (client + copy + backend)
## Docker ## Docker
Szablon pobiera gotowy obraz z rejestru Gitea (pełna ścieżka), bez lokalnego
buildowania:
```pwsh ```pwsh
cp docker-compose.yaml.example docker-compose.yaml cp docker-compose.yaml.example docker-compose.yaml
docker compose up --build docker compose pull
docker compose up -d
``` ```
- Aplikacja: http://localhost:8080 - Aplikacja: http://localhost:8075
- Dane: `./data` (bind mount, trwałe — SurrealDB embedded RocksDB) - Dane: `./data` (bind mount, trwałe — SurrealDB embedded RocksDB)
- Obraz: `tarninahub:0.0.1` - Obraz: `git.rtynski.pl/rtynski/hy2026:latest`
Wolumen hosta można wskazać zmienną `TARNINAHUB_PORT` (domyślnie `8080`). Port hosta można wskazać zmienną `TARNINAHUB_PORT` (domyślnie `8075`), a wersję
Plik `docker-compose.yaml.example` jest szablonem; `docker-compose.yaml` możesz obrazu zmienną `APP_VERSION` (domyślnie `latest`). Plik
`docker-compose.yaml.example` jest szablonem; `docker-compose.yaml` możesz
dostosować lokalnie. dostosować lokalnie.
### Publikacja obrazu do Gitea
Token dostępu utworzysz w Gitea:
- https://git.rtynski.pl/user/settings/applications
- **Generate New Token** → zakres **`write:package`** (wystarcza do pushu obrazu).
Wymagany **PowerShell Core 7+** (`pwsh`). Windows nie uruchamia domyślnie
plików `.ps1`, więc skrypt wywołaj jawnie przez `pwsh`:
```pwsh
$env:GITEA_USER = "rtynski"; $env:GITEA_TOKEN = "<token>"
pwsh ./scripts/docker-push.ps1
```
Skrypt najpierw sprawdza połączenie z demonem Docker i rejestrem, czyta wersję z
`backend/TarninaHub.csproj`. Jeśli dana wersja jest już wypchnięta do rejestru,
kończy pracę z czerwonym komunikatem; w przeciwnym razie buduje frontend,
kopiuje go do `backend/wwwroot`, buduje backend, buduje obraz Docker i wypycha go
do `git.rtynski.pl/rtynski/hy2026` jako `<wersja>` oraz `latest`. Nadpisanie
sprawdzenia: `-Force`.
## Struktura ## Struktura
``` ```
+1 -1
View File
@@ -13,7 +13,7 @@ services:
# RocksDB zapisuje do bind-mountu ./data; root upraszcza uprawnienia (MVP). # RocksDB zapisuje do bind-mountu ./data; root upraszcza uprawnienia (MVP).
user: "0:0" user: "0:0"
ports: ports:
- "${TARNINAHUB_PORT:-8080}:8080" - "${TARNINAHUB_PORT:-8075}:8080"
environment: environment:
ASPNETCORE_ENVIRONMENT: Production ASPNETCORE_ENVIRONMENT: Production
ASPNETCORE_URLS: http://+:8080 ASPNETCORE_URLS: http://+:8080
+20 -10
View File
@@ -2,29 +2,29 @@
# #
# Użycie: # Użycie:
# cp docker-compose.yaml.example docker-compose.yaml # cp docker-compose.yaml.example docker-compose.yaml
# docker compose up --build # docker compose pull
# docker compose up -d
# #
# Aplikacja: http://localhost:8080 # Obraz pobierany z rejestru Gitea (pełna ścieżka):
# git.rtynski.pl/rtynski/hy2026:<wersja>
#
# Aplikacja: http://localhost:8075
# Dane: ./data (bind mount, trwałe, SurrealDB embedded RocksDB) # Dane: ./data (bind mount, trwałe, SurrealDB embedded RocksDB)
name: tarninahub name: tarninahub
services: services:
app: app:
# Obraz budowany lokalnie z Dockerfile (multi-stage: klient Vue + backend .NET). # Obraz z rejestru Gitea — pobierany przez `docker compose pull`.
image: tarninahub:${APP_VERSION:-0.0.1} # `latest` domyślnie; konkretną wersję ustaw przez APP_VERSION, np. 0.0.1.
build: image: git.rtynski.pl/rtynski/hy2026:${APP_VERSION:-latest}
context: .
dockerfile: Dockerfile
args:
APP_VERSION: ${APP_VERSION:-0.0.1}
container_name: tarninahub container_name: tarninahub
restart: unless-stopped restart: unless-stopped
# RocksDB zapisuje do bind-mountu ./data; root upraszcza uprawnienia (MVP). # RocksDB zapisuje do bind-mountu ./data; root upraszcza uprawnienia (MVP).
# W produkcji użyj named volume albo dopasuj właściciela katalogu ./data. # W produkcji użyj named volume albo dopasuj właściciela katalogu ./data.
user: "0:0" user: "0:0"
ports: ports:
- "${TARNINAHUB_PORT:-8080}:8080" - "${TARNINAHUB_PORT:-8075}:8080"
environment: environment:
ASPNETCORE_ENVIRONMENT: Production ASPNETCORE_ENVIRONMENT: Production
ASPNETCORE_URLS: http://+:8080 ASPNETCORE_URLS: http://+:8080
@@ -40,9 +40,19 @@ services:
volumes: volumes:
# Jedyny volumen aplikacji — trwałe dane (SurrealDB / RocksDB). # Jedyny volumen aplikacji — trwałe dane (SurrealDB / RocksDB).
- ./data:/app/data - ./data:/app/data
# Podłączenie do zewnętrznej sieci (odkomentuj razem z blokiem `networks`).
# networks:
# - ovh_net
healthcheck: healthcheck:
test: ["CMD", "curl", "-fsS", "http://localhost:8080/api/health"] test: ["CMD", "curl", "-fsS", "http://localhost:8080/api/health"]
interval: 30s interval: 30s
timeout: 5s timeout: 5s
retries: 3 retries: 3
start_period: 20s start_period: 20s
# Zewnętrzna sieć (opcjonalnie) — odkomentuj, aby podłączyć usługę do
# istniejącej sieci hosta. Pamiętaj też odkomentować `networks:` w `app`.
# networks:
# ovh_net:
# external:
# name: ovh_net
+142
View File
@@ -0,0 +1,142 @@
<#
.SYNOPSIS
Buduje i publikuje obraz aplikacji w rejestrze kontenerów Gitea.
.DESCRIPTION
Wersja czytana jest z backend/TarninaHub.csproj (<Version>).
Krok 0 sprawdza połączenie z demonem Docker i dostępność rejestru Gitea.
Jeżeli obraz w tej wersji jest już wypchnięty do rejestru, skrypt wypisuje
czerwony komunikat i kończy pracę. W przeciwnym razie wykonuje po kolei:
0. sprawdzenie połączenia (demon Docker + rejestr),
1. odczyt wersji z backendu,
2. logowanie do rejestru,
3. sprawdzenie, czy wersja już istnieje,
4. build frontendu, kopiowanie i build backendu,
5. build obrazu Docker,
6. push obrazu jako <version> oraz :latest.
Dane logowania pobierane są ze zmiennych środowiskowych GITEA_USER oraz
GITEA_TOKEN (preferowany) lub GITEA_PASSWORD; jeśli ich brak, używany jest
`docker login` (interaktywnie). Token utworzysz na stronie:
https://<adres-gitea>/user/settings/applications (zakres: write:package)
.EXAMPLE
pwsh ./scripts/docker-push.ps1
.EXAMPLE
$env:GITEA_USER = "rtynski"; $env:GITEA_TOKEN = "xxx"
pwsh ./scripts/docker-push.ps1 -Force
#>
param(
[string]$Registry = "git.rtynski.pl",
[string]$Owner = "rtynski",
[string]$Repo = "hy2026",
[string]$ProjectFile = "backend/TarninaHub.csproj",
[string]$SolutionFile = "TarninaHub.slnx",
[string]$Username = $env:GITEA_USER,
[string]$Token = $env:GITEA_TOKEN,
[string]$Password = $env:GITEA_PASSWORD,
[switch]$Force
)
$ErrorActionPreference = "Stop"
$root = Split-Path -Parent $PSScriptRoot
$image = "$Registry/$Owner/$Repo"
function Invoke-Step {
param([string]$Label, [scriptblock]$Action)
Write-Host "`n> $Label" -ForegroundColor Cyan
Push-Location $root
try { & $Action } finally { Pop-Location }
if ($LASTEXITCODE -ne 0) { throw "Krok nie powiódł się: $Label" }
}
function Test-TcpConnection {
param([string]$HostName, [int]$Port, [int]$TimeoutMs = 5000)
$client = [System.Net.Sockets.TcpClient]::new()
try {
$task = $client.ConnectAsync($HostName, $Port)
return $task.Wait($TimeoutMs) -and $client.Connected
} catch {
return $false
} finally {
$client.Dispose()
}
}
# 0. Sprawdzenie połączenia (demon Docker + dostępność rejestru)
Write-Host "Krok 0: sprawdzanie połączenia..." -ForegroundColor Cyan
if (-not (Get-Command docker -ErrorAction SilentlyContinue)) {
throw "Nie znaleziono 'docker' w PATH."
}
docker info *> $null
if ($LASTEXITCODE -ne 0) {
throw "Brak połączenia z demonem Docker. Uruchom Docker Desktop."
}
if (-not (Test-TcpConnection -HostName $Registry -Port 443)) {
throw "Nie mogę połączyć się z rejestrem ${Registry}:443. Sprawdź sieć/adres."
}
Write-Host "Połączenie OK (Docker + ${Registry}:443)." -ForegroundColor Green
# 1. Wersja z backendu
$projectPath = Join-Path $root $ProjectFile
if (-not (Test-Path -LiteralPath $projectPath)) {
throw "Nie znaleziono pliku projektu: $projectPath"
}
$xml = [xml](Get-Content -LiteralPath $projectPath -Raw)
$versionNode = $xml.SelectSingleNode('/Project/PropertyGroup/Version')
if (-not $versionNode -or [string]::IsNullOrWhiteSpace($versionNode.InnerText)) {
throw "Brak <Version> w $ProjectFile."
}
$version = $versionNode.InnerText.Trim()
$versionTag = "${image}:$version"
$latestTag = "${image}:latest"
Write-Host "Wersja backendu: $version"
# 2. Logowanie do rejestru (potrzebne do sprawdzenia i push)
$secret = if ($Token) { $Token } elseif ($Password) { $Password } else { $null }
if ($Username -and $secret) {
Write-Host "Loguję do $Registry jako $Username..."
$secret | docker login $Registry --username $Username --password-stdin
} else {
Write-Host "Loguję do $Registry (interaktywnie)..."
Write-Host "Jeśli nie widzisz promptu, wpisz nazwę użytkownika i naciśnij Enter." -ForegroundColor Yellow
docker login $Registry
}
if ($LASTEXITCODE -ne 0) { throw "docker login nie powiodło się." }
# 3. Sprawdzenie, czy wersja została już wypchnięta
docker manifest inspect $versionTag *> $null
$alreadyPushed = ($LASTEXITCODE -eq 0)
if ($alreadyPushed -and -not $Force) {
Write-Host "`nObraz $versionTag jest już wypchnięty do rejestru." -ForegroundColor Red
Write-Host "Zmien <Version> w $ProjectFile lub użyj -Force." -ForegroundColor Red
exit 1
}
if ($alreadyPushed) {
Write-Host "Obraz $versionTag już istnieje, ale -Force pomija sprawdzenie." -ForegroundColor Yellow
}
# 4. Build frontendu, kopiowanie i build backendu
Invoke-Step "Build frontendu (Vite)" { npm --prefix client run build }
Invoke-Step "Kopiowanie client/dist -> backend/wwwroot" { node scripts/copy-client.mjs }
Invoke-Step "Build backendu (.NET)" { dotnet build $SolutionFile --configuration Release }
# 5. Build obrazu Docker
Invoke-Step "Build obrazu Docker ($versionTag)" {
docker build --build-arg "APP_VERSION=$version" -f Dockerfile -t $versionTag -t $latestTag .
}
# 6. Push wersji oraz latest
Invoke-Step "Push $versionTag" { docker push $versionTag }
Invoke-Step "Push $latestTag" { docker push $latestTag }
Write-Host "`nGotowe: $versionTag oraz $latestTag" -ForegroundColor Green