Compare commits
3
Commits
5598fa5156
...
179ad953cb
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
179ad953cb | ||
|
|
9d28d23e45 | ||
|
|
46178d915a |
@@ -14,6 +14,11 @@ Platforma Małopolskiego Hubu Innowacji Społecznych (MVP hackathonu).
|
||||
|
||||
- .NET SDK 10+
|
||||
- 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
|
||||
|
||||
@@ -39,19 +44,46 @@ node scripts/build.mjs # buduje całość (client + copy + backend)
|
||||
|
||||
## Docker
|
||||
|
||||
Szablon pobiera gotowy obraz z rejestru Gitea (pełna ścieżka), bez lokalnego
|
||||
buildowania:
|
||||
|
||||
```pwsh
|
||||
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)
|
||||
- Obraz: `tarninahub:0.0.1`
|
||||
- Obraz: `git.rtynski.pl/rtynski/hy2026:latest`
|
||||
|
||||
Wolumen hosta można wskazać zmienną `TARNINAHUB_PORT` (domyślnie `8080`).
|
||||
Plik `docker-compose.yaml.example` jest szablonem; `docker-compose.yaml` możesz
|
||||
Port hosta można wskazać zmienną `TARNINAHUB_PORT` (domyślnie `8075`), a wersję
|
||||
obrazu zmienną `APP_VERSION` (domyślnie `latest`). Plik
|
||||
`docker-compose.yaml.example` jest szablonem; `docker-compose.yaml` możesz
|
||||
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
|
||||
|
||||
```
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ services:
|
||||
# RocksDB zapisuje do bind-mountu ./data; root upraszcza uprawnienia (MVP).
|
||||
user: "0:0"
|
||||
ports:
|
||||
- "${TARNINAHUB_PORT:-8080}:8080"
|
||||
- "${TARNINAHUB_PORT:-8075}:8080"
|
||||
environment:
|
||||
ASPNETCORE_ENVIRONMENT: Production
|
||||
ASPNETCORE_URLS: http://+:8080
|
||||
|
||||
+20
-10
@@ -2,29 +2,29 @@
|
||||
#
|
||||
# Użycie:
|
||||
# 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)
|
||||
|
||||
name: tarninahub
|
||||
|
||||
services:
|
||||
app:
|
||||
# Obraz budowany lokalnie z Dockerfile (multi-stage: klient Vue + backend .NET).
|
||||
image: tarninahub:${APP_VERSION:-0.0.1}
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
args:
|
||||
APP_VERSION: ${APP_VERSION:-0.0.1}
|
||||
# Obraz z rejestru Gitea — pobierany przez `docker compose pull`.
|
||||
# `latest` domyślnie; konkretną wersję ustaw przez APP_VERSION, np. 0.0.1.
|
||||
image: git.rtynski.pl/rtynski/hy2026:${APP_VERSION:-latest}
|
||||
container_name: tarninahub
|
||||
restart: unless-stopped
|
||||
# RocksDB zapisuje do bind-mountu ./data; root upraszcza uprawnienia (MVP).
|
||||
# W produkcji użyj named volume albo dopasuj właściciela katalogu ./data.
|
||||
user: "0:0"
|
||||
ports:
|
||||
- "${TARNINAHUB_PORT:-8080}:8080"
|
||||
- "${TARNINAHUB_PORT:-8075}:8080"
|
||||
environment:
|
||||
ASPNETCORE_ENVIRONMENT: Production
|
||||
ASPNETCORE_URLS: http://+:8080
|
||||
@@ -40,9 +40,19 @@ services:
|
||||
volumes:
|
||||
# Jedyny volumen aplikacji — trwałe dane (SurrealDB / RocksDB).
|
||||
- ./data:/app/data
|
||||
# Podłączenie do zewnętrznej sieci (odkomentuj razem z blokiem `networks`).
|
||||
# networks:
|
||||
# - ovh_net
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-fsS", "http://localhost:8080/api/health"]
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
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
|
||||
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user