8.5 KiB
8.5 KiB
Docker Registry 部署方案
概述
使用 Docker Registry 可以完全避免上传大文件(~120MB tar),部署时间从 5-10 分钟减少到 2-3 分钟。
方案对比
当前方案(tar 文件上传)
本地构建 → docker save → scp 上传 (120MB) → 服务器 docker load → 部署
耗时:5-10 分钟
Registry 方案
本地构建 → docker push → 服务器 docker pull → 部署
耗时:2-3 分钟
方案选择
方案 1:使用 Docker Hub(最简单)
优点:
- ✅ 无需搭建服务器
- ✅ 免费(公开仓库)或付费(私有仓库)
- ✅ 全球 CDN 加速
- ✅ 操作简单
缺点:
- ❌ 公开仓库不安全(代码可能泄露)
- ❌ 私有仓库需要付费($7/月)
- ❌ 依赖外部服务
适用场景:个人项目或小团队
方案 2:使用阿里云容器镜像服务(推荐 ⭐)
优点:
- ✅ 国内访问速度快
- ✅ 免费额度充足(个人版免费)
- ✅ 支持私有仓库
- ✅ 与阿里云其他服务集成
缺点:
- ❌ 需要阿里云账号
- ❌ 依赖外部服务
适用场景:国内部署,推荐使用
方案 3:自建 Harbor Registry(最灵活)
优点:
- ✅ 完全控制
- ✅ 不依赖外部服务
- ✅ 支持多租户
- ✅ 支持镜像扫描、安全策略
缺点:
- ❌ 需要服务器资源
- ❌ 需要维护
- ❌ 配置复杂
适用场景:企业级部署,需要完全控制
实施方案
方案 1:Docker Hub(示例)
1. 注册 Docker Hub 账号
访问 https://hub.docker.com 注册账号
2. 登录 Docker Hub
docker login
# 输入用户名和密码
3. 修改部署脚本
在 local-build-and-upload.ps1 中添加:
# 配置 Registry
$RegistryHost = "docker.io" # Docker Hub
$RegistryUser = "your-username"
$RegistryImage = "${RegistryUser}/flnxi-material"
# 构建并标记镜像
$fullImage = "${RegistryImage}:${Tag}"
docker build -t $fullImage -f $Dockerfile $buildArgs $Context
# Push 到 Registry
Write-Host "===> 推送镜像到 Docker Hub" -ForegroundColor Cyan
docker push $fullImage
# 服务器端 Pull 并部署
Invoke-SSHCommand -Command "docker pull ${fullImage}"
Invoke-SSHCommand -Command "cd ${RemotePath} && docker compose up -d"
方案 2:阿里云容器镜像服务(推荐)
1. 创建阿里云账号和容器镜像服务
- 访问 https://www.aliyun.com 注册账号
- 进入「容器镜像服务 ACR」
- 创建「个人版实例」(免费)
- 创建命名空间(如:
youyidian) - 创建镜像仓库(如:
3d-material)
2. 获取登录凭证
在镜像仓库页面,点击「登录指令」,获取:
- 登录地址:
registry.cn-hangzhou.aliyuncs.com(根据地域不同) - 用户名:通常是阿里云账号
- 密码:在「访问凭证」中设置
3. 修改部署脚本
创建新文件(位于项目根目录)一键镜像部署.ps1:
[CmdletBinding()]
param(
[Parameter(Mandatory = $true)]
[string]$Server,
[string]$Username = "root",
[string]$Password,
[string]$RegistryHost = "registry.cn-hangzhou.aliyuncs.com",
[string]$RegistryNamespace = "youyidian",
[string]$RegistryImage = "3d-material",
[string]$RegistryUser,
[string]$RegistryPassword,
[string]$Tag = "latest",
[string]$Dockerfile = "Dockerfile",
[string]$Context = ".",
[string]$RemotePath = "/root/deploy",
[string]$ComposeFile = "docker-compose.prod.yml"
)
# 启用 BuildKit
$env:DOCKER_BUILDKIT = "1"
$projectRoot = Resolve-Path "$PSScriptRoot/../.."
Push-Location $projectRoot
try {
# 构建镜像
$fullImageName = "${RegistryHost}/${RegistryNamespace}/${RegistryImage}:${Tag}"
Write-Host "===> 构建镜像: $fullImageName" -ForegroundColor Cyan
$buildArgs = @(
"--build-arg", "DATABASE_URL=postgresql://placeholder:placeholder@localhost:5432/placeholder",
"--build-arg", "NEXTAUTH_URL=http://45.249.208.118:4320",
"--build-arg", "APP_PUBLIC_URL=http://45.249.208.118:4320"
)
docker build -t $fullImageName -f $Dockerfile $buildArgs $Context
if ($LASTEXITCODE -ne 0) {
throw "构建失败"
}
# 登录 Registry
Write-Host "===> 登录容器镜像服务" -ForegroundColor Cyan
if ($RegistryPassword) {
echo $RegistryPassword | docker login $RegistryHost -u $RegistryUser --password-stdin
} else {
docker login $RegistryHost -u $RegistryUser
}
# 推送镜像
Write-Host "===> 推送镜像到 Registry" -ForegroundColor Cyan
docker push $fullImageName
if ($LASTEXITCODE -ne 0) {
throw "推送失败"
}
# 服务器端操作
Write-Host "===> 在服务器上拉取并部署" -ForegroundColor Cyan
# 获取认证信息(复用原有逻辑)
$AuthInfo = Get-AuthMethod -Server $Server -Username $Username -Password $Password
# 在服务器上登录 Registry(如果需要)
$loginCmd = "echo '$RegistryPassword' | docker login $RegistryHost -u $RegistryUser --password-stdin"
Invoke-SSHCommand -Server $Server -Username $Username -Password $Password -Command $loginCmd -AuthInfo $AuthInfo
# 拉取镜像
Invoke-SSHCommand -Server $Server -Username $Username -Password $Password -Command "docker pull ${fullImageName}" -AuthInfo $AuthInfo
# 更新 docker-compose.yml 中的镜像名称
$updateImageCmd = "cd ${RemotePath} && sed -i 's|image:.*flnxi-material.*|image: ${fullImageName}|g' docker-compose.yml"
Invoke-SSHCommand -Server $Server -Username $Username -Password $Password -Command $updateImageCmd -AuthInfo $AuthInfo
# 部署
Invoke-SSHCommand -Server $Server -Username $Username -Password $Password -Command "cd ${RemotePath} && docker compose up -d" -AuthInfo $AuthInfo
Write-Host "✓ 部署完成" -ForegroundColor Green
}
finally {
Pop-Location
}
4. 使用方式
# 设置环境变量(可选,避免在命令行中暴露密码)
$env:ALIYUN_REGISTRY_USER = "your-username"
$env:ALIYUN_REGISTRY_PASSWORD = "your-password"
# 执行部署
.\一键镜像部署.ps1 `
-Server 45.249.208.118 `
-Username root `
-Password "your-ssh-password" `
-RegistryUser $env:ALIYUN_REGISTRY_USER `
-RegistryPassword $env:ALIYUN_REGISTRY_PASSWORD `
-Tag "v1.0.0"
方案 3:自建 Harbor Registry
1. 在服务器上安装 Harbor
# 下载 Harbor
wget https://github.com/goharbor/harbor/releases/download/v2.10.0/harbor-offline-installer-v2.10.0.tgz
tar xvf harbor-offline-installer-v2.10.0.tgz
cd harbor
# 配置 harbor.yml
cp harbor.yml.tmpl harbor.yml
# 编辑 harbor.yml,设置域名、密码等
# 安装
./install.sh
2. 配置 Nginx 反向代理(可选)
server {
listen 80;
server_name registry.yourdomain.com;
location / {
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
3. 使用方式
与方案 2 类似,只需修改 Registry 地址:
.\一键镜像部署.ps1 `
-Server 45.249.208.118 `
-RegistryHost "registry.yourdomain.com" `
-RegistryUser "admin" `
-RegistryPassword "Harbor12345"
安全建议
1. 使用环境变量存储密码
# 创建 .env.registry 文件(不提交到 Git)
$env:REGISTRY_PASSWORD = "your-password"
# 在脚本中使用
-RegistryPassword $env:REGISTRY_PASSWORD
2. 使用访问令牌(Token)
阿里云 ACR 支持访问令牌,比密码更安全:
- 在 ACR 控制台创建访问令牌
- 使用令牌作为密码
3. 限制 Registry 访问
- 只允许特定 IP 访问
- 使用 HTTPS
- 定期轮换密码
成本对比
当前方案(tar 上传)
- 成本:$0(使用现有服务器)
- 时间:5-10 分钟
Docker Hub
- 成本:$0(公开)或 $7/月(私有)
- 时间:2-3 分钟
阿里云 ACR
- 成本:$0(个人版免费)
- 时间:2-3 分钟(国内更快)
Harbor(自建)
- 成本:服务器资源(约 2GB RAM,20GB 磁盘)
- 时间:2-3 分钟
推荐方案
推荐使用阿里云容器镜像服务(ACR),原因:
- ✅ 免费(个人版)
- ✅ 国内访问速度快
- ✅ 配置简单
- ✅ 支持私有仓库
- ✅ 无需维护
迁移步骤
- 创建 Registry 账号和仓库(5 分钟)
- 修改部署脚本(10 分钟)
- 测试部署(5 分钟)
- 切换到新方案(1 分钟)
总计:约 20 分钟即可完成迁移