第十九篇:《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 流水线,可以显著提升交付速度和可靠性。核心要点:

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

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

安全扫描嵌入流水线。

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

相关推荐
fengkai454513 分钟前
十二、Redis -2
运维·数据库·redis·容器
DolitD2 小时前
3D应用多实例并发中的GPU隔离技术路径分析
容器·gru·接口隔离原则
姜鱼问生4 小时前
docker exec 排查容器问题:从日志到进程
运维·网络·数据库·docker·容器
人生百态,人生如梦5 小时前
Ubuntu在低版本下使用ccswitch+claudecode(CCSwitch+Docker+Claude)连调教程
linux·ubuntu·docker·claudecode·ccswitch
洋就在江州5 小时前
gitlab-cicd 离线集成——springboot-cicd (非docker形式,shell形式)
java·spring boot·后端·ci/cd·gitlab·gitlab-runner
oicola5 小时前
【运维】CI/CD是什么,合格的规范应该怎么设置
运维·ci/cd
程序员老赵5 小时前
Docker 部署 OpenViking:轻松搭建 AI Agent 上下文数据库平台
docker·开源·agent
吴声子夜歌6 小时前
Docker入门与实战——高级镜像构建
docker
小匠石钧知6 小时前
07_在k8s集群中安装ingress-nginx
nginx·容器·kubernetes·ingress
坐看风云变幻6 小时前
Betaflight 开发环境搭建保姆级教程(Ubuntu / Windows+WSL / Docker 三方案 + 官方网址大全)
windows·ubuntu·docker·无人机·飞控·betaflight