部署优化
This commit is contained in:
@@ -1,13 +1,15 @@
|
||||
# 构建 api / player / admin 生产镜像并导出为 tar
|
||||
# 用法(在项目根目录或本目录执行均可):
|
||||
# .\docs\docker\build-and-export-images.ps1
|
||||
# .\docs\docker\build-and-export-images.ps1 -Tag v1.2.3
|
||||
# .\build-and-export-images.ps1 -UseCache
|
||||
# .\build-and-export-images.ps1 -ExportOnly
|
||||
|
||||
param(
|
||||
[string]$Tag = $env:IMAGE_TAG,
|
||||
[switch]$UseCache,
|
||||
[switch]$ExportOnly,
|
||||
[string]$Output = "thebet365-images.tar"
|
||||
[string]$Output = ""
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
@@ -18,6 +20,21 @@ $ComposeFile = "docker-compose.prod.yml"
|
||||
$EnvFile = ".env.docker"
|
||||
$Services = @("api", "player", "admin")
|
||||
|
||||
function Get-DefaultTag {
|
||||
try {
|
||||
$short = (& git rev-parse --short HEAD 2>$null).Trim()
|
||||
if ($short) { return $short }
|
||||
} catch {}
|
||||
return Get-Date -Format "yyyyMMdd-HHmmss"
|
||||
}
|
||||
|
||||
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)"
|
||||
}
|
||||
@@ -31,8 +48,16 @@ if (-not (Test-Path $EnvFile)) {
|
||||
}
|
||||
}
|
||||
|
||||
if ([string]::IsNullOrWhiteSpace($Tag)) {
|
||||
$Tag = Get-DefaultTag
|
||||
}
|
||||
Assert-ImageTag $Tag
|
||||
if ([string]::IsNullOrWhiteSpace($Output)) {
|
||||
$Output = "thebet365-images-$Tag.tar"
|
||||
}
|
||||
|
||||
if (-not $ExportOnly) {
|
||||
Write-Host "==> 构建镜像: $($Services -join ', ')"
|
||||
Write-Host "==> 构建镜像: $($Services -join ', ') (tag: $Tag)"
|
||||
$buildArgs = @(
|
||||
"compose", "-f", $ComposeFile, "--env-file", $EnvFile, "build"
|
||||
)
|
||||
@@ -40,28 +65,72 @@ if (-not $ExportOnly) {
|
||||
$buildArgs += "--no-cache"
|
||||
}
|
||||
$buildArgs += $Services
|
||||
& docker @buildArgs
|
||||
if ($LASTEXITCODE -ne 0) { throw "docker build 失败,退出码 $LASTEXITCODE" }
|
||||
$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 "==> 导出镜像 -> $OutputPath"
|
||||
& docker save `
|
||||
thebet365-api:latest `
|
||||
thebet365-player:latest `
|
||||
thebet365-admin:latest `
|
||||
"thebet365-api:${Tag}" `
|
||||
"thebet365-player:${Tag}" `
|
||||
"thebet365-admin:${Tag}" `
|
||||
-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()
|
||||
$apiImageId = (& docker image inspect "thebet365-api:${Tag}" --format "{{.Id}}").Trim()
|
||||
$playerImageId = (& docker image inspect "thebet365-player:${Tag}" --format "{{.Id}}").Trim()
|
||||
$adminImageId = (& docker image inspect "thebet365-admin:${Tag}" --format "{{.Id}}").Trim()
|
||||
|
||||
@(
|
||||
"tag=$Tag"
|
||||
"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"
|
||||
"api_image=thebet365-api:${Tag}"
|
||||
"api_image_id=$apiImageId"
|
||||
"player_image=thebet365-player:${Tag}"
|
||||
"player_image_id=$playerImageId"
|
||||
"admin_image=thebet365-admin:${Tag}"
|
||||
"admin_image_id=$adminImageId"
|
||||
) | Set-Content -Encoding UTF8 $manifestPath
|
||||
|
||||
$sizeMb = [math]::Round((Get-Item $OutputPath).Length / 1MB, 2)
|
||||
Write-Host "完成: $OutputPath (${sizeMb} MB)"
|
||||
Write-Host "Manifest: $manifestPath"
|
||||
|
||||
Write-Host @"
|
||||
|
||||
服务器首次部署:
|
||||
./scripts/deploy-first.sh --images thebet365-images.tar
|
||||
./scripts/deploy-first.sh --images $([System.IO.Path]::GetFileName($OutputPath)) --tag $Tag
|
||||
|
||||
服务器后续更新:
|
||||
./scripts/deploy-update.sh --images thebet365-images.tar
|
||||
./scripts/deploy-update.sh --images $([System.IO.Path]::GetFileName($OutputPath)) --tag $Tag
|
||||
"@
|
||||
|
||||
Reference in New Issue
Block a user