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

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

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

安全扫描嵌入流水线。

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

相关推荐
smartpi_ai1 小时前
CI-73T1 低功耗选型误区:不支持休眠模式的替代方案指南
人工智能·ci/cd·语音识别
浪飘1 小时前
K8S场景下:华为NPU+基于HAMI VNPU能力整体介绍
docker·kubernetes·gpu算力
追寻少年2 小时前
Kubernetes 服务发现和域名解析-cnblog
容器·kubernetes·服务发现
codeejun2 小时前
每日一Go-75、CI/CD 到 K8s:云原生ArgoCD / GitOps 全流程实战(Go + Gin)
ci/cd·云原生·golang
ggaofeng2 小时前
如何在docker和k8s中使用nfs文件系统
docker·eureka·kubernetes
Plastic garden2 小时前
k8s(3)rocky9.7 k8s和Rancher
运维·docker·容器
IT策士2 小时前
第 43 篇 k8s之集群网络策略:NetworkPolicy 入门
网络·容器·kubernetes
杨某不才2 小时前
Linux服务器离线安装docker
linux·服务器·docker
MyFreeIT2 小时前
Docker & MySQL Manual
mysql·docker·容器