20. CI/CD с Docker
Docker стал стандартом в CI/CD пайплайнах. Контейнеры обеспечивают воспроизводимость — то, что собрано в CI, запускается в продакшене точно так же. GitHub Actions — самая популярная платформа для автоматизации с нативной поддержкой Docker.
Базовый GitHub Actions Workflow
Заголовок раздела «Базовый GitHub Actions Workflow»name: Build and Push Docker Image
on: push: branches: [main] pull_request: branches: [main]
jobs: build: runs-on: ubuntu-latest
steps: - name: Checkout code uses: actions/checkout@v4
- name: Set up Docker Buildx uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub if: github.event_name != 'pull_request' 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: ${{ github.event_name != 'pull_request' }} tags: | myusername/myapp:latest myusername/myapp:${{ github.sha }} cache-from: type=registry,ref=myusername/myapp:buildcache cache-to: type=registry,ref=myusername/myapp:buildcache,mode=maxКеширование слоёв в CI
Заголовок раздела «Кеширование слоёв в CI»Кеширование критически важно для ускорения CI/CD. BuildKit поддерживает несколько типов кеша:
- name: Build with cache uses: docker/build-push-action@v5 with: context: . push: true tags: myapp:latest # Кеш в реестре (рекомендуется) cache-from: type=registry,ref=myapp:buildcache cache-to: type=registry,ref=myapp:buildcache,mode=max
# Или кеш в GitHub Actions Cache cache-from: type=gha cache-to: type=gha,mode=maxПолный CI/CD Pipeline: Build → Test → Push → Deploy
Заголовок раздела «Полный CI/CD Pipeline: Build → Test → Push → Deploy»name: CI/CD Pipeline
on: push: branches: [main, develop] pull_request: branches: [main]
env: REGISTRY: ghcr.io IMAGE_NAME: ${{ github.repository }}
jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4
- name: Run tests in Docker run: | docker compose -f docker-compose.test.yml up \ --abort-on-container-exit \ --exit-code-from tests
build-push: needs: test runs-on: ubuntu-latest if: github.event_name == 'push' outputs: image-tag: ${{ steps.meta.outputs.tags }}
steps: - uses: actions/checkout@v4
- name: Docker meta id: meta uses: docker/metadata-action@v5 with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} tags: | type=sha type=ref,event=branch type=semver,pattern={{version}}
- name: Build and push uses: docker/build-push-action@v5 with: context: . push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }}
deploy-staging: needs: build-push if: github.ref == 'refs/heads/develop' runs-on: ubuntu-latest steps: - name: Deploy to staging run: | ssh user@staging-server \ "docker compose pull && docker compose up -d"
deploy-production: needs: build-push if: github.ref == 'refs/heads/main' environment: production runs-on: ubuntu-latest steps: - name: Deploy to production run: | ssh user@prod-server \ "docker compose pull && docker compose up -d --no-downtime"Сканирование безопасности в CI
Заголовок раздела «Сканирование безопасности в CI»- name: Scan image for vulnerabilities uses: aquasecurity/trivy-action@master with: image-ref: 'myapp:${{ github.sha }}' format: 'sarif' output: 'trivy-results.sarif' severity: 'CRITICAL,HIGH' exit-code: '1' # провалить pipeline при критических CVE
- name: Upload scan results uses: github/codeql-action/upload-sarif@v2 with: sarif_file: 'trivy-results.sarif'