
Docker-CI/CD:集成 GitHub Actions 实现自动化构建与部署
文章目录
- [Docker-CI/CD:集成 GitHub Actions 实现自动化构建与部署](#Docker-CI/CD:集成 GitHub Actions 实现自动化构建与部署)
-
- 摘要
- [一、为什么选择 GitHub Actions?](#一、为什么选择 GitHub Actions?)
- 二、核心流程设计
- 三、准备工作
-
- [3.1 项目结构要求](#3.1 项目结构要求)
- [3.2 配置 Secrets(敏感信息)](#3.2 配置 Secrets(敏感信息))
- [四、编写 GitHub Actions 工作流](#四、编写 GitHub Actions 工作流)
- 五、关键步骤解析
-
- [5.1 镜像标签策略](#5.1 镜像标签策略)
- [5.2 安全扫描为何放在推送后?](#5.2 安全扫描为何放在推送后?)
- [5.3 部署逻辑:覆盖式更新](#5.3 部署逻辑:覆盖式更新)
- 六、优化与进阶
-
- [6.1 缓存 Docker 层加速构建](#6.1 缓存 Docker 层加速构建)
- [6.2 多环境分离(推荐)](#6.2 多环境分离(推荐))
- [6.3 使用自建 Registry(如 Harbor)](#6.3 使用自建 Registry(如 Harbor))
- 七、常见问题排查
-
- [❌ 问题 1:SSH 连接被拒绝](#❌ 问题 1:SSH 连接被拒绝)
- [❌ 问题 2:Docker Compose 启动失败](#❌ 问题 2:Docker Compose 启动失败)
- [❌ 问题 3:镜像推送权限不足](#❌ 问题 3:镜像推送权限不足)
- 八、安全最佳实践回顾
- 结语
关键字: GitHub Actions、 Docker CI/CD、 自动化部署、 Docker 镜像构建、 Trivy 扫描、 docker-compose 部署、 DevOps 实战
摘要
"手动 docker build && scp && ssh restart?那是石器时代的运维。"
在现代 DevOps 流程中,一次
git push就应触发完整的构建、测试、部署链条------而 Docker 正是这条链的核心载体。
你是否经历过这些"痛苦时刻"?
- 本地开发一切正常,上线后却报错"依赖缺失";
- 发布新版本要手动登录服务器,停容器、拉镜像、启服务;
- 团队成员各自打包镜像,版本混乱难以追溯;
- 测试环境和生产环境配置不一致,Bug 难以复现......
这些问题的根源,在于缺乏标准化的自动化交付流程。
而 GitHub Actions + Docker 的组合,正是解决这些问题的利器。它能让你:
✅ 代码提交即自动构建镜像
✅ 自动运行单元测试与安全扫描
✅ 按分支策略发布到不同环境(dev/staging/prod)
✅ 镜像版本与 Git 提交一一对应,可追溯、可回滚
本文将手把手教你搭建一套完整的 CI/CD 流水线,真正实现"提交即部署"。
一、为什么选择 GitHub Actions?
作为 GitHub 原生 CI/CD 工具,Actions 具有天然优势:
| 优势 | 说明 |
|---|---|
| 无缝集成 | 无需额外账号,仓库内直接配置 |
| 免费额度高 | 公开仓库完全免费,私有仓库每月 2000 分钟 |
| 生态丰富 | 官方提供 docker/build-push-action、aws-actions 等成熟 Action |
| YAML 驱动 | 流程定义即代码(Infrastructure as Code) |
💡 适用场景:中小型项目、开源项目、个人博客、内部工具等。
二、核心流程设计
我们的目标流水线如下:
main 分支 dev 分支 开发者 git push 触发 GitHub Actions 构建 Docker 镜像 运行单元测试 Trivy 扫描漏洞 推送镜像到 Docker Hub SSH 到服务器执行 docker compose pull && up 部署到测试环境
关键原则:
- main 分支 → 生产环境
- dev 分支 → 测试环境
- 每次构建生成带 Git SHA 的镜像标签 (如
myapp:abc1234)
三、准备工作
3.1 项目结构要求
确保你的项目包含:
Dockerfile(位于根目录或子目录)docker-compose.yml(用于部署)- 可运行的测试脚本(如
pytest、npm test)
示例结构:
text
my-web-app/
├── Dockerfile
├── docker-compose.yml
├── app.py
├── tests/
│ └── test_app.py
└── .github/workflows/ci-cd.yml ← CI/CD 配置文件
3.2 配置 Secrets(敏感信息)
在 GitHub 仓库中设置以下 Secrets(Settings → Secrets and variables → Actions):
| Secret 名称 | 用途 |
|---|---|
DOCKERHUB_USERNAME |
Docker Hub 用户名 |
DOCKERHUB_TOKEN |
Docker Hub 访问令牌(非密码!) |
SERVER_HOST |
生产服务器 IP |
SERVER_USER |
SSH 用户名(如 ubuntu) |
SERVER_SSH_KEY |
服务器私钥(PEM 格式) |
🔒 安全提示:
- Docker Hub Token 创建路径:Account Settings → Security → New Access Token
- SSH 私钥需去除密码(或使用
ssh-agent),内容以-----BEGIN OPENSSH PRIVATE KEY-----开头
四、编写 GitHub Actions 工作流
创建 .github/workflows/ci-cd.yml:
yaml
name: CI/CD Pipeline
on:
push:
branches: [ "main", "dev" ]
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
# 1. 检出代码
- name: Checkout code
uses: actions/checkout@v4
# 2. 登录 Docker Hub
- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
# 3. 构建并推送镜像(带 Git SHA 标签)
- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
file: ./Dockerfile
push: true
tags: |
your-dockerhub-username/my-web-app:${{ github.sha }}
your-dockerhub-username/my-web-app:latest-${{ github.ref_name }}
# 4. 运行测试(可选但推荐)
- name: Run tests
run: |
docker build -t my-web-app-test .
docker run --rm my-web-app-test pytest tests/
# 5. 安全扫描(使用 Trivy)
- name: Scan image for vulnerabilities
uses: aquasecurity/trivy-action@master
with:
image-ref: 'your-dockerhub-username/my-web-app:${{ github.sha }}'
format: 'table'
exit-code: '1'
severity: 'CRITICAL,HIGH'
# 6. 部署到服务器
- name: Deploy to server
if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/dev'
env:
SERVER_HOST: ${{ secrets.SERVER_HOST }}
SERVER_USER: ${{ secrets.SERVER_USER }}
SERVER_SSH_KEY: ${{ secrets.SERVER_SSH_KEY }}
run: |
# 创建临时密钥文件
mkdir -p ~/.ssh
echo "$SERVER_SSH_KEY" > ~/.ssh/deploy_key
chmod 600 ~/.ssh/deploy_key
# 动态生成 docker-compose.override.yml
ENV_TAG="latest-main"
if [[ "${{ github.ref }}" == "refs/heads/dev" ]]; then
ENV_TAG="latest-dev"
fi
cat > deploy-compose.yml <<EOF
version: '3.8'
services:
backend:
image: your-dockerhub-username/my-web-app:$ENV_TAG
EOF
# 上传并部署
scp -o StrictHostKeyChecking=no -i ~/.ssh/deploy_key \
deploy-compose.yml $SERVER_USER@$SERVER_HOST:/home/$SERVER_USER/app/
ssh -o StrictHostKeyChecking=no -i ~/.ssh/deploy_key \
$SERVER_USER@$SERVER_HOST <<'EOF'
cd /home/ubuntu/app
docker compose -f docker-compose.yml -f deploy-compose.yml up -d
EOF
📌 替换
your-dockerhub-username为你的实际用户名!
五、关键步骤解析
5.1 镜像标签策略
我们使用两种标签:
${``{ github.sha }}:唯一标识每次提交,用于精确回滚;latest-main/latest-dev:便于 Compose 文件引用。
这样既保证可追溯性,又简化部署配置。
5.2 安全扫描为何放在推送后?
虽然也可以扫描本地镜像,但推送后再扫描更贴近真实环境,且 Trivy Action 支持直接拉取远程镜像分析。
若发现高危漏洞,流水线立即失败,阻止问题镜像上线。
5.3 部署逻辑:覆盖式更新
通过 docker-compose.override.yml 机制,动态覆盖镜像标签:
- 生产服务器上的
docker-compose.yml保持不变(含网络、卷等定义); - CI/CD 仅推送一个轻量级
deploy-compose.yml,指定新镜像; - 最终效果 = 基础配置 + 新镜像。
这种方式避免了频繁修改主 Compose 文件,降低出错风险。
六、优化与进阶
6.1 缓存 Docker 层加速构建
在 build-push-action 中启用缓存:
yaml
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build and push
uses: docker/build-push-action@v5
with:
...
cache-from: type=gha
cache-to: type=gha,mode=max
首次构建较慢,后续提交可复用中间层,速度提升 5~10 倍。
6.2 多环境分离(推荐)
为不同环境创建独立工作流:
.github/workflows/deploy-dev.yml→ 监听dev分支.github/workflows/deploy-prod.yml→ 监听main分支 + 手动审批
生产部署加入人工确认:
yaml
environment:
name: production
url: https://your-app.com
并在仓库 Settings → Environments 中配置审批者。
6.3 使用自建 Registry(如 Harbor)
若不想依赖 Docker Hub,可替换为私有仓库:
yaml
- name: Log in to Harbor
uses: docker/login-action@v3
with:
registry: harbor.yourcompany.com
username: ${{ secrets.HARBOR_USER }}
password: ${{ secrets.HARBOR_PASS }}
镜像标签改为:harbor.yourcompany.com/project/my-app:${``{ github.sha }}
七、常见问题排查
❌ 问题 1:SSH 连接被拒绝
原因:服务器未允许密钥登录,或防火墙限制。
检查:
bash
# 本地测试
ssh -i your-key.pem ubuntu@your-server-ip
确保 /etc/ssh/sshd_config 包含:
text
PubkeyAuthentication yes
PasswordAuthentication no
❌ 问题 2:Docker Compose 启动失败
原因 :服务器缺少 docker-compose.yml 或依赖服务未启动。
建议:
- 在服务器预置完整的
docker-compose.yml; - 使用
depends_on确保数据库等先启动; - 查看日志:
docker compose logs backend
❌ 问题 3:镜像推送权限不足
原因:Docker Hub Token 权限不够,或用户名拼写错误。
验证:
- Token 需勾选 "Read & Write" 权限;
- 镜像仓库名必须与用户名匹配(如
john/my-app)。
八、安全最佳实践回顾
| 风险点 | 防护措施 |
|---|---|
| 密钥硬编码 | 使用 GitHub Secrets |
| 镜像含漏洞 | 集成 Trivy 扫描 |
| 无回滚机制 | 使用 Git SHA 作为镜像标签 |
| 生产误操作 | 生产部署加人工审批 |
| 构建污染 | 每次构建使用干净 Runner |
结语
通过 GitHub Actions 与 Docker 的结合,我们成功将"代码 → 服务"的过程自动化、标准化、安全化。
现在,当你修复一个 Bug 并推送到 main 分支,系统会自动:
- 构建新镜像
- 运行测试
- 扫描漏洞
- 更新线上服务
整个过程无需人工干预,且每一步都可审计、可回溯。
这不仅是效率的提升,更是工程可靠性的飞跃。
系列总结预告 :
下一篇(最终篇)→ 《Docker 实战全景图:从开发到生产的完整技术栈梳理》
我们将回顾整个系列,绘制一张涵盖构建、网络、安全、监控、CI/CD 的 Docker 全景图,并给出学习路径建议!
参考资料:
- GitHub Actions 官方文档:https://docs.github.com/en/actions
- Docker Build Push Action:https://github.com/docker/build-push-action
- Trivy GitHub Action:https://github.com/aquasecurity/trivy-action
- Docker Compose Override:https://docs.docker.com/compose/extends/
