1. Docker trong CI/CD - Tổng quan
Docker đóng vai trò quan trọng trong CI/CD pipeline:
Consistent build environment: Build trong container đảm bảo reproducible
Isolated testing: Chạy tests trong containers cô lập
Artifact packaging: Đóng gói ứng dụng thành Docker image
Deployment: Deploy containers lên production
2. GitHub Actions với Docker
# .github/workflows/docker.yml name: Build and Push Docker Imageon: push: branches: [main] tags: ['v*'] pull_request: branches: [main]
env: REGISTRY: ghcr.io IMAGE_NAME: ${{ github.repository }}
jobs: build: runs-on: ubuntu-latest permissions: contents: read packages: write
steps: - uses: actions/checkout@v4 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Login to Container Registry uses: docker/login-action@v3 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Extract metadata id: meta uses: docker/metadata-action@v5 with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} tags: | type=semver,pattern={{version}} type=semver,pattern={{major}}.{{minor}} type=sha - name: Build and Push uses: docker/build-push-action@v6 with: context: . push: ${{ github.event_name != 'pull_request' }} tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} cache-from: type=gha cache-to: type=gha,mode=max - name: Scan for vulnerabilities uses: aquasecurity/trivy-action@master with: image-ref: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:sha-${{ github.sha }} format: 'table' exit-code: '1' severity: 'CRITICAL,HIGH'
3. GitLab CI với Docker
# .gitlab-ci.yml stages: - test - build - scan - deployvariables: DOCKER_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
test: stage: test image: node:20-alpine script: - npm ci - npm test cache: paths: - node_modules/
build: stage: build image: docker:27 services: - docker:27-dind variables: DOCKER_TLS_CERTDIR: "/certs" before_script: - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY script: - docker build -t $DOCKER_IMAGE . - docker push $DOCKER_IMAGE - | if [ "$CI_COMMIT_TAG" ]; then docker tag $DOCKER_IMAGE $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG fi
scan: stage: scan image: name: aquasec/trivy:latest entrypoint: [""] script: - trivy image --exit-code 1 --severity CRITICAL $DOCKER_IMAGE allow_failure: true
deploy: stage: deploy image: docker:27 only: - main script: - docker pull $DOCKER_IMAGE - docker compose -f docker-compose.prod.yml up -d
4. Jenkins Pipeline với Docker
// Jenkinsfile pipeline { agent anyenvironment { REGISTRY = 'harbor.example.com' IMAGE = "${REGISTRY}/myproject/myapp" TAG = "${env.BUILD_NUMBER}-${env.GIT_COMMIT.take(7)}" } stages { stage('Test') { agent { docker { image 'node:20-alpine' args '-v /tmp:/tmp' } } steps { sh 'npm ci' sh 'npm test' } } stage('Build Image') { steps { script { docker.build("${IMAGE}:${TAG}") } } } stage('Push Image') { steps { script { docker.withRegistry("https://${REGISTRY}", 'harbor-creds') { docker.image("${IMAGE}:${TAG}").push() docker.image("${IMAGE}:${TAG}").push('latest') } } } } stage('Deploy') { when { branch 'main' } steps { sh "TAG=${TAG} docker compose -f docker-compose.prod.yml up -d" } } }
}
5. Docker-in-Docker vs Socket Mounting
Docker-in-Docker (DinD)
# CI runner chạy Docker daemon riêng bên trong container
services:
docker:
image: docker:27-dind
privileged: true
volumes:
- docker-certs:/certs
Ưu điểm: Cô lập hoàn toàn, không ảnh hưởng host
Nhược điểm: Cần privileged mode, chậm hơn, cache riêng biệt
Docker Socket Mounting
# Mount Docker socket từ host
docker run -v /var/run/docker.sock:/var/run/docker.sock docker:27
Ưu điểm: Nhanh, chia sẻ cache với host
Nhược điểm: Security risk - container có full access tới Docker daemon
6. Automated Testing với Docker
# docker-compose.test.yml services: test-db: image: postgres:16-alpine environment: POSTGRES_DB: test_db POSTGRES_PASSWORD: test healthcheck: test: ["CMD-SHELL", "pg_isready"] interval: 5s timeout: 3s retries: 5
test: build: context: . target: test environment: DB_HOST: test-db DB_NAME: test_db DB_PASSWORD: test NODE_ENV: test depends_on: test-db: condition: service_healthy command: npm test
# Chạy tests
docker compose -f docker-compose.test.yml run --rm test
echo $? # Exit code = test result
# Cleanup
docker compose -f docker-compose.test.yml down -v
7. Deployment Strategies
Blue-Green Deployment
#!/bin/bash # blue-green-deploy.shCURRENT=$(docker inspect --format='{{.Config.Labels.version}}' app-blue 2>/dev/null) NEW_VERSION=$1
if [ "$CURRENT" ]; then # Deploy to green TAG=$NEW_VERSION docker compose -f docker-compose.green.yml up -d # Wait for healthy sleep 30 # Switch traffic (update nginx upstream) # Remove blue docker compose -f docker-compose.blue.yml down else # Deploy to blue TAG=$NEW_VERSION docker compose -f docker-compose.blue.yml up -d fi
8. Tổng kết
Trong bài này, bạn đã nắm được:
Docker trong CI/CD pipeline overview
GitHub Actions, GitLab CI, Jenkins với Docker
DinD vs Docker Socket mounting
Automated testing với Docker Compose
Blue-green và canary deployment strategies
Bài tiếp theo sẽ hướng dẫn Docker Performance Tuning.