Chapter 10

Docker 在 CI/CD 中的应用

GitHub Actions 自动构建镜像、蓝绿部署、Kubernetes 简介——完成现代化交付闭环

CI/CD 是什么

CI(持续集成,Continuous Integration):开发者频繁向主分支提交代码,每次提交自动触发构建、测试,尽早发现问题。

CD(持续交付/部署,Continuous Delivery/Deployment):通过 CI 的代码自动发布到测试/生产环境,减少手动发布的风险。

💡

Docker 在 CI/CD 中的核心价值

GitHub Actions 完整工作流

基础:构建并推送镜像


# .github/workflows/docker-publish.yml

name: Build and Push Docker Image

on:
  push:
    branches:
      - main
    tags:
      - 'v*'                    # v1.0.0 等标签触发
  pull_request:
    branches:
      - main                    # PR 只构建不推送

env:
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}   # org/repo

jobs:
  build-and-push:
    runs-on: ubuntu-latest

    permissions:
      contents: read
      packages: write

    steps:
      # 1. 拉取代码
      - name: Checkout repository
        uses: actions/checkout@v4

      # 2. 配置 QEMU(跨平台构建需要)
      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3

      # 3. 配置 Docker Buildx
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      # 4. 登录 GitHub Container Registry
      - name: Log in to the Container registry
        uses: docker/login-action@v3
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      # 5. 提取元数据(自动生成标签)
      - name: Extract metadata
        id: meta
        uses: docker/metadata-action@v5
        with:
          images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
          tags: |
            type=ref,event=branch          # main → :main
            type=ref,event=pr              # PR → :pr-42
            type=semver,pattern={{version}} # v1.2.3 → :1.2.3
            type=semver,pattern={{major}}.{{minor}}  # → :1.2
            type=sha                       # → :sha-abc1234

      # 6. 构建并推送多平台镜像
      - name: Build and push Docker image
        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        # 使用 GitHub Actions 缓存
          cache-to: type=gha,mode=max

镜像标签策略在 CI 中

不同触发事件打不同标签,满足不同用途:

触发事件生成标签用途
push to main:main, :sha-abc1234最新主分支,用于持续部署到 staging
push tag v1.2.3:1.2.3, :1.2, :latest正式版本,用于生产部署
feature 分支:feature-login功能测试
Pull Request:pr-42(只构建不推送)PR 验证

Docker Scout 安全检查

在 CI 流水线中集成漏洞扫描,阻止有高危漏洞的镜像部署:


      # 在 build step 之后添加
      - name: Docker Scout CVE scan
        uses: docker/scout-action@v1
        with:
          command: cves
          image: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:main
          only-severities: critical,high
          exit-code: true     # 发现高危漏洞时让 CI 失败

部署策略

蓝绿部署(Blue-Green Deployment)

同时维护两套完全相同的生产环境(蓝/绿),每次更新切换流量到新版本,出问题立即切回旧版。


蓝绿部署流程:

当前状态(蓝色环境 v1.0 接收100%流量):
负载均衡器 → [蓝色 v1.0 ✅] | [绿色 v1.0 空闲]

部署新版本到绿色环境:
负载均衡器 → [蓝色 v1.0 ✅] | [绿色 v2.0 测试]

切换流量到绿色(瞬间):
负载均衡器 → [蓝色 v1.0 保留] | [绿色 v2.0 ✅]

如果出问题,立即切回蓝色:
负载均衡器 → [蓝色 v1.0 ✅] | [绿色 v2.0 回滚]

滚动更新(Rolling Update)

逐步替换服务实例,新旧版本短暂共存,不中断服务:


初始:[v1.0] [v1.0] [v1.0] [v1.0]
步骤1:[v2.0] [v1.0] [v1.0] [v1.0]  (等待 v2.0 健康)
步骤2:[v2.0] [v2.0] [v1.0] [v1.0]
步骤3:[v2.0] [v2.0] [v2.0] [v1.0]
完成:[v2.0] [v2.0] [v2.0] [v2.0]

# 使用 Docker Compose 模拟滚动更新
docker compose pull api         # 拉取新镜像
docker compose up -d --no-deps api  # 只更新 api 服务

生产运行容器的注意事项

日志:写到 stdout/stderr

容器内的应用应将日志写到标准输出(stdout)和标准错误(stderr),而非文件。Docker 会收集这些输出并通过日志驱动处理:


# /etc/docker/daemon.json 配置日志驱动
{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m",
    "max-file": "3"
  }
}

# 其他日志驱动:
# fluentd  — 发送到 Fluentd 日志聚合
# awslogs  — 发送到 AWS CloudWatch
# gelf     — 发送到 Graylog
# syslog   — 发送到系统 syslog

信号处理:PID 1 问题

Docker stop 发送 SIGTERM 给容器内的 PID 1 进程。如果应用不是 PID 1(例如通过 shell 启动),信号可能无法传递,导致强制 SIGKILL。


# ❌ Shell 形式:sh 成为 PID 1,node 无法收到 SIGTERM
CMD node server.js

# ✅ Exec 形式:node 直接成为 PID 1
CMD ["node", "server.js"]

# ✅ 使用 tini 作为 init 进程(处理孤儿进程)
RUN apk add --no-cache tini
ENTRYPOINT ["/sbin/tini", "--"]
CMD ["node", "server.js"]

健康检查与重启


# Dockerfile 中定义健康检查(第3章已介绍)
HEALTHCHECK --interval=30s --timeout=10s --retries=3 \
  CMD curl -f http://localhost:3000/health || exit 1

# Compose 中配置自动重启
services:
  api:
    restart: unless-stopped

Kubernetes 简介

当你的应用需要跨多台机器、自动扩缩容、高可用部署时,Docker Compose 就不够用了。Kubernetes(K8s)是容器编排领域的事实标准。

Docker Compose vs Kubernetes

能力Docker ComposeKubernetes
运行节点单台机器多台机器集群
自动扩缩容手动 --scale自动 HPA(水平 Pod 自动扩缩)
自愈能力restart 策略自动替换异常 Pod
滚动更新手动内置,可配置策略
服务发现容器名 DNSService + CoreDNS
配置管理env_fileConfigMap + Secret
学习曲线
适用场景开发、小型单机部署生产、微服务、大规模

Kubernetes 核心概念速览

将 Docker Compose 转换为 K8s


# 使用 Kompose 工具自动转换
brew install kompose

# 将 compose.yml 转换为 K8s YAML 文件
kompose convert -f compose.yml

# 部署到 K8s
kubectl apply -f .

学习路径建议 — 先用 Docker Compose 掌握多容器应用的概念(服务依赖、网络、卷),再进阶 Kubernetes。K8s 的绝大多数概念与 Compose 类似,只是功能更强大、配置更复杂。推荐用 minikubek3d 在本机搭建 K8s 练习环境。

课程总结

恭喜你完成了全部 10 章的学习!以下是你已掌握的完整知识体系:

第1章:容器化概念、Namespace/Cgroup、Docker 架构
第2章:安装 Docker、镜像命令、容器生命周期
第3章:Dockerfile 指令、分层缓存、.dockerignore
第4-5章:多阶段构建、镜像优化、Docker 网络
第6-7章:数据卷持久化、Docker Compose 编排
第8-10章:镜像安全、镜像仓库、CI/CD 集成