Docker 镜像的自动化构建是 CI/CD 的核心环节。本文构建从代码提交到镜像推送、安全扫描、再到部署触发的完整流水线,覆盖 Docker Hub、阿里云 ACR、GitHub Container Registry 和 AWS ECR 四大主流 Registry。
一、基础镜像构建与推送
# .github/workflows/docker.yml
name: Docker CI/CD
on:
push:
branches: [main]
tags: ['v*']
pull_request:
branches: [main]
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=sha,prefix=,suffix=,format=short
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
platforms: linux/amd64,linux/arm64
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
build-args: |
BUILDKIT_INLINE_CACHE=1
二、多 Registry 推送策略
2.1 Docker Hub
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and push to Docker Hub
uses: docker/build-push-action@v5
with:
push: true
tags: |
${{ secrets.DOCKERHUB_USERNAME }}/myapp:${{ github.sha }}
${{ secrets.DOCKERHUB_USERNAME }}/myapp:latest
2.2 阿里云 ACR
- name: Login to Alibaba Cloud ACR
uses: docker/login-action@v3
with:
registry: registry.cn-hangzhou.aliyuncs.com
username: ${{ secrets.ACR_USERNAME }}
password: ${{ secrets.ACR_PASSWORD }}
- name: Build and push to ACR
uses: docker/build-push-action@v5
with:
push: true
tags: registry.cn-hangzhou.aliyuncs.com/my-namespace/myapp:${{ github.sha }}
2.3 AWS ECR
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: us-east-1
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2
- name: Build and push to ECR
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
ECR_REPOSITORY: my-app
run: |
docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:${{ github.sha }} .
docker push $ECR_REGISTRY/$ECR_REPOSITORY:${{ github.sha }}
docker tag $ECR_REGISTRY/$ECR_REPOSITORY:${{ github.sha }} $ECR_REGISTRY/$ECR_REPOSITORY:latest
docker push $ECR_REGISTRY/$ECR_REPOSITORY:latest
三、安全扫描:Trivy + Grype
3.1 Trivy 镜像扫描
jobs:
scan:
runs-on: ubuntu-latest
needs: build
steps:
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@master
with:
image-ref: ghcr.io/${{ github.repository }}:${{ github.sha }}
format: 'sarif'
output: 'trivy-results.sarif'
- name: Upload Trivy scan results
uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: 'trivy-results.sarif'
3.2 扫描结果阻断策略
- name: Scan and fail on critical
uses: aquasecurity/trivy-action@master
with:
image-ref: myapp:latest
severity: 'CRITICAL,HIGH'
exit-code: '1' # 发现漏洞时失败
ignore-unfixed: true
四、部署触发
4.1 触发 Kubernetes 部署
jobs:
deploy:
runs-on: ubuntu-latest
needs: [build, scan]
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
- name: Update Kubernetes manifest
run: |
sed -i 's|image: .*|image: ghcr.io/${{ github.repository }}:${{ github.sha }}|' k8s/deployment.yaml
- name: Commit and push
run: |
git config user.name "GitHub Actions"
git config user.email "actions@github.com"
git add k8s/deployment.yaml
git commit -m "deploy: update image to ${{ github.sha }}"
git push
4.2 SSH 部署到 VPS
- name: Deploy via SSH
uses: appleboy/ssh-action@v1.0.0
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
cd /opt/myapp
docker pull ghcr.io/${{ github.repository }}:${{ github.sha }}
docker-compose up -d
五、优化策略
| 优化手段 | 效果 |
|---|---|
cache-from/to: type=gha | 构建层缓存提速 3-5x |
platforms: linux/amd64,linux/arm64 | 支持 Apple Silicon 服务器 |
metadata-action | 自动语义化版本标签 |
pull_request 不 push | PR 只 build 不 push,节省 Registry 空间 |
ignore-unfixed: true | 只关注有可修复方案的漏洞 |
相关阅读
- GitHub Actions 详解 — 核心概念与语法速查
- Docker 专题 — Dockerfile 最佳实践与多阶段构建
- Kubernetes 部署指南 — K8s 部署策略
- Node.js 专题 — Node.js Docker 化部署
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。
「saas」更多文章
自定义域名接入 Cloudflare:CDN 加速与缓存规则配置实战
手把手讲解自定义域名接入 Cloudflare CDN 的完整流程:NS 接管、SSL/TLS 模式选择、橙云代理与灰云 DNS 的区别,并用 2024 年后的新 Cache Rules 引擎实战配置静态资源长缓存、HTML 不缓存、后台 Bypass,让边缘缓存命中率最大化。
Hugo 部署到 Cloudflare Pages 实战:从 Git 推送到全球边缘上线
详解 Cloudflare Pages 部署 Hugo 静态站的完整流程,涵盖框架预设、HUGO_VERSION 环境变量固定、构建命令、自定义域名、分支预览、_headers 缓存安全头配置及常见构建失败排查,一次推送即可全球边缘上线。
Cloudflare Workers 入门实战:在边缘运行你的第一行代码
一份面向初学者的 cloudflare workers 教程,从 V8 Isolate 运行时模型讲起,手把手演示 wrangler 初始化、路由分发、KV 存储、Cache API 缓存响应与环境变量配置,帮你在 30 分钟内部署第一个生产可用的边缘 Serverless 应用。