Skip to content

Docker CI/CD Integration

This chapter covers how to integrate Docker into continuous integration and continuous deployment (CI/CD) pipelines.

CI/CD with Docker

Code Push → Build Image → Run Tests → Push Image → Deploy Container
StageDocker's Role
BuildBuild standardized images with Dockerfile
TestRun tests in containers for consistent environments
PushPush images to a registry
DeployPull images and run containers

GitHub Actions

Build and Push to 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 }}

Full CI/CD Pipeline

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 }}

Multi-Stage Dockerfile (with Test Support)

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;"]

Image Tagging Strategies

StrategyTag FormatUse Case
Git SHAmyapp:abc1234Track every build precisely
Semantic versionmyapp:v1.2.3Official releases
Branch namemyapp:mainDevelopment environments
latestmyapp:latestLatest stable version

Zero-Downtime Deployment

Blue-Green Deployment

bash
docker run -d --name app-green -p 3001:3000 myapp:v2
curl http://localhost:3001/health
# Switch traffic (update Nginx config)
docker stop app-blue && docker rm app-blue

Rolling Update (Docker Compose)

bash
docker compose up -d --no-deps --scale app=2 app

Chapter Summary

Docker with CI/CD enables fully automated pipelines from code commit to production deployment. Standardized image builds and deployments ensure environment consistency and deployment reliability.

Further Reading

Content is for learning and research only.