Docker CI/CD 集成
本章将介绍如何将 Docker 集成到持续集成和持续部署(CI/CD)流程中。
CI/CD 与 Docker
Docker 在 CI/CD 中的作用:
代码提交 → 构建镜像 → 运行测试 → 推送镜像 → 部署容器| 阶段 | Docker 的作用 |
|---|---|
| 构建 | 使用 Dockerfile 构建标准化镜像 |
| 测试 | 在容器中运行测试,环境一致 |
| 推送 | 将镜像推送到 Registry |
| 部署 | 拉取镜像并运行容器 |
GitHub Actions
构建并推送到 Docker Hub
yaml
# .github/workflows/docker.yml
name: Build and Push Docker Image
on:
push:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and Push
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: |
myuser/myapp:latest
myuser/myapp:${{ github.sha }}构建、测试、部署完整流程
yaml
name: CI/CD Pipeline
on:
push:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build test image
run: docker build -t myapp:test --target test .
- name: Run tests
run: docker run --rm myapp:test
build-and-push:
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and Push
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: myuser/myapp:${{ github.sha }}
deploy:
needs: build-and-push
runs-on: ubuntu-latest
steps:
- name: Deploy to server
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
docker pull myuser/myapp:${{ github.sha }}
docker stop myapp || true
docker rm myapp || true
docker run -d --name myapp -p 80:3000 myuser/myapp:${{ github.sha }}GitLab CI/CD
yaml
# .gitlab-ci.yml
stages:
- test
- build
- deploy
variables:
IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
test:
stage: test
image: docker:latest
services:
- docker:dind
script:
- docker build -t myapp:test --target test .
- docker run --rm myapp:test
build:
stage: build
image: docker:latest
services:
- docker:dind
script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
- docker build -t $IMAGE_TAG .
- docker push $IMAGE_TAG
deploy:
stage: deploy
script:
- ssh $SERVER "docker pull $IMAGE_TAG && docker stop myapp; docker rm myapp; docker run -d --name myapp -p 80:3000 $IMAGE_TAG"
only:
- main多阶段 Dockerfile(支持测试)
dockerfile
# 基础阶段
FROM node:20-alpine AS base
WORKDIR /app
COPY package*.json ./
RUN npm ci
# 测试阶段
FROM base AS test
COPY . .
CMD ["npm", "test"]
# 构建阶段
FROM base AS build
COPY . .
RUN npm run build
# 生产阶段
FROM nginx:alpine AS production
COPY --from=build /app/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]镜像标签策略
| 策略 | 标签格式 | 适用场景 |
|---|---|---|
| Git SHA | myapp:abc1234 | 精确追踪每次构建 |
| 语义化版本 | myapp:v1.2.3 | 正式发布 |
| 分支名 | myapp:main | 开发环境 |
| latest | myapp:latest | 最新稳定版 |
bash
# 多标签构建
docker build -t myapp:v1.2.3 -t myapp:latest .Docker Compose 部署
使用 Docker Compose 进行生产部署
yaml
# docker-compose.prod.yml
services:
app:
image: myuser/myapp:${IMAGE_TAG:-latest}
ports:
- "80:3000"
environment:
- NODE_ENV=production
restart: always
deploy:
replicas: 2
db:
image: postgres:16
volumes:
- db-data:/var/lib/postgresql/data
environment:
POSTGRES_PASSWORD: ${DB_PASSWORD}
restart: always
volumes:
db-data:bash
# 部署
IMAGE_TAG=abc1234 docker compose -f docker-compose.prod.yml up -d
# 更新
IMAGE_TAG=def5678 docker compose -f docker-compose.prod.yml up -d --no-deps app零停机部署
蓝绿部署
bash
# 启动新版本(绿色)
docker run -d --name app-green -p 3001:3000 myapp:v2
# 测试新版本
curl http://localhost:3001/health
# 切换流量(更新 Nginx 配置)
# 停止旧版本(蓝色)
docker stop app-blue && docker rm app-blue滚动更新(Docker Compose)
bash
# 逐个更新服务实例
docker compose up -d --no-deps --scale app=2 app本章小结
Docker 与 CI/CD 的结合可以实现从代码提交到生产部署的全自动化流程。通过标准化的镜像构建和部署,确保了环境一致性和部署可靠性。
关键要点:
- 使用多阶段 Dockerfile 支持测试和构建
- 合理的镜像标签策略便于版本追踪
- GitHub Actions 和 GitLab CI 都能很好地集成 Docker
- 零停机部署保证服务可用性