部署脚本:regctl 被安全软件拦截时自动降级为 docker 直传
This commit is contained in:
parent
0b1de5b3ce
commit
79158103de
@ -119,7 +119,15 @@ git pull --ff-only
|
||||
13. 开发机、服务器 Docker 和服务器 Registry 均仅保留当前和上一个本项目版本;
|
||||
14. 清理 7 天前的本项目构建缓存,并将总量压到最多 3GB。
|
||||
|
||||
### 5.1 程序资源与业务文件的固定边界
|
||||
### 5.1 安全软件拦截 regctl 时的降级
|
||||
|
||||
第 6 步默认用项目专用 `regctl`(未签名)把 BuildKit 原生 OCI 分层包推入服务器本机 Registry。少数开发机的 360 安全卫士、金山毒霸等安全软件会拦截未签名程序,表现为 `regctl-v0.11.5.exe` 启动即报“拒绝访问”。
|
||||
|
||||
- 脚本会自动降级:regctl 无法运行或连续上传失败时,改用 `docker save` 全量包经 `scp` 上传,在服务器上 `docker load`、推入本机 Registry,再执行同一个 `activate-incremental-release.sh`(回滚、健康检查、双版本保留和旧层回收逻辑不变)。降级只增加传输量,功能与发布结果一致。
|
||||
- 也可以在受拦截的开发机上显式跳过 regctl:`.\scripts\deploy-from-workstation.ps1 -SkipRegctl`。
|
||||
- 建议在这类开发机上把 `%LOCALAPPDATA%\CaiWuXiTong\tools` 加入安全软件信任区,以恢复只上传变化层的增量方式。
|
||||
|
||||
### 5.2 程序资源与业务文件的固定边界
|
||||
|
||||
- 程序资源:JavaScript、CSS、字体、PWA 图标和仓库图片。它们只随 Git 提交和应用镜像发布,浏览器从当前应用域名加载。
|
||||
- 业务文件:用户上传的图片、票据、PDF、表格和附件。生产环境统一写入项目唯一的私有七牛桶,本地开发默认仍写入本机 `storage/app/uploads`。
|
||||
|
||||
@ -21,7 +21,8 @@ param(
|
||||
[switch]$BootstrapServer,
|
||||
[switch]$ConfigureDingTalkCallback,
|
||||
[switch]$AllowNonMain,
|
||||
[switch]$AllowMigrations
|
||||
[switch]$AllowMigrations,
|
||||
[switch]$SkipRegctl
|
||||
)
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
@ -504,6 +505,8 @@ try {
|
||||
|
||||
# docker save 导出未压缩层,每次导入重新压缩会改变摘要,导致 Registry 无法复用。
|
||||
# 直接导出 BuildKit 原生 OCI 层,让未变化层的压缩摘要跨版本保持稳定。
|
||||
# 注意:360/金山等安全软件会拦截未签名的 regctl(启动即“拒绝访问”),
|
||||
# 这类开发机可以用 -SkipRegctl,或者交给下面的自动降级改走 docker 直传。
|
||||
Invoke-Native {
|
||||
docker buildx build `
|
||||
--builder $BuilderName `
|
||||
@ -518,49 +521,89 @@ try {
|
||||
--file deploy/Dockerfile `
|
||||
.
|
||||
} '导出稳定分层的 OCI 应用镜像失败。'
|
||||
$regctlPath = Get-RegctlPath
|
||||
$localRegistryPort = Get-AvailableLocalPort
|
||||
$sshTunnel = Start-RegistryTunnel -LocalPort $localRegistryPort
|
||||
$registryImage = "127.0.0.1:${localRegistryPort}/caiwuxitong/app:$imageTag"
|
||||
$serverRegistryImage = "127.0.0.1:5000/caiwuxitong/app:$imageTag"
|
||||
|
||||
$beforeBytesOutput = @(& ssh @sshOptions $sshTarget "du -sb /var/lib/docker-registry 2>/dev/null | cut -f1")
|
||||
$beforeBytes = [long](($beforeBytesOutput -join '').Trim())
|
||||
$uploadTimer = [Diagnostics.Stopwatch]::StartNew()
|
||||
$uploadSucceeded = $false
|
||||
for ($uploadAttempt = 1; $uploadAttempt -le 2; $uploadAttempt++) {
|
||||
if ($uploadAttempt -gt 1) {
|
||||
if ($sshTunnel) {
|
||||
if (-not $sshTunnel.HasExited) {
|
||||
$sshTunnel.Kill()
|
||||
$sshTunnel.WaitForExit()
|
||||
}
|
||||
$sshTunnel.Dispose()
|
||||
}
|
||||
|
||||
if (-not $SkipRegctl) {
|
||||
try {
|
||||
$regctlPath = Get-RegctlPath
|
||||
$localRegistryPort = Get-AvailableLocalPort
|
||||
$sshTunnel = Start-RegistryTunnel -LocalPort $localRegistryPort
|
||||
$registryImage = "127.0.0.1:${localRegistryPort}/caiwuxitong/app:$imageTag"
|
||||
|
||||
for ($uploadAttempt = 1; $uploadAttempt -le 2; $uploadAttempt++) {
|
||||
if ($uploadAttempt -gt 1) {
|
||||
if ($sshTunnel) {
|
||||
if (-not $sshTunnel.HasExited) {
|
||||
$sshTunnel.Kill()
|
||||
$sshTunnel.WaitForExit()
|
||||
}
|
||||
$sshTunnel.Dispose()
|
||||
}
|
||||
|
||||
$localRegistryPort = Get-AvailableLocalPort
|
||||
$sshTunnel = Start-RegistryTunnel -LocalPort $localRegistryPort
|
||||
$registryImage = "127.0.0.1:${localRegistryPort}/caiwuxitong/app:$imageTag"
|
||||
}
|
||||
|
||||
if ($sshTunnel.HasExited) {
|
||||
$uploadExitCode = 255
|
||||
}
|
||||
else {
|
||||
& $regctlPath `
|
||||
--host "reg=127.0.0.1:${localRegistryPort},tls=disabled" `
|
||||
image import $registryImage $localTar
|
||||
$uploadExitCode = $LASTEXITCODE
|
||||
}
|
||||
|
||||
if ($uploadExitCode -eq 0) {
|
||||
$uploadSucceeded = $true
|
||||
break
|
||||
}
|
||||
|
||||
if ($uploadAttempt -eq 1) {
|
||||
Write-Warning '增量镜像隧道在上传期间中断,正在重新建立隧道并重试一次。'
|
||||
}
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Write-Warning "regctl 无法运行(本机安全软件可能拦截了未签名程序):$($_.Exception.Message)"
|
||||
}
|
||||
}
|
||||
else {
|
||||
Write-Host '已指定 -SkipRegctl:跳过 regctl,直接用 docker 直传镜像。'
|
||||
}
|
||||
|
||||
if (-not $uploadSucceeded) {
|
||||
if (-not $SkipRegctl) {
|
||||
Write-Warning '改用 docker 直传方式上传镜像(与 regctl 增量导入等效,只是改为传输完整镜像包)。'
|
||||
}
|
||||
|
||||
if ($sshTunnel.HasExited) {
|
||||
$uploadExitCode = 255
|
||||
}
|
||||
else {
|
||||
& $regctlPath `
|
||||
--host "reg=127.0.0.1:${localRegistryPort},tls=disabled" `
|
||||
image import $registryImage $localTar
|
||||
$uploadExitCode = $LASTEXITCODE
|
||||
if ($sshTunnel) {
|
||||
if (-not $sshTunnel.HasExited) {
|
||||
$sshTunnel.Kill()
|
||||
$sshTunnel.WaitForExit()
|
||||
}
|
||||
$sshTunnel.Dispose()
|
||||
$sshTunnel = $null
|
||||
}
|
||||
|
||||
if ($uploadExitCode -eq 0) {
|
||||
$uploadSucceeded = $true
|
||||
break
|
||||
if (Test-Path -LiteralPath $localTar) {
|
||||
Remove-Item -LiteralPath $localTar -Force
|
||||
}
|
||||
|
||||
if ($uploadAttempt -eq 1) {
|
||||
Write-Warning '增量镜像隧道在上传期间中断,正在重新建立隧道并重试一次。'
|
||||
}
|
||||
Invoke-Native { docker save --output $localTar $fullImage } '导出应用镜像失败。'
|
||||
Compress-Gzip -Source $localTar -Destination $localArchive
|
||||
$archiveSizeMB = [math]::Round((Get-Item -LiteralPath $localArchive).Length / 1MB, 1)
|
||||
Write-Host "docker 直传镜像包:$archiveSizeMB MiB"
|
||||
Invoke-Native { scp @scpOptions @sshOptions $localArchive "${sshTarget}:$remoteArchive" } '上传镜像失败。'
|
||||
Invoke-Native {
|
||||
ssh @sshOptions $sshTarget "gunzip -cf '$remoteArchive' | docker load && docker tag '$fullImage' '$serverRegistryImage' && docker push '$serverRegistryImage'"
|
||||
} '服务器加载镜像或推入本机 Registry 失败。'
|
||||
$uploadSucceeded = $true
|
||||
}
|
||||
|
||||
if (-not $uploadSucceeded) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user