Files
smartmate/deploy/docker-pack.ps1
2026-05-09 17:51:04 +08:00

178 lines
6.0 KiB
PowerShell

param(
[string]$AppTag = "latest",
[string]$OutputDir = ".docker-bundles",
[string]$PlanFile = "",
[string]$Services = "",
[switch]$IncludeInfra,
[switch]$SkipBackend,
[switch]$SkipFrontend,
[string]$BackendImage = "",
[string]$FrontendImage = ""
)
$ErrorActionPreference = "Stop"
Set-StrictMode -Version Latest
. (Join-Path $PSScriptRoot "service-catalog.ps1")
function Read-ReleasePlan {
param([string]$Path)
$values = @{}
if ([string]::IsNullOrWhiteSpace($Path)) {
return $values
}
if (-not (Test-Path -LiteralPath $Path)) {
throw ("release plan not found: {0}" -f $Path)
}
foreach ($line in Get-Content -LiteralPath $Path -Encoding UTF8) {
if ([string]::IsNullOrWhiteSpace($line) -or $line.TrimStart().StartsWith("#")) {
continue
}
$parts = $line -split "=", 2
if ($parts.Count -ne 2) {
throw ("invalid release plan line: {0}" -f $line)
}
$values[$parts[0].Trim()] = $parts[1].Trim()
}
return $values
}
function Get-ImageRefForService {
param(
[string]$Service,
[hashtable]$Plan,
[string]$Tag
)
$imageEnv = Get-SmartFlowImageEnvForService -Service $Service
if ($Plan.ContainsKey($imageEnv) -and -not [string]::IsNullOrWhiteSpace($Plan[$imageEnv])) {
return $Plan[$imageEnv]
}
return Get-SmartFlowDefaultImageForService -Service $Service -AppTag $Tag
}
function Invoke-Docker {
param([string[]]$Arguments)
& docker @Arguments
if ($LASTEXITCODE -ne 0) {
throw ("docker command failed: docker {0}" -f ($Arguments -join " "))
}
}
$repoRoot = Split-Path -Parent $PSScriptRoot
$bundleDir = Join-Path $repoRoot $OutputDir
$plan = Read-ReleasePlan -Path $PlanFile
if ($plan.ContainsKey("SMARTFLOW_APP_TAG") -and -not [string]::IsNullOrWhiteSpace($plan["SMARTFLOW_APP_TAG"])) {
$AppTag = $plan["SMARTFLOW_APP_TAG"]
}
if ([string]::IsNullOrWhiteSpace($Services) -and $plan.ContainsKey("SMARTFLOW_RESTART_SERVICES")) {
$Services = $plan["SMARTFLOW_RESTART_SERVICES"]
}
$selectedServices = @()
if (-not [string]::IsNullOrWhiteSpace($Services)) {
$selectedServices = @($Services.Split(",") | Where-Object { -not [string]::IsNullOrWhiteSpace($_) } | ForEach-Object { $_.Trim() })
} elseif ([string]::IsNullOrWhiteSpace($PlanFile)) {
if (-not $SkipBackend) {
$selectedServices += @(Get-SmartFlowBackendServices)
}
if (-not $SkipFrontend) {
$selectedServices += "frontend"
}
}
New-Item -ItemType Directory -Force -Path $bundleDir | Out-Null
$appBundlePath = Join-Path $bundleDir ("smartflow-app-{0}.tar" -f $AppTag)
$infraBundlePath = Join-Path $bundleDir ("smartflow-infra-{0}.tar" -f $AppTag)
if (Test-Path -LiteralPath $appBundlePath) {
Remove-Item -LiteralPath $appBundlePath -Force
}
$appImages = @()
foreach ($service in $selectedServices) {
if ($service -eq "frontend") {
if ($SkipFrontend) {
continue
}
$imageRef = Get-ImageRefForService -Service $service -Plan $plan -Tag $AppTag
Write-Host "==> Build frontend image $imageRef"
Invoke-Docker -Arguments @(
"build", "--platform", "linux/amd64",
"-f", (Join-Path $repoRoot "frontend\Dockerfile"),
"-t", $imageRef,
(Join-Path $repoRoot "frontend")
)
$appImages += $imageRef
continue
}
if ($SkipBackend) {
continue
}
if (-not (Test-SmartFlowBackendService -Service $service)) {
throw ("unknown backend release service: {0}" -f $service)
}
$imageRef = Get-ImageRefForService -Service $service -Plan $plan -Tag $AppTag
Write-Host "==> Build backend service image $imageRef"
Invoke-Docker -Arguments @(
"build", "--platform", "linux/amd64",
"--target", "runtime-service",
"--build-arg", ("SERVICE={0}" -f $service),
"-f", (Join-Path $repoRoot "backend\Dockerfile"),
"-t", $imageRef,
(Join-Path $repoRoot "backend")
)
$appImages += $imageRef
}
if ($appImages.Count -gt 0) {
Write-Host "==> Export app bundle to $appBundlePath"
Invoke-Docker -Arguments (@("save", "-o", $appBundlePath) + $appImages)
} else {
Write-Host "==> Skip app bundle export because no application image is selected"
}
if (-not $IncludeInfra) {
Write-Host "==> Done."
return
}
$infraImages = @()
if ([string]::IsNullOrWhiteSpace($env:SMARTFLOW_MYSQL_IMAGE)) { $infraImages += "mysql:8.0" } else { $infraImages += $env:SMARTFLOW_MYSQL_IMAGE }
if ([string]::IsNullOrWhiteSpace($env:SMARTFLOW_REDIS_IMAGE)) { $infraImages += "redis:7" } else { $infraImages += $env:SMARTFLOW_REDIS_IMAGE }
if ([string]::IsNullOrWhiteSpace($env:SMARTFLOW_KAFKA_IMAGE)) { $infraImages += "apache/kafka:3.7.2" } else { $infraImages += $env:SMARTFLOW_KAFKA_IMAGE }
if ([string]::IsNullOrWhiteSpace($env:SMARTFLOW_ETCD_IMAGE)) { $infraImages += "quay.io/coreos/etcd:v3.5.5" } else { $infraImages += $env:SMARTFLOW_ETCD_IMAGE }
if ([string]::IsNullOrWhiteSpace($env:SMARTFLOW_MINIO_IMAGE)) { $infraImages += "minio/minio:RELEASE.2023-03-20T20-16-18Z" } else { $infraImages += $env:SMARTFLOW_MINIO_IMAGE }
if ([string]::IsNullOrWhiteSpace($env:SMARTFLOW_MILVUS_IMAGE)) { $infraImages += "milvusdb/milvus:v2.4.4" } else { $infraImages += $env:SMARTFLOW_MILVUS_IMAGE }
if ([string]::IsNullOrWhiteSpace($env:SMARTFLOW_ATTU_IMAGE)) { $infraImages += "zilliz/attu:v2.4.3" } else { $infraImages += $env:SMARTFLOW_ATTU_IMAGE }
foreach ($imageRef in $infraImages) {
& docker image inspect $imageRef | Out-Null
if ($LASTEXITCODE -eq 0) {
Write-Host "==> Reuse local infra image $imageRef"
continue
}
Write-Host "==> Pull infra image $imageRef"
Invoke-Docker -Arguments @("pull", $imageRef)
}
if (Test-Path -LiteralPath $infraBundlePath) {
Remove-Item -LiteralPath $infraBundlePath -Force
}
Write-Host "==> Export infra bundle to $infraBundlePath"
Invoke-Docker -Arguments (@("save", "-o", $infraBundlePath) + $infraImages)
Write-Host "==> Done."