GitHub Actions Docker CI/CD 完全指南:多平台构建、安全扫描、Registry 推送与生产部署

用 GitHub Actions 实现 Docker 镜像的自动化 CI/CD:多平台镜像构建(linux/amd64 + linux/arm64)、Trivy/Grype 漏洞扫描、推送 Docker Hub / 阿里云 ACR / GitHub Container Registry / AWS ECR、语义化版本标签管理、以及 Kubernetes 部署触发。

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 不 pushPR 只 build 不 push,节省 Registry 空间
ignore-unfixed: true只关注有可修复方案的漏洞

相关阅读

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「saas」更多文章