第十九篇:《Docker 在生产环境中的 CI/CD 实践》

将 Docker 集成到 CI/CD 流水线中,可以实现从代码提交到镜像构建、测试、部署的全自动化。本文介绍如何使用 Jenkins、GitLab CI 和 GitHub Actions 构建镜像、推送到私有仓库,并通过滚动更新部署到 Swarm 或 Kubernetes 集群。同时涵盖镜像缓存、安全扫描、蓝绿部署等生产级实践。

一、CI/CD 中的 Docker 典型流程

text

代码提交 → 触发构建 → 运行单元测试 → 构建镜像 → 推送镜像 → 部署到测试环境 → 集成测试 → 部署到生产环境

每个阶段都可以在容器中执行,确保环境一致性。

二、使用 Jenkins Pipeline 构建 Docker 镜像

2.1 环境准备

Jenkins 安装 Docker Pipeline 插件。

Jenkins 节点上安装 Docker,并将 Jenkins 用户加入 docker 组(或使用 Docker outside of Docker 方式)。

2.2 Jenkinsfile 示例

groovy

pipeline {

agent any

environment {

DOCKER_REGISTRY = 'myregistry.com:5000'

DOCKER_IMAGE = "DOCKERREGISTRY/myapp:{DOCKER_REGISTRY}/myapp:DOCKERREGISTRY/myapp:{BUILD_NUMBER}"

}

stages {

stage('Checkout') {

steps { git 'https://github.com/your/app.git' }

}

stage('Unit Test') {

steps {

sh 'docker run --rm -v $(pwd):/app -w /app node:18 npm test'

}

}

stage('Build Image') {

steps {

sh "docker build -t ${DOCKER_IMAGE} ."

}

}

stage('Push Image') {

steps {

withCredentials(string(credentialsId: 'registry_password', variable: 'REG_PASS')) {

sh '''

echo {REG_PASS} \| docker login -u youruser --password-stdin {DOCKER_REGISTRY}

docker push ${DOCKER_IMAGE}

'''

}

}

}

stage('Deploy to Test') {

steps {

sh "docker stack deploy -c docker-compose.test.yml myapp --with-registry-auth"

}

}

stage('Integration Test') {

steps {

sh './integration-tests.sh'

}

}

stage('Deploy to Production') {

input { message "Deploy to production?" }

steps {

sh "docker stack deploy -c docker-compose.prod.yml myapp --with-registry-auth"

}

}

}

post {

always {

cleanWs() // 清理工作空间

}

}

}

2.3 使用 Docker 缓存加速构建

在构建阶段,可以挂载宿主机的 Docker 缓存目录,避免重复下载基础镜像层:

groovy

sh '''

docker build --cache-from {DOCKER_IMAGE} -t {DOCKER_IMAGE} .

'''

或在 docker build 中使用 --build-arg BUILDKIT_INLINE_CACHE=1 配合 registry 缓存。

三、GitLab CI 集成

.gitlab-ci.yml 示例:

yaml 复制代码
stages:
  - test
  - build
  - deploy

variables:
  DOCKER_REGISTRY: myregistry.com:5000
  IMAGE_TAG: $CI_COMMIT_SHORT_SHA

before_script:
  - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $DOCKER_REGISTRY

unit-test:
  stage: test
  script:
    - docker run --rm -v $(pwd):/app -w /app node:18 npm test

build:
  stage: build
  script:
    - docker build -t $DOCKER_REGISTRY/myapp:$IMAGE_TAG .
    - docker push $DOCKER_REGISTRY/myapp:$IMAGE_TAG

deploy-test:
  stage: deploy
  script:
    - docker stack deploy -c docker-compose.test.yml myapp --with-registry-auth
  environment: test

deploy-prod:
  stage: deploy
  script:
    - docker stack deploy -c docker-compose.prod.yml myapp --with-registry-auth
  environment: production
  only:
    - main

四、GitHub Actions 集成

.github/workflows/docker-ci.yml:

yaml 复制代码
name: Docker CI/CD

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Run unit tests
        run: docker run --rm -v ${{ github.workspace }}:/app -w /app node:18 npm test

  build-and-push:
    needs: test
    runs-on: ubuntu-latest
    if: github.event_name == 'push' && github.ref == 'refs/heads/main'
    steps:
      - uses: actions/checkout@v3
      - name: Login to Registry
        uses: docker/login-action@v2
        with:
          registry: myregistry.com:5000
          username: ${{ secrets.REG_USER }}
          password: ${{ secrets.REG_PASS }}
      - name: Build and push
        uses: docker/build-push-action@v4
        with:
          context: .
          push: true
          tags: myregistry.com:5000/myapp:${{ github.sha }}
      - name: Deploy to Swarm
        uses: appleboy/ssh-action@v0.1.5
        with:
          host: ${{ secrets.SWARM_MANAGER }}
          username: ${{ secrets.SSH_USER }}
          key: ${{ secrets.SSH_KEY }}
          script: |
            docker login -u ${{ secrets.REG_USER }} -p ${{ secrets.REG_PASS }} myregistry.com:5000
            docker stack deploy -c /path/to/docker-compose.prod.yml myapp --with-registry-auth

五、镜像安全扫描

在 CI 中集成漏洞扫描,可阻断含高危漏洞的镜像。

5.1 使用 Trivy

bash 复制代码
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock aquasec/trivy image --severity HIGH,CRITICAL myapp:latest

在 Jenkins 中若扫描失败则终止流水线。

5.2 使用 Docker Scout(官方)

bash 复制代码
docker scout quickview myapp:latest

六、部署策略

6.1 滚动更新(Swarm)

Swarm 服务支持滚动更新,只需在 stack 文件中配置更新策略:

yaml 复制代码
deploy:
  replicas: 5
  update_config:
    parallelism: 2
    delay: 10s
    failure_action: rollback

6.2 蓝绿部署(手动实现)

使用两个环境标签(blue / green),通过负载均衡切换。

bash 复制代码
# 部署新版本 green
docker service update --label-add env=green myapp
# 切换负载均衡器路由到 green
# 验证成功后移除 blue
docker service rm myapp_blue

6.3 金丝雀发布(Istio + Kubernetes)

更复杂的金丝雀发布需要服务网格,不在 Docker Swarm 原生支持范围内,可考虑迁移到 K8s。

七、构建缓存优化

使用 BuildKit:DOCKER_BUILDKIT=1 docker build,支持并行构建和跳过未使用的阶段。

缓存外部依赖:将 package.json / go.mod 先复制,安装依赖,再复制源码。

使用 registry 作为缓存源:--cache-from 参数。

示例优化版 Dockerfile 已在前文提及。

八、清理 CI 环境

避免 CI 节点磁盘被大量旧镜像占满。定期执行:

bash 复制代码
docker system prune -f --filter "until=24h"

或在 GitLab Runner 配置中设置 cleanup 脚本。

九、小结

将 Docker 融入 CI/CD 流水线,可以显著提升交付速度和可靠性。核心要点:

每个阶段使用容器保证一致。

镜像缓存和分层构建加速构建。

安全扫描嵌入流水线。

选择合适的部署策略(滚动更新、蓝绿)。

相关推荐
潘正翔10 小时前
docker核心概念
linux·运维·服务器·docker·容器·centos·运维开发
Java小白笔记13 小时前
Docker 安装配置完全指南:MacOS 、Windows、Linux环境下的安装、配置与验证
linux·macos·docker
小小测试开发13 小时前
Promptfoo 源码级解析:LLM 评估框架的核心设计与 CI/CD 集成实践
人工智能·ci/cd
csdn_aspnet13 小时前
GitHub Actions自动化运维实战,用CI/CD流水线实现测试、部署、安全扫描一体化
运维·安全·ci/cd·自动化·github
copyer_xyf17 小时前
Docker 入门与实战:容器化 React + NestJS 项目
docker
刘马想放假18 小时前
Docker 从入门到进阶:一篇写给工程师的系统化实战指南
运维·docker·容器
Wang's Blog19 小时前
Go-Zero进阶实战2: 使用 Docker Compose 编排与部署微服务
docker·微服务·golang
zjun302119 小时前
如何搭建TRAE IDE 连接到容器开发环境
docker·容器·ascend·trae
寒冰碧海20 小时前
大模型部署从0到1(一):通用环境全流程准备|NVIDIA驱动+Docker+NVIDIA Container Toolkit
运维·docker·容器
hj28625120 小时前
K8S 核心组件与资源概念 + 带注释命令 + 实操案例版笔记
笔记·容器·kubernetes