# ?? api / player / admin ???????? tar # ??????????????????: # .\docs\docker\build-and-export-images.ps1 # .\docs\docker\build-and-export-images.ps1 -Service admin # .\docs\docker\build-and-export-images.ps1 -Tag v1.2.3 # .\docs\docker\build-and-export-images.ps1 -UseCache # .\docs\docker\build-and-export-images.ps1 -ExportOnly # # ???????????????????????????????????? # docs\docker\build-and-export-all-themes.bat param( [ValidateSet("all", "api", "player", "admin", "api-admin")] [string]$Service = "all", [string]$Tag = $env:IMAGE_TAG, [switch]$UseCache, [switch]$ExportOnly, [string]$Output = "" ) $ErrorActionPreference = "Stop" $Root = (Resolve-Path (Join-Path $PSScriptRoot "../..")).Path Set-Location $Root $ComposeFile = "docker-compose.prod.yml" $EnvFile = ".env.docker" $AllServices = @("api", "player", "admin") function Get-DefaultTag { "latest" } function Get-DefaultOutput { param([string]$Svc, [string]$ImageTag) if ($Svc -eq "all" -or $Svc -eq "api-admin") { return "thebet365-images-$ImageTag.tar" } return "thebet365-$Svc-$ImageTag.tar" } function Assert-ImageTag { param([string]$Value) if ($Value -notmatch '^[A-Za-z0-9_][A-Za-z0-9_.-]{0,127}$') { throw "?? tag ???? $Value" } } if (-not (Test-Path $ComposeFile)) { throw "????$ComposeFile?????? $Root?? } if (-not (Test-Path $EnvFile)) { if (Test-Path ".env.docker.example") { Write-Warning "????.env.docker????.env.docker.example????????????" $EnvFile = ".env.docker.example" } else { throw "????.env.docker ??.env.docker.example" } } if ([string]::IsNullOrWhiteSpace($Tag)) { $Tag = Get-DefaultTag } Assert-ImageTag $Tag $BuildServices = switch ($Service) { "all" { $AllServices } "api-admin" { @("api", "admin") } default { @($Service) } } $SaveImages = $BuildServices | ForEach-Object { "thebet365-${_}:${Tag}" } if ([string]::IsNullOrWhiteSpace($Output)) { $Output = Get-DefaultOutput -Svc $Service -ImageTag $Tag } if (-not $ExportOnly) { Write-Host "==> ????: $($BuildServices -join ', ') (tag: $Tag)" $buildArgs = @( "compose", "-f", $ComposeFile, "--env-file", $EnvFile, "build" ) if (-not $UseCache) { $buildArgs += "--no-cache" } $buildArgs += $BuildServices $oldImageTag = $env:IMAGE_TAG try { $env:IMAGE_TAG = $Tag & docker @buildArgs if ($LASTEXITCODE -ne 0) { throw "docker build ?????? $LASTEXITCODE" } } finally { $env:IMAGE_TAG = $oldImageTag } } $OutputPath = if ([System.IO.Path]::IsPathRooted($Output)) { $Output } else { Join-Path $Root $Output } Write-Host "==> ???? ($Service) -> $OutputPath" & docker save @SaveImages -o $OutputPath if ($LASTEXITCODE -ne 0) { throw "docker save ?????? $LASTEXITCODE" } $manifestPath = if ($OutputPath.EndsWith(".tar")) { $OutputPath.Substring(0, $OutputPath.Length - 4) + ".manifest.txt" } else { "$OutputPath.manifest.txt" } $gitCommit = "unknown" $gitDirty = "unknown" try { $gitCommit = (& git rev-parse HEAD 2>$null).Trim() & git diff --quiet $diffExit = $LASTEXITCODE & git diff --cached --quiet $cachedExit = $LASTEXITCODE $gitDirty = if ($diffExit -eq 0 -and $cachedExit -eq 0) { "false" } else { "true" } } catch {} $tarHash = (Get-FileHash -Algorithm SHA256 $OutputPath).Hash.ToLowerInvariant() $manifestLines = @( "tag=$Tag" "service=$Service" "built_at=$((Get-Date).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ"))" "git_commit=$gitCommit" "git_dirty=$gitDirty" "tar=$([System.IO.Path]::GetFileName($OutputPath))" "tar_sha256=$tarHash" ) foreach ($svc in $BuildServices) { $imageId = (& docker image inspect "thebet365-${svc}:${Tag}" --format "{{.Id}}").Trim() if ($Service -eq "all" -or $Service -eq "api-admin") { $manifestLines += "${svc}_image=thebet365-${svc}:${Tag}" $manifestLines += "${svc}_image_id=$imageId" } else { $manifestLines += "image=thebet365-${svc}:${Tag}" $manifestLines += "image_id=$imageId" } } $manifestLines | Set-Content -Encoding UTF8 $manifestPath $sizeMb = [math]::Round((Get-Item $OutputPath).Length / 1MB, 2) Write-Host "??: $OutputPath (${sizeMb} MB)" Write-Host "Manifest: $manifestPath" $recreate = switch ($Service) { "all" { "api player admin" } "api-admin" { "api admin" } default { $Service } } Write-Host @" ????????: docker load -i $([System.IO.Path]::GetFileName($OutputPath)) docker compose -f docker-compose.prod.yml --env-file .env.docker up -d --force-recreate $recreate "@