15 10 月 2026

手动 docker build + scp 镜像的时代该翻篇了:推代码自动出镜像、服务器自动拉新版、版本号可回滚。这篇讲私有镜像仓库怎么搭、CI 流水线怎么配、发布流程怎么设计。GitHub Actions 和 Gitee Go 都有现成配置。

需要现成的游戏云服务器,可以看看财富云计算:一键开服面板,NAT 型无独立公网 IP,价格比独立 IP 机型省一半以上,主流游戏都能快速部署。

一、为什么需要镜像仓库

方式问题
Docker Hub 公共仓库国内拉取慢、公开镜像有暴露风险、私有镜像要钱
scp 镜像文件几个 G 传来传去,版本一多就乱
每台机器各自 build环境差异、构建时间浪费、无版本记录

私有仓库(Registry):局域网/内网机器秒拉,版本集中管理,配合 CI 全自动。镜像命名规范:

registry.example.com/项目名/服务名:版本号
registry.example.com/blog/web:1.2.3

二、搭私有 Registry(30 分钟)

2.1 Docker 自建(最简单)

# 跑一个 registry 容器
docker run -d \
  --name registry \
  -p 5000:5000 \
  -v registry_data:/var/lib/registry \
  --restart unless-stopped \
  registry:2

# 本机测试:打标签+推送
docker tag nginx:1.27 localhost:5000/nginx:test
docker push localhost:5000/nginx:test

# 别的机器拉取(先配 insecure-registries,见下)
docker pull 服务器IP:5000/nginx:test

HTTP 仓库要配白名单(默认只信 HTTPS)。每台用仓库的机器,/etc/docker/daemon.json:

{
  "insecure-registries": ["192.168.1.10:5000"]
}

改完 systemctl restart docker。

2.2 带认证的仓库(多机器必配)

# 1. 建账号密码
mkdir -p /opt/registry-auth && cd /opt/registry-auth
docker run --rm --entrypoint htpasswd httpd:2 -Bbn admin 你的密码 > htpasswd

# 2. 带认证重启 registry
docker run -d --name registry -p 5000:5000 \
  -v registry_data:/var/lib/registry \
  -v /opt/registry-auth:/auth \
  -e REGISTRY_AUTH=htpasswd \
  -e REGISTRY_AUTH_HTPASSWD_REALM="Registry Realm" \
  -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
  registry:2

# 3. 客户端先登录
docker login 服务器IP:5000
# 用户名 admin,密码 上面设的

2.3 现成方案(不想运维)

  • Harbor:企业级,带 UI、漏洞扫描、权限管理,功能全但吃资源(4G 起步)
  • Nexus:Maven/npm/docker 一体
  • 云厂商 ACR/CCR:托管服务,按量付费,省心

个人/小团队自建 registry 容器就够了,别上来就 Harbor。

三、镜像版本管理规范

# 推送规范:版本号 + latest 双标签
docker build -t registry.example.com/blog/web:1.2.3 .
docker tag registry.example.com/blog/web:1.2.3 registry.example.com/blog/web:latest
docker push registry.example.com/blog/web:1.2.3
docker push registry.example.com/blog/web:latest
标签用途
1.2.3(语义化版本)生产部署用这个,可精确回滚
latest测试/开发用,永远是最后一次构建
main / 分支名CI 每次推代码自动构建,供测试

铁律:生产环境跑版本号,不跑 latest。回滚就是改 compose 里的标签号,30 秒的事:

# 回滚到 1.2.2
docker compose down
# 改 docker-compose.yml 里 image 标签为 1.2.2
docker compose up -d

版本策略和镜像瘦身见Dockerfile 编写与镜像优化。

四、CI 自动构建(GitHub Actions)

仓库里放 .github/workflows/build.yml:

name: Build and Push

on:
  push:
    branches: [main]
    tags: ['v*']

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Set version
        id: vars
        run: echo "VERSION=${GITHUB_REF_NAME#v}" >> $GITHUB_OUTPUT

      - name: Login Registry
        run: echo "${{ secrets.REGISTRY_PASSWORD }}" | docker login ${{ secrets.REGISTRY_URL }} -u ${{ secrets.REGISTRY_USER }} --password-stdin

      - name: Build and Push
        run: |
          docker build -t ${{ secrets.REGISTRY_URL }}/blog/web:${{ steps.vars.outputs.VERSION }} .
          docker tag ${{ secrets.REGISTRY_URL }}/blog/web:${{ steps.vars.outputs.VERSION }} ${{ secrets.REGISTRY_URL }}/blog/web:latest
          docker push ${{ secrets.REGISTRY_URL }}/blog/web:${{ steps.vars.outputs.VERSION }}
          docker push ${{ secrets.REGISTRY_URL }}/blog/web:latest

      - name: Scan vulnerabilities
        run: docker run --rm aquasec/trivy image --exit-code 1 --severity CRITICAL ${{ secrets.REGISTRY_URL }}/blog/web:${{ steps.vars.outputs.VERSION }}

仓库 Settings → Secrets 里配:REGISTRY_URL、REGISTRY_USER、REGISTRY_PASSWORD——密码绝不写进 yml,不然又泄露出事,防范见Git 仓库与代码泄露防范。

Gitee Go 类似:仓库 → 流水线 → 选 Docker 模板,改登录和构建命令即可。

五、服务器自动部署

镜像推好了,服务器怎么自动更新?两种姿势:

5.1 Watchtower(自动拉新镜像)

services:
  watchtower:
    image: containrrr/watchtower
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      - WATCHTOWER_POLL_INTERVAL=300      # 每 5 分钟检查一次
      - WATCHTOWER_CLEANUP=true           # 删旧镜像
      - WATCHTOWER_INCLUDE_STOPPED=false
    restart: unless-stopped

测试环境很香;生产环境慎用——latest 变了就自动重启,没测试过的新版直接上线容易出事。

5.2 Webhook 部署(推荐生产)

# 服务器上跑个 webhook 服务,收到 POST 就拉新镜像重启
docker run -d --name webhook -p 9000:9000 \
  -v /opt/webhook:/etc/webhook \
  -v /var/run/docker.sock:/var/run/docker.sock \
  almir/webhook

# hooks.json:定义触发脚本
cat > /opt/webhook/hooks.json <<'EOF'
[{
  "id": "deploy-web",
  "execute-command": "/opt/webhook/deploy.sh",
  "command-working-directory": "/opt/app"
}]
EOF

cat > /opt/webhook/deploy.sh <<'EOF'
#!/bin/bash
cd /opt/app
docker compose pull web
docker compose up -d web
EOF
chmod +x /opt/webhook/deploy.sh

CI 最后加一步 curl -X POST http://服务器IP:9000/hooks/deploy-web,全链路打通:推代码 → 构建镜像 → 服务器拉新 → 重启,全程无人值守。

Webhook 地址要保密(URL 里带 token),且只对 CI 的 IP 开放,安全组见云服务器安全组配置实战。

六、维护:仓库也要养

# 看仓库占用
docker system df

# 清理:删除 7 天前的旧镜像标签(registry 容器内跑,或配 REGISTRY_STORAGE_DELETE)
# registry 2.7+ 支持 API 删除,先开环境变量:
# -e REGISTRY_STORAGE_DELETE_ENABLED=true
# 然后:
curl -X DELETE http://localhost:5000/v2/blog/web/manifests/<digest>

# 定期跑垃圾回收(真删数据)
docker exec registry bin/registry garbage-collect /etc/docker/registry/config.yml

磁盘涨得最快的三样:CI 每次构建的新层、没人清理的旧标签、latest 反复覆盖的层。每周一次 GC + 保留策略(只留最近 10 个版本),仓库能长期健康。

七、常见问题

现象原因解法
push 报 http: server gave HTTP response to HTTPS client没配 insecure-registries按第二节配 daemon.json
pull 超时大镜像走公网走内网/同区域机器拉
CI 构建慢没利用缓存依赖层先 COPY,见Dockerfile 优化
镜像越存越大没跑 GC定期 garbage-collect
密码泄露写进了 CI yml用 Secrets,泄露了立刻吊销
生产被自动更新搞崩Watchtower + latest改版本号部署 + Webhook 手动触发

镜像仓库 + CI 是容器化的最后一公里:构建一次、到处运行、版本可回滚、发布全自动。小团队用「registry 容器 + GitHub Actions + Webhook」三件套就够了,半天搭完,受益一整年。

需要现成的游戏云服务器,可以看看财富云计算:一键开服面板,NAT 型无独立公网 IP,价格比独立 IP 机型省一半以上,主流游戏都能快速部署。延伸阅读:Docker 部署网站实战、Docker 数据卷与网络详解、Git 版本控制与服务器部署。

延伸阅读
  1. 网站环境怎么选:LNMP 手动 / 宝塔面板 / Docker / 云开发
  2. 问卷表单系统搭建:SurveyKing / Formbricks,数据自己收
  3. 图床搭建:Lsky Pro / Lychee,自托管图片托管方案
  4. 邮件列表搭建:listmonk 自托管 Newsletter,把读者握在自己手里
  5. 文档站点搭建:MkDocs / VuePress / Docsify,产品文档与技术手册方案
  6. RSS 阅读器搭建:FreshRSS 自托管,把信息流拿回自己手里
  7. 短链接服务搭建:Shlink 自托管,链接数据自己掌握
  8. 网站状态监控页搭建:Uptime Kuma,服务器挂了第一时间知道
更多阅读
  1. 上一篇:Docker 数据卷与网络详解:数据不丢、容器互通的完整指南
  2. 下一篇:开服要花多少钱:预算分级指南,从 0 元到长期服一次算清
发表评论 2