CI/CD Integration

Learn how to integrate Docker with CI/CD pipelines for automated builds and deployments

Docker-ი CI/CD პროცესებში

Docker-ი თანამედროვე CI/CD პროცესების (pipelines) მთავარი კომპონენტია, რომელიც უზრუნველყოფს თანმიმდევრულ build-ებს, ეფექტურ ტესტირებას და საიმედო deployment-ს სხვადასხვა გარემოში. აპლიკაციების კონტეინერიზაციით, Docker-ი ქმნის ერთგვაროვან გარემოს განვითარების მთელი ციკლის განმავლობაში, დეველოპერის ლოკალური მანქანიდან დაწყებული, ტესტირებითა და production deployment-ით დამთავრებული.

Docker-ის როლი CI/CD-ში მოიცავს:

  • იზოლირებული, განმეორებადი build გარემოების უზრუნველყოფა
  • აპლიკაციის შეფუთვის სტანდარტიზაცია სხვადასხვა გარემოსთვის
  • აპლიკაციის image-ების ეფექტური გავრცელების ხელშეწყობა
  • შეუცვლელი (immutable) ინფრასტრუქტურის პატერნების მხარდაჭერა
  • მიკროსერვისების არქიტექტურისა და მასშტაბირებადი deployment-ების მხარდაჭერა

ძირითადი უპირატესობები

თანმიმდევრულობა

  • ერთი და იგივე გარემო განვითარების, ტესტირებისა და production-ის ეტაპებზე
    • იდენტური გაშვების გარემო (runtime) ყოველ ეტაპზე გამორიცხავს გარემოზე დამოკიდებულ ხარვეზებს
    • კონტეინერის image-ები შეიცავს ყველა დამოკიდებულებას, ბიბლიოთეკასა და კონფიგურაციას
    • "ააწყე ერთხელ, გაუშვი ყველგან" ფილოსოფია პრაქტიკულ რეალობად იქცევა
    • კონფიგურაციებს შორის განსხვავებები იმართება გარემოს ცვლადებით ან კონფიგურაციის ფაილებით
  • "ჩემს კომპიუტერზე მუშაობს" პრობლემის აღმოფხვრა
    • კონტეინერები ერთად ფუთავს ყველა დამოკიდებულებასა და გაშვების გარემოს
    • დეველოპერები, ტესტერები და ოპერაციების გუნდები მუშაობენ იდენტური კონტეინერებით
    • სისტემის დონის დამოკიდებულებები კაფსულირებულია კონტეინერში
    • კონტეინერების ორკესტრაცია უზრუნველყოფს deployment-ის თანმიმდევრულ ქცევას
  • განმეორებადი build-ები და ტესტები
    • კონტეინერიზებული build პროცესები უზრუნველყოფს იზოლირებულ, თანმიმდევრულ build გარემოებს
    • Build-ის არტეფაქტები დამოკიდებულია მხოლოდ საწყის კოდზე და არა build მანქანაზე
    • დეტერმინისტული build-ები იდენტური შემავალი მონაცემებიდან იდენტურ შედეგს იძლევა
    • ავტომატური ტესტირება ეშვება კონტეინერებში, რომლებიც production გარემოს იდენტურია
  • დეტერმინისტული deployment-ები
    • შეუცვლელი (immutable) კონტეინერის image-ები ხელს უშლის გარემოებს შორის შეუსაბამობას
    • კონტეინერების ორკესტრაციის პლატფორმები უზრუნველყოფენ სასურველი მდგომარეობის შენარჩუნებას
    • "ინფრასტრუქტურა როგორც კოდი" პრაქტიკა უზრუნველყოფს თანმიმდევრულ ინფრასტრუქტურას
    • დეკლარაციული კონფიგურაცია ამცირებს ხელით ჩარევასა და შეცდომებს
  • ვერსიების კონტროლის ქვეშ მყოფი ინფრასტრუქტურა
    • Dockerfile-ები და compose ფაილები ინახება ვერსიების კონტროლის სისტემაში
    • Image-ის თეგები უზრუნველყოფს მკაფიო ვერსიონირებასა და მიკვლევადობას
    • კონტეინერის კონფიგურაციები იმართება აპლიკაციის კოდთან ერთად
    • გარემოში განხორციელებული ცვლილებების სრული აუდიტის კვალი

სისწრაფე

  • დაკეშირებული ფენები (layers) უფრო სწრაფი build-ებისთვის
    • Docker-ის ფენების კეშირება დრამატულად აჩქარებს განმეორებით build-ებს
    • ხელახლა აწყობა სჭირდება მხოლოდ შეცვლილ ფენებს
    • Dockerfile-ების ოპტიმიზაცია ეფექტური კეშირებისთვის
    • BuildKit-ის პარალელური დამუშავება მრავალეტაპიანი build-ებისთვის
  • პარალელური ტესტირება კონტეინერებში
    • რამდენიმე ტესტ-სუიტის ერთდროულად გაშვება იზოლირებულ კონტეინერებში
    • მატრიცული ტესტირება სხვადასხვა კონფიგურაციასა თუ ვერსიაზე
    • რესურს-ეფექტური სატესტო გარემოები კონტეინერიზაციის საშუალებით
    • დროებითი სატესტო გარემოები სწრაფად იქმნება და იშლება
  • Image-ების ეფექტური გავრცელება
    • Image-ების განახლებისას გადაეცემა მხოლოდ შეცვლილი ფენები
    • განაწილებული registry-ები აუმჯობესებს pull-ის წარმადობას
    • ფენების დედუპლიკაცია ამცირებს შენახვის მოთხოვნებს
    • კონტენტზე დაფუძნებული მისამართების საცავი (Content-addressable storage) უზრუნველყოფს მთლიანობას
  • სწრაფი deployment-ი კონტეინერების ორკესტრაციით
    • კონტეინერების ორკესტრატორები ავტომატიზირებენ deployment-ის პროცესებს
    • Rolling updates ამცირებს შეფერხების დროს (downtime)
    • Blue-green და canary deployment-ის პატერნები
    • თვითაღდგენის შესაძლებლობები ავტომატურად აღადგენს სისტემას ხარვეზებისგან
  • სწრაფი უკან დაბრუნება (rollback) საჭიროებისას
    • შეუცვლელი image-ები მყისიერი უკან დაბრუნების საშუალებას იძლევა წინა ვერსიებზე
    • ვერსიების თეგირება უზრუნველყოფს მკაფიო სამიზნეებს უკან დასაბრუნებლად
    • Registry-ს ისტორია ინახავს ყველა წინა ვერსიას
    • ორკესტრაციის პლატფორმებს აქვთ ხარვეზის შემთხვევაში ავტომატური უკან დაბრუნების მხარდაჭერა

იზოლაცია

  • იზოლირებული build გარემოები
    • თითოეული build ეშვება სუფთა, იზოლირებულ კონტეინერში
    • არ ხდება ჩარევა ერთდროულად მიმდინარე build-ებს შორის
    • გარემოს ცვლადები აკონტროლებენ build-ის სპეციფიკურ პარამეტრებს
    • განმეორებადია CI სერვერის მიუხედავად
  • განცალკევებული სატესტო გარემოები
    • ტესტები ეშვება იზოლირებულ კონტეინერებში, რომლებიც production-ის იდენტურია
    • სატესტო მონაცემების იზოლაცია ხელს უშლის ტესტებს შორის მონაცემების შერევას
    • პარალელური ტესტების შესრულება ჩარევის გარეშე
    • რესურსების ლიმიტები ხელს უშლის "ხმაურიანი მეზობლის" პრობლემებს
  • დამოკიდებულებების იზოლაცია
    • აპლიკაციის დამოკიდებულებები მოთავსებულია image-ებში
    • არ არის კონფლიქტები აპლიკაციებს შორის, რომლებიც სხვადასხვა ვერსიებს საჭიროებენ
    • დამოკიდებულებების მკაფიო დეკლარირება Dockerfile-ებში
    • კონტეინერებს შეუძლიათ გამოიყენონ ერთი და იგივე დამოკიდებულების სხვადასხვა ვერსიები
  • გარემოს სპეციფიკური კონფიგურაციები
    • გარემოს ცვლადები ემატება გაშვების დროს (runtime)
    • კონფიგურაციის ფაილები მაგრდება (mount) ან ემატება სხვადასხვა გარემოსთვის
    • საიდუმლოებების მართვა ინტეგრირებულია კონტეინერულ პლატფორმებთან
    • ერთი და იგივე image-ი ეშვება სხვადასხვა გარემოში სხვადასხვა კონფიგურაციით
  • სუფთა მდგომარეობა ყოველი build-ისთვის
    • ყოველი build-ი და ტესტი იწყება ცნობილი სუფთა მდგომარეობიდან
    • არ რჩება არტეფაქტები წინა build-ებიდან
    • დროებითი build გარემოები ხელს უშლის მდგომარეობის დაგროვებას
    • მკაფიო გამიჯვნა მუდმივ მონაცემებსა და აპლიკაციის კოდს შორის

CI/CD პროცესის კომპონენტები

GitHub Actions მაგალითი

name: Docker CI/CD

on:
  push:
    branches: [ main ]
    # სურვილისამებრ, გაეშვას თეგებზე release-ებისთვის
    tags: [ 'v*.*.*' ]
  pull_request:
    branches: [ main ]

jobs:
  build-and-push:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v3
        with:
            # სრული ისტორიის გადმოწერა სწორი ვერსიონირებისთვის
          fetch-depth: 0

      # Docker-ის მეტამონაცემების ამოღება
      - name: Extract Docker metadata
        id: meta
        uses: docker/metadata-action@v4
        with:
          images: username/app
            # თეგების გენერირება branch-ის, git თეგის და commit SHA-ს მიხედვით
          tags: |
            type=ref,event=branch
            type=ref,event=pr
            type=semver,pattern={{version}}
            type=semver,pattern={{major}}.{{minor}}
            type=sha,format=short

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v2
        with:
            # პარალელური აწყობისთვის რამდენიმე კვანძის გამოყენება
          driver-opts: network=host

      - name: Login to DockerHub
        # ეს ნაბიჯი გაეშვება მხოლოდ რეესტრში ატვირთვისას (არა pull request-ებზე)
        if: github.event_name != 'pull_request'
        uses: docker/login-action@v2
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}
          # Optionally add logout: true for security

      # Docker-ის ფენების კეშირება build-ების დასაჩქარებლად
      - name: Cache Docker layers
        uses: actions/cache@v3
        with:
          path: /tmp/.buildx-cache
          key: ${{ runner.os }}-buildx-${{ github.sha }}
          restore-keys: |
            ${{ runner.os }}-buildx-

      # სურვილისამებრ: ტესტების გაშვება აწყობამდე
      - name: Run tests
        run: |
          docker build -t username/app:test --target test .
          docker run username/app:test

      # მოწყვლადობების სკანირება ატვირთვამდე
      - name: Run Trivy vulnerability scanner
        uses: aquasecurity/trivy-action@master
        with:
          image-ref: 'username/app:test'
          format: 'table'
          exit-code: '1'
          ignore-unfixed: true
          severity: 'CRITICAL,HIGH'

      - name: Build and push
        uses: docker/build-push-action@v4
        with:
          context: .
            # ატვირთვა მხოლოდ იმ შემთხვევაში, თუ არ არის PR და ტესტები/სკანირება წარმატებულია
          push: ${{ github.event_name != 'pull_request' }}
            # მეტამონაცემების გამოყენება ჭკვიანი თეგირებისთვის
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}
            # რეესტრის კეშის გამოყენება ეფექტური build-ებისთვის
          cache-from: type=registry,ref=username/app:buildcache
          cache-to: type=registry,ref=username/app:buildcache,mode=max
            # Build არგუმენტები საჭიროების შემთხვევაში
          build-args: |
            BUILD_VERSION=${{ github.ref_name }}
            BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ')
            # BuildKit-ის ეფექტური build შესაძლებლობების გამოყენება
          platforms: linux/amd64,linux/arm64
            # წარმომავლობის დადასტურების დამატება
          provenance: true
            # Image-ის ხელმოწერა უსაფრთხოებისთვის (თუ კონფიგურირებულია)
            # ხელმოწერის ჩართვა: true

      # Deployment-ი staging გარემოში წარმატებული build/push-ის შემდეგ
      - name: Deploy to staging
        if: github.event_name != 'pull_request' && github.ref == 'refs/heads/main'
        run: |
          echo "Deployment-ი staging გარემოში"
          # გამოიყენეთ kubectl, helm, ან სხვა deployment-ის ხელსაწყოები
          # kubectl set image deployment/app-deployment app=username/app:${{ github.sha }}

GitLab CI/CD მაგალითი

# პროცესის ყველა ეტაპის განსაზღვრა
stages:
  - build
  - test
  - security
  - deploy
  - verify

# გლობალური ცვლადები, რომლებიც გამოიყენება job-ებში
variables:
  # Commit SHA-ს გამოყენება უნიკალური image-ის თეგირებისთვის
  DOCKER_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
  # თეგის მინიჭება semver-ით, თუ თეგი აიტვირთება
  RELEASE_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG
  # გამოიყენეთ Docker Hub-ის სარკე სიჩქარის ლიმიტების თავიდან ასაცილებლად
  DOCKER_HUB_MIRROR: https://mirror.gcr.io
  # Docker BuildKit-ის კონფიგურაცია ეფექტური build-ებისთვის
  DOCKER_BUILDKIT: 1
  # მორგებული build არგუმენტები
  BUILD_ARGS: "--build-arg BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ') --build-arg VCS_REF=$CI_COMMIT_SHORT_SHA"

# Build ეტაპი: აპლიკაციის კომპილაცია და შეფუთვა
build:
  stage: build
  # გამოიყენეთ Docker-in-Docker image-ების ასაწყობად
  image: docker:20.10.16
  services:
    - docker:20.10.16-dind
  before_script:
    # საჭიროების შემთხვევაში დააინსტალირეთ დამოკიდებულებები
    - apk add --no-cache git curl jq
    # Docker BuildX-ის კონფიგურაცია მრავალპლატფორმიანი build-ებისთვის
    - docker buildx create --use
    # GitLab კონტეინერების რეესტრში ავტორიზაცია
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
  script:
    # წინა build-ებიდან კეშირება
    - |
      CACHE_FROM=""
      if docker pull $CI_REGISTRY_IMAGE:latest &>/dev/null; then
        CACHE_FROM="--cache-from $CI_REGISTRY_IMAGE:latest"
      fi
    # აპლიკაციის image-ის აწყობა მეტამონაცემებით
    - >
      docker build
      $CACHE_FROM
      $BUILD_ARGS
      --build-arg CI_PIPELINE_ID=$CI_PIPELINE_ID
      --label org.opencontainers.image.created="$(date -u +'%Y-%m-%dT%H:%M:%SZ')"
      --label org.opencontainers.image.revision="$CI_COMMIT_SHA"
      --label org.opencontainers.image.version="${CI_COMMIT_TAG:-$CI_COMMIT_SHORT_SHA}"
      -t $DOCKER_IMAGE
      -t $CI_REGISTRY_IMAGE:latest
      .
    # ორივე თეგის რეესტრში ატვირთვა
    - docker push $DOCKER_IMAGE
    - docker push $CI_REGISTRY_IMAGE:latest
    # ვერსიის თეგის მინიჭება, თუ ეს თეგით build-ია
    - |
      if [ -n "$CI_COMMIT_TAG" ]; then
        docker tag $DOCKER_IMAGE $RELEASE_IMAGE
        docker push $RELEASE_IMAGE
      fi
  # არტეფაქტების შექმნა შემდეგი ეტაპებისთვის
  artifacts:
    paths:
      - docker-image-info.json
    expire_in: 1 week
  # დამოკიდებულებების კეშირება მომავალი build-ების დასაჩქარებლად
  cache:
    key: ${CI_COMMIT_REF_SLUG}
    paths:
      - node_modules/
      - .npm/
  only:
    - main
    - tags
    - merge_requests

# ტესტირების ეტაპი: ავტომატური ტესტების გაშვება
test:
  stage: test
  image: $DOCKER_IMAGE
  # სატესტო გარემოს ცვლადების განსაზღვრა
  variables:
    NODE_ENV: test
    # გამოიყენეთ in-memory მონაცემთა ბაზა ტესტებისთვის
    DATABASE_URL: "sqlite://:memory:"
  before_script:
    # Prepare test environment
    - echo "Setting up test environment"
    - npm install --only=dev
  script:
    # Run unit tests
    - npm run test:unit
    # Run integration tests
    - npm run test:integration
    # Run end-to-end tests if not a merge request (for speed)
    - '[ "$CI_PIPELINE_SOURCE" = "merge_request_event" ] || npm run test:e2e'
    # Generate code coverage report
    - npm run coverage
  # ტესტის რეპორტების გამოქვეყნება არტეფაქტებად
  artifacts:
    reports:
      junit: junit-*.xml
      coverage_report:
        coverage_format: cobertura
        path: coverage/cobertura-coverage.xml
    paths:
      - coverage/
  coverage: '/Statements\s+:\s+(\d+.?\d*)%/'
  only:
    - main
    - tags
    - merge_requests

# უსაფრთხოების სკანირების ეტაპი
security:
  stage: security
  image:
    name: aquasec/trivy:latest
    entrypoint: [""]
  variables:
    # პროცესის შეწყვეტა კრიტიკულ მოწყვლადობებზე
    TRIVY_EXIT_CODE: 1
    TRIVY_FORMAT: json
    TRIVY_OUTPUT: trivy-results.json
    # dev დამოკიდებულებების გამოტოვება
    TRIVY_SEVERITY: CRITICAL,HIGH
  script:
    # დასასკანერებელი image-ის გადმოწერა
    - docker pull $DOCKER_IMAGE
    # Image-ის სკანირება მოწყვლადობებზე
    - trivy image --format $TRIVY_FORMAT --output $TRIVY_OUTPUT --exit-code $TRIVY_EXIT_CODE $DOCKER_IMAGE
  # უსაფრთხოების რეპორტის გენერირება
  artifacts:
    paths:
      - trivy-results.json
    reports:
      container_scanning: trivy-results.json
  allow_failure: true
  only:
    - main
    - tags

# Deployment-ის ეტაპი
deploy:
  stage: deploy
  image: docker:20.10.16
  services:
    - docker:20.10.16-dind
  before_script:
    # Deployment-ის ხელსაწყოების ინსტალაცია
    - apk add --no-cache curl bash
    # რეესტრში ავტორიზაცია
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
  script:
    # Deployment-ისთვის image-ის გადმოწერა
    - docker pull $DOCKER_IMAGE
    # Production release-ებისთვის გამოიყენეთ ვერსიის თეგი
    - |
      if [ -n "$CI_COMMIT_TAG" ]; then
        docker tag $DOCKER_IMAGE $CI_REGISTRY_IMAGE:stable
        docker push $CI_REGISTRY_IMAGE:stable
        DEPLOY_ENV="production"
      else
        DEPLOY_ENV="staging"
      fi
    # Deployment-ი შესაბამის გარემოში
    - echo "Deploying to $DEPLOY_ENV environment"
    # მაგალითი docker-compose-ის ან kubectl-ის გამოყენებით
    - |
      if [ "$DEPLOY_ENV" = "production" ]; then
        echo "Production deployment-ის შესრულება"
        # kubectl set image deployment/app app=$DOCKER_IMAGE
      else
        echo "Performing staging deployment"
        # docker-compose -f docker-compose.staging.yml up -d
      fi
  environment:
    name: $DEPLOY_ENV
    url: https://$DEPLOY_ENV.example.com
  only:
    - main
    - tags

# ვერიფიკაციის ეტაპი
verify:
  stage: verify
  image: curlimages/curl
  script:
    # დაელოდეთ deployment-ის დასტაბილურებას
    - sleep 30
    # სიჯანსაღის შემოწმება
    - curl -f https://$DEPLOY_ENV.example.com/health || exit 1
    # Smoke ტესტების გაშვება
    - curl -f https://$DEPLOY_ENV.example.com/api/status | grep -q "OK"
  environment:
    name: $DEPLOY_ENV
    url: https://$DEPLOY_ENV.example.com
  only:
    - main
    - tags

Jenkins პაიპლაინის მაგალითი

Jenkinsfile

pipeline {
    // გამოიყენეთ დინამიური agent-ი Docker-ის შესაძლებლობებით
    agent {
        docker {
            image 'docker:20.10.16-dind'
            args '-v /var/run/docker.sock:/var/run/docker.sock -v jenkins-docker-certs:/certs/client -v jenkins-data:/var/jenkins_home'
        }
    }

    // პაიპლაინის გარემოს ცვლადები
    environment {
        DOCKER_REGISTRY = 'docker.io'
        DOCKER_IMAGE = 'myusername/myapp'
        DOCKER_CREDENTIALS_ID = 'docker-hub-credentials'
        // გამოიყენეთ დროის ნიშნულიანი თეგები ვერსიონირებისთვის
        BUILD_VERSION = "${env.BUILD_NUMBER}-${new Date().format('yyyyMMddHHmmss')}"
        // Docker BuildKit-ის კონფიგურაცია
        DOCKER_BUILDKIT = '1'
    }

    // Define stages of the pipeline
    stages {
        // გარემოს მომზადება
        stage('Prepare') {
            steps {
                // გარემოს გასუფთავება
                cleanWs()
                // კოდის ჩამოტვირთვა SCM-დან
                checkout scm
                // საჭირო ხელსაწყოების ინსტალაცია
                sh 'apk add --no-cache git curl jq'
                // Docker BuildX-ის კონფიგურაცია მრავალპლატფორმიანი build-ებისთვის
                sh 'docker buildx create --name cibuilder --use || true'
                // გარემოს ინფორმაციის გამოტანა დებაგისთვის
                sh 'docker version'
                sh 'docker info'
                sh 'git log -1'
                // კოდიდან ვერსიის ინფორმაციის გამოტანა
                script {
                    // სემანტიკური ინფორმაციის გამოტანა package.json-დან
                    if (fileExists('package.json')) {
                        def packageJson = readJSON file: 'package.json'
                        env.APP_VERSION = packageJson.version
                        echo "Building application version: ${env.APP_VERSION}"
                    }
                }
            }
        }

        // Docker იმიჯის აშენება
        stage('Build') {
            steps {
                // ფენების ქეშირება წინა აშენებიდან, თუ შესაძლებელია
                sh '''
                    if docker pull ${DOCKER_IMAGE}:latest; then
                        CACHE_FROM="--cache-from ${DOCKER_IMAGE}:latest"
                    else
                        CACHE_FROM=""
                    fi

                    # Build the image with metadata
                    docker build \
                        $CACHE_FROM \
                        --build-arg BUILD_DATE=$(date -u +"%Y-%m-%dT%H:%M:%SZ") \
                        --build-arg VCS_REF=$(git rev-parse --short HEAD) \
                        --build-arg VERSION=${APP_VERSION:-0.1.0} \
                        --label org.opencontainers.image.created=$(date -u +"%Y-%m-%dT%H:%M:%SZ") \
                        --label org.opencontainers.image.revision=$(git rev-parse HEAD) \
                        --label org.opencontainers.image.version=${APP_VERSION:-0.1.0} \
                        -t myapp:${BUILD_VERSION} \
                        -t myapp:latest \
                        .
                '''

                // იმიჯის დეტალების გამოტანა
                sh 'docker image ls myapp'
            }
        }

        // ტესტების გაშვება კონტეინერში
        stage('Test') {
            steps {
                // სხვადასხვა ტიპის ტესტების გაშვება
                sh '''
                    # Unit ტესტები
                    docker run --rm myapp:latest npm test

                    # ინტეგრაციული ტესტები, თუ არსებობს
                    if [ -f "integration-test.sh" ]; then
                        docker run --rm myapp:latest ./integration-test.sh
                    fi

                    #  Linting-ის გაშვება თუ შესაძლებელია
                    if docker run --rm myapp:latest which eslint > /dev/null; then
                        docker run --rm myapp:latest eslint .
                    fi
                '''

                // უსაფრთხოების სკანირება
                sh '''
                    # Optional: Run Trivy scanner
                    if which trivy > /dev/null; then
                        trivy image --exit-code 1 --severity HIGH,CRITICAL myapp:latest
                    else
                        echo "Trivy not installed, skipping security scan"
                    fi
                '''
            }
        }

        // იმიჯის რეესტრში ატვირთვა
        stage('Push') {
            steps {
                // Jenkins-ის ანგარიშის გამოყენება უსაფრთხო შესვლისთვის
                withCredentials([usernamePassword(credentialsId: "${DOCKER_CREDENTIALS_ID}", usernameVariable: 'DOCKER_USER', passwordVariable: 'DOCKER_PASSWORD')]) {
                    sh '''
                        # Login to Docker Hub securely
                        echo "${DOCKER_PASSWORD}" | docker login -u "${DOCKER_USER}" --password-stdin ${DOCKER_REGISTRY}

                        # Tag with appropriate names for the registry
                        docker tag myapp:latest ${DOCKER_IMAGE}:latest
                        docker tag myapp:latest ${DOCKER_IMAGE}:${BUILD_VERSION}

                        # If this is a tag build, also tag with the git tag
                        if [ -n "${GIT_TAG}" ]; then
                            docker tag myapp:latest ${DOCKER_IMAGE}:${GIT_TAG}
                            docker push ${DOCKER_IMAGE}:${GIT_TAG}
                        fi

                        # Push all tags to the registry
                        docker push ${DOCKER_IMAGE}:latest
                        docker push ${DOCKER_IMAGE}:${BUILD_VERSION}

                        # Logout for security
                        docker logout ${DOCKER_REGISTRY}
                    '''
                }
            }
        }

        // აპლიკაციის დეფლოიმენტი სამიზნე გარემოში
        stage('Deploy') {
            steps {
                // Deployment-ის სხვადასხვა სტრატეგია branch-ის/გარემოს მიხედვით
                script {
                    if (env.BRANCH_NAME == 'main' || env.BRANCH_NAME == 'master') {
                        echo "დეფლოიმენტი საწარმოო გარემოში"
                        // Docker Compose-ის გამოყენება საწარმოო დეფლოიმენტისთვის
                        withCredentials([file(credentialsId: 'production-env-file', variable: 'ENV_FILE')]) {
                            sh '''
                                # გარმოს ფაილის კოპირება საწარმოო გარემოში
                                cp ${ENV_FILE} .env.production

                                # იმიჯის ტეგის განახლება compose ფაილში
                                sed -i "s|image: ${DOCKER_IMAGE}:.*|image: ${DOCKER_IMAGE}:${BUILD_VERSION}|g" docker-compose.prod.yml

                                # ნულოვანი დაუნთაიმით განახლება
                                docker-compose -f docker-compose.prod.yml up -d --remove-orphans

                                # ჯანმრთელობის შემოწმების დალოდება
                                timeout 60s bash -c 'until docker-compose -f docker-compose.prod.yml exec -T app wget -q -O- http://localhost:3000/health | grep -q "ok"; do sleep 2; done'
                            '''
                        }
                    } else if (env.BRANCH_NAME == 'staging') {
                        echo "დეფლოიმენტი staging გარემოში"
                        sh 'docker-compose -f docker-compose.staging.yml up -d'
                    } else {
                        echo "Branch ${env.BRANCH_NAME} doesn't trigger deployment"
                    }
                }
            }
        }
    }

    // ბილდის შემდგომი მოქმედებები
    post {
        always {
            // Docker-ის რესურსების გასუფთავება
            sh '''
                docker system prune -f
                docker image rm -f myapp:${BUILD_VERSION} myapp:latest || true
            '''
        }
        success {
            echo "Pipeline completed successfully!"
            // წარმატების შესახებ შეტყობინება (Slack, email, სხვ.)
            slackSend(color: 'good', message: "ბილდი წარმატებულია: ${env.JOB_NAME} #${env.BUILD_NUMBER} - ${env.BUILD_URL}")
        }
        failure {
            echo "ფაიფლაინი ჩაიშალა!"
            // Notify on failure
            slackSend(color: 'danger', message: "ბილდი ჩაიშალა: ${env.JOB_NAME} #${env.BUILD_NUMBER} - ${env.BUILD_URL}")
        }
    }
}

მრავალარქიტექტურული ბილდები

pipeline {
    agent any

    environment {
        DOCKER_REGISTRY = 'docker.io'
        DOCKER_IMAGE = 'myusername/myapp'
        DOCKER_CREDENTIALS_ID = 'docker-hub-credentials'
        PLATFORMS = 'linux/amd64,linux/arm64,linux/arm/v7'
    }

    stages {
        stage('Prepare BuildX') {
            steps {
                //  Docker BuildX-ის დაყენება თუ საჭიროა
                sh '''
                    # Docker BuildX-ის დაყენება მრავალპლატფორმიანი build-ებისთვის
                    docker buildx version || {
                        BUILDX_VERSION="v0.10.0"
                        mkdir -p ~/.docker/cli-plugins
                        curl -sSLo ~/.docker/cli-plugins/docker-buildx \
                            https://github.com/docker/buildx/releases/download/${BUILDX_VERSION}/buildx-${BUILDX_VERSION}.linux-amd64
                        chmod +x ~/.docker/cli-plugins/docker-buildx
                    }

                    # ახალი builder-ის ინსტანსის შექმნა და გამოყენება შესაბამისი დრაივერებით
                    docker buildx create --name multiarch-builder --driver docker-container --use || true
                    docker buildx inspect multiarch-builder --bootstrap
                '''
            }
        }

        stage('Login to Registry') {
            steps {
                withCredentials([usernamePassword(credentialsId: "${DOCKER_CREDENTIALS_ID}", usernameVariable: 'DOCKER_USER', passwordVariable: 'DOCKER_PASSWORD')]) {
                    sh 'echo "${DOCKER_PASSWORD}" | docker login -u "${DOCKER_USER}" --password-stdin ${DOCKER_REGISTRY}'
                }
            }
        }

        stage('Build Multi-arch Images') {
            steps {
                // მრავალარქიტექტურული იმიჯის აშენება და ატვირთვა ერთ ეტაპად
                sh '''
                    # ვერსიის ამოღება git თეგიდან ან დროის ნიშნულზე დაფუძნებული ვერსიის გენერირება
                    if git describe --exact-match --tags HEAD > /dev/null 2>&1; then
                        VERSION=$(git describe --exact-match --tags HEAD)
                    else
                        VERSION=$(git rev-parse --short HEAD)
                    fi

                    echo "მრავალარქიტექტურული იმიჯის აშენება, ვერსია: $VERSION"

                    # Build and push with all platforms in one command
                    docker buildx build \
                        --platform ${PLATFORMS} \
                        --build-arg BUILD_DATE=$(date -u +"%Y-%m-%dT%H:%M:%SZ") \
                        --build-arg VCS_REF=$(git rev-parse --short HEAD) \
                        --build-arg VERSION=${VERSION} \
                        --tag ${DOCKER_IMAGE}:${VERSION} \
                        --tag ${DOCKER_IMAGE}:latest \
                        --push \
                        .
                '''
            }
        }
    }
}

CircleCI მაგალითი

CircleCI-ის სრული პაიპლაინი Docker-ზე დაფუძნებული აპლიკაციებისთვის:

version: 2.1

# ხელახლა გამოსაყენებელი ბრძანებების განსაზღვრა
commands:
  docker_build:
    description: "Docker-ის იმიჯის აგება და თეგირება"
    parameters:
      image_name:
        type: string
        default: "myapp"
      dockerfile:
        type: string
        default: "Dockerfile"
      build_args:
        type: string
        default: ""
    steps:
      - run:
          name: Docker-ის იმიჯის აგება
          command: |
            # თეგების გამოთვლა
            COMMIT_TAG=${CIRCLE_SHA1:0:8}
            VERSION_TAG=${CIRCLE_TAG:-$COMMIT_TAG}

            # გამოიყენეთ კეში წინა build-ებიდან, თუ ხელმისაწვდომია
            CACHE_FROM=""
            if docker pull $DOCKERHUB_USERNAME/<< parameters.image_name >>:latest &>/dev/null; then
              CACHE_FROM="--cache-from $DOCKERHUB_USERNAME/<< parameters.image_name >>:latest"
            fi

            # აწყობა შესაბამისი თეგებითა და ლეიბლებით
            docker build \
              $CACHE_FROM \
              -f << parameters.dockerfile >> \
              --build-arg BUILDKIT_INLINE_CACHE=1 \
              --build-arg BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ') \
              --build-arg VCS_REF=${CIRCLE_SHA1} \
              --build-arg VERSION=${VERSION_TAG} \
              << parameters.build_args >> \
              -t << parameters.image_name >>:${COMMIT_TAG} \
              -t << parameters.image_name >>:latest \
              -t $DOCKERHUB_USERNAME/<< parameters.image_name >>:${COMMIT_TAG} \
              -t $DOCKERHUB_USERNAME/<< parameters.image_name >>:latest \
              .

            # ვერსიის თეგის მინიჭება, თუ ეს თეგით build-ია
            if [ -n "${CIRCLE_TAG}" ]; then
              docker tag << parameters.image_name >>:${COMMIT_TAG} $DOCKERHUB_USERNAME/<< parameters.image_name >>:${CIRCLE_TAG}
            fi

# შემსრულებლის გარემოების განსაზღვრა
executors:
  docker-builder:
    docker:
      - image: cimg/base:2023.03
    resource_class: medium+

# Job-ების განსაზღვრა
jobs:
  build:
    executor: docker-builder
    steps:
      - checkout
      - setup_remote_docker:
          version: 20.10.14
          docker_layer_caching: true
      - docker_build:
          image_name: myapp
          build_args: "--build-arg NODE_ENV=production"
      - run:
          name: იმიჯის შენახვა შემდგომი job-ებისთვის
          command: |
            COMMIT_TAG=${CIRCLE_SHA1:0:8}
            mkdir -p /tmp/workspace
            docker save myapp:${COMMIT_TAG} | gzip > /tmp/workspace/myapp-image.tar.gz
      - persist_to_workspace:
          root: /tmp/workspace
          paths:
            - myapp-image.tar.gz

  test:
    docker:
      - image: cimg/base:2023.03
    steps:
      - setup_remote_docker:
          version: 20.10.14
      - attach_workspace:
          at: /tmp/workspace
      - run:
          name: Docker-ის იმიჯის ჩატვირთვა
          command: |
            docker load < /tmp/workspace/myapp-image.tar.gz
      - run:
          name: Unit ტესტების გაშვება
          command: |
            COMMIT_TAG=${CIRCLE_SHA1:0:8}
            docker run --rm myapp:${COMMIT_TAG} npm run test:unit
      - run:
          name: ინტეგრაციული ტესტების გაშვება
          command: |
            COMMIT_TAG=${CIRCLE_SHA1:0:8}
            docker run --rm myapp:${COMMIT_TAG} npm run test:integration
      - run:
          name: უსაფრთხოების სკანირების გაშვება
          command: |
            COMMIT_TAG=${CIRCLE_SHA1:0:8}
            docker run --rm -v /var/run/docker.sock:/var/run/docker.sock aquasec/trivy:latest image --severity HIGH,CRITICAL --exit-code 0 myapp:${COMMIT_TAG}

  push:
    executor: docker-builder
    steps:
      - checkout
      - setup_remote_docker:
          version: 20.10.14
      - attach_workspace:
          at: /tmp/workspace
      - run:
          name: Docker-ის იმიჯის ჩატვირთვა
          command: |
            docker load < /tmp/workspace/myapp-image.tar.gz
      - run:
          name: Docker Hub-ზე ატვირთვა
          command: |
            COMMIT_TAG=${CIRCLE_SHA1:0:8}
            echo "$DOCKERHUB_PASSWORD" | docker login -u "$DOCKERHUB_USERNAME" --password-stdin
            docker push $DOCKERHUB_USERNAME/myapp:${COMMIT_TAG}
            docker push $DOCKERHUB_USERNAME/myapp:latest

            # ვერსიის თეგის ატვირთვა, თუ ეს თეგით build-ია
            if [ -n "${CIRCLE_TAG}" ]; then
              docker push $DOCKERHUB_USERNAME/myapp:${CIRCLE_TAG}
            fi

            # უსაფრთხოებისთვის ყოველთვის გამოდით სისტემიდან
            docker logout

  deploy-staging:
    docker:
      - image: cimg/base:2023.03
    steps:
      - checkout
      - run:
          name: Deployment-ის ხელსაწყოების ინსტალაცია
          command: |
            sudo apt-get update
            sudo apt-get install -y curl jq
            # kubectl-ის ინსტალაცია Kubernetes-ის deployment-ებისთვის
            curl -LO "https://dl.k8s.io/release/v1.26.0/bin/linux/amd64/kubectl"
            chmod +x kubectl
            sudo mv kubectl /usr/local/bin/
      - run:
          name: Staging-ზე დეპლოი
          command: |
            COMMIT_TAG=${CIRCLE_SHA1:0:8}
            echo "Deploying $DOCKERHUB_USERNAME/myapp:${COMMIT_TAG} to staging"
            # Deployment-ის მაგალითი kubectl-ის გამოყენებით
            # kubectl config use-context staging
            # kubectl set image deployment/myapp myapp=$DOCKERHUB_USERNAME/myapp:${COMMIT_TAG} --record
            # kubectl rollout status deployment/myapp

  deploy-production:
    docker:
      - image: cimg/base:2023.03
    steps:
      - checkout
      - run:
          name: Deployment-ის ხელსაწყოების ინსტალაცია
          command: |
            sudo apt-get update
            sudo apt-get install -y curl jq
            curl -LO "https://dl.k8s.io/release/v1.26.0/bin/linux/amd64/kubectl"
            chmod +x kubectl
            sudo mv kubectl /usr/local/bin/
      - run:
          name: Production-ზე დეპლოი
          command: |
            VERSION_TAG=${CIRCLE_TAG}
            echo "Deploying $DOCKERHUB_USERNAME/myapp:${VERSION_TAG} to production"
            # საწარმოო deployment-ის მაგალითი
            # kubectl config use-context production
            # kubectl set image deployment/myapp myapp=$DOCKERHUB_USERNAME/myapp:${VERSION_TAG} --record
            # kubectl rollout status deployment/myapp

# სამუშაო პროცესების ორკესტრირება
workflows:
  version: 2
  build-test-deploy:
    jobs:
      - build:
          filters:
            tags:
              only: /^v.*/
      - test:
          requires:
            - build
          filters:
            tags:
              only: /^v.*/
      - push:
          requires:
            - test
          filters:
            tags:
              only: /^v.*/
            branches:
              only: main
      - deploy-staging:
          requires:
            - push
          filters:
            branches:
              only: main
      - approve-production:
          type: approval
          requires:
            - push
          filters:
            tags:
              only: /^v.*/
            branches:
              ignore: /.*/
      - deploy-production:
          requires:
            - approve-production
          filters:
            tags:
              only: /^v.*/
            branches:
              ignore: /.*/

Docker-ის აწყობის სტრატეგიები

ავტომატური ტესტირება

Docker-ი უზრუნველყოფს თანმიმდევრულ, იზოლირებულ სატესტო გარემოებს, რომლებიც production-ის იდენტურია. ქვემოთ მოცემულია ტესტირების სრული კონფიგურაცია:

version: '3.8'
services:
  # მთავარი აპლიკაციის სერვისი
  app:
    build:
      context: .
      dockerfile: Dockerfile
      target: development # გამოიყენეთ განვითარების ეტაპი ტესტირების დამოკიდებულებებით
    depends_on:
      db:
        condition: service_healthy # დაელოდეთ მონაცემთა ბაზის სრულ მზადყოფნას
      redis:
        condition: service_healthy
    environment:
      - NODE_ENV=test
      - DB_HOST=db
      - DB_PORT=5432
      - DB_USER=test
      - DB_PASSWORD=test
      - DB_NAME=test_db
      - REDIS_HOST=redis
      - REDIS_PORT=6379
    # საწყისი კოდის დამაგრება განვითარების დროს hot reloading-ისთვის
    volumes:
      - ./src:/app/src:ro
      - ./test:/app/test:ro
      - node_modules:/app/node_modules
    # პორტის გახსნა debug-ისთვის
    ports:
      - "9229:9229"
    # ჯანმრთელობის შემოწმების დამატება მზადყოფნისთვის
    healthcheck:
      test: ["CMD", "wget", "-qO-", "http://localhost:3000/health"]
      interval: 5s
      timeout: 3s
      retries: 5
      start_period: 10s

  # მონაცემთა ბაზის სერვისი ტესტირებისთვის
  db:
    image: postgres:13-alpine
    environment:
      - POSTGRES_USER=test
      - POSTGRES_PASSWORD=test
      - POSTGRES_DB=test_db
    volumes:
      - ./test/fixtures/init.sql:/docker-entrypoint-initdb.d/init.sql:ro
      - postgres-data:/var/lib/postgresql/data
    # ჯანმრთელობის შემოწმება უზრუნველყოფს, რომ მონაცემთა ბაზა მზად არის ტესტების გაშვებამდე
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U test -d test_db"]
      interval: 5s
      timeout: 3s
      retries: 5
      start_period: 10s

  # კეშის სერვისი
  redis:
    image: redis:alpine
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 5s
      timeout: 3s
      retries: 5

  # Unit ტესტები
  test-unit:
    image: myapp:test
    depends_on:
      app:
        condition: service_healthy
    environment:
      - NODE_ENV=test
      - TEST_TYPE=unit
    volumes:
      - ./test/reports:/app/test/reports
    command: npm run test:unit

  # ინტეგრაციული ტესტები
  test-integration:
    image: myapp:test
    depends_on:
      app:
        condition: service_healthy
      db:
        condition: service_healthy
      redis:
        condition: service_healthy
    environment:
      - NODE_ENV=test
      - TEST_TYPE=integration
      - DB_HOST=db
      - REDIS_HOST=redis
    volumes:
      - ./test/reports:/app/test/reports
    command: npm run test:integration

  # End-to-end ტესტები
  test-e2e:
    image: myapp:test
    depends_on:
      app:
        condition: service_healthy
      db:
        condition: service_healthy
    environment:
      - NODE_ENV=test
      - TEST_TYPE=e2e
      - APP_URL=http://app:3000
    volumes:
      - ./test/reports:/app/test/reports
      - ./test/screenshots:/app/test/screenshots
    command: npm run test:e2e

volumes:
  node_modules:
  postgres-data:

უსაფრთხოების სკანირება

უსაფრთხოების სკანირების CI/CD პროცესში ინტეგრაცია ეხმარება მოწყვლადობების იდენტიფიცირებას განვითარების პროცესის ადრეულ ეტაპზე:

მოწყვლადობების სკანირება

# ძირითადი სკანირება Trivy-ით CI-ში
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
  aquasec/trivy:latest image myapp:latest

# გაფართოებული სკანირება ფილტრაციითა და ფორმატირებული გამოტანით
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
  aquasec/trivy:latest image \
  --severity HIGH,CRITICAL \
  --exit-code 1 \
  --ignore-unfixed \
  --format json \
  --output trivy-results.json \
  myapp:latest

# პაიპლაინის ინტეგრაცია მოწყვლადობის ზღვარით
if docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
  aquasec/trivy:latest image --severity CRITICAL \
  --exit-code 1 --no-progress myapp:latest; then
  echo "კრიტიკული მოწყვლადობები არ მოიძებნა"
else
  echo "კრიტიკული მოწყვლადობები მოიძებნა, build-ი ჩაიშლება"
  exit 1
fi

# სკანირება და რეპორტის დამატება build-ის არტეფაქტებში
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
  -v "$(pwd)/reports:/reports" \
  aquasec/trivy:latest image \
  --format template \
  --template "@/contrib/html.tpl" \
  -o /reports/trivy-report.html \
  myapp:latest

Docker Bench Security

# გაუშვით Docker Bench Security ჰოსტისა და კონტეინერის კონფიგურაციის შესამოწმებლად
docker run --rm -it \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v /etc:/etc \
  -v /usr/bin/containerd:/usr/bin/containerd \
  -v /usr/bin/runc:/usr/bin/runc \
  -v /usr/lib/systemd:/usr/lib/systemd \
  -v /var/lib:/var/lib \
  docker/docker-bench-security

# გაუშვით გამოტანის ფაილში გადამისამართებით CI ინტეგრაციისთვის
docker run --rm \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v /etc:/etc \
  docker/docker-bench-security > docker-bench-results.txt

# მხოლოდ ჩაშლილი შემოწმებების ფილტრაცია
docker run --rm \
  -v /var/run/docker.sock:/var/run/docker.sock \
  docker/docker-bench-security | grep "\[WARN\]" > security-warnings.txt

პოლიტიკის აღსრულება

  • Image-ის ხელმოწერის დანერგვა
    • გამოიყენეთ Docker Content Trust image-ების ხელმოწერისა და ვერიფიკაციისთვის
    • დააკონფიგურირეთ CI/CD image-ების ავტომატური ხელმოწერისთვის
    • შეინახეთ ხელმოწერის გასაღებები უსაფრთხოდ CI საიდუმლოებებში ან HSM-ებში
    • მაგალითი: DOCKER_CONTENT_TRUST=1 docker push myorg/myapp:1.0.0
    • დანერგეთ გასაღებების როტაციისა და მართვის პროცედურები
  • Image-ის მთლიანობის ვერიფიკაცია
    • ვალიდაცია გაუკეთეთ image-ის ხელმოწერებს deployment-მდე
    • შეამოწმეთ image-ის digest-ები შეუცვლელობისთვის
    • დანერგეთ ბრძანებათა ჯაჭვის ვერიფიკაცია
    • მაგალითი: docker trust inspect --pretty myorg/myapp:1.0.0
    • ინტეგრირება CI/CD-ში ავტომატური ვალიდაციის ნაბიჯებით
  • დააყენეთ admission controller-ები
    • დანერგეთ Kubernetes admission controller-ები runtime ვალიდაციისთვის
    • დააკონფიგურირეთ validating და mutating webhook-ები
    • შეამოწმეთ image-ები უსაფრთხოების პოლიტიკების წინააღმდეგ deployment-მდე
    • Kubernetes-ის კონფიგურაციის მაგალითი:
      apiVersion: admissionregistration.k8s.io/v1
      kind: ValidatingWebhookConfiguration
      metadata:
        name: image-policy-webhook
      webhooks:
      - name: image-policy.k8s.io
        rules:
        - apiGroups: [""]
          apiVersions: ["v1"]
          operations: ["CREATE", "UPDATE"]
          resources: ["pods"]
          scope: "Namespaced"
        clientConfig:
          service:
            namespace: image-policy
            name: image-policy-webhook
            path: /validate
        admissionReviewVersions: ["v1", "v1beta1"]
        sideEffects: None
        timeoutSeconds: 5
      
  • გამოიყენეთ პოლიტიკის ძრავები, როგორიცაა OPA
    • განსაზღვრეთ დეკლარაციული პოლიტიკები Open Policy Agent (OPA)-ით
    • ინტეგრირება Kubernetes-თან Gatekeeper-ის გამოყენებით
    • აღასრულეთ ორგანიზაციული უსაფრთხოების სტანდარტები
    • OPA პოლიტიკის მაგალითი:
      package kubernetes.admission
      
      deny[msg] {
        input.request.kind.kind == "Pod"
        image := input.request.object.spec.containers[_].image
        not startswith(image, "approved-registry.com/")
        msg := sprintf("image '%v' მოდის არასანდო რეესტრიდან", [image])
      }
      
  • აღასრულეთ უსაფრთხოების სტანდარტები
    • დანერგეთ შესაბამისობის შემოწმებები ინდუსტრიული სტანდარტებისთვის
    • ვალიდაცია გაუკეთეთ CIS Docker Benchmark-ის წინააღმდეგ
    • აღასრულეთ ორგანიზაცია-სპეციფიკური უსაფრთხოების პოლიტიკები
    • ავტომატიზირება გაუკეთეთ შესაბამისობის ვერიფიკაციას CI/CD-ში
    • გენერირება გაუკეთეთ შესაბამისობის რეპორტებს აუდიტისთვის
    • CI ნაბიჯის მაგალითი:
      compliance-check:
        runs-on: ubuntu-latest
        steps:
          - name: CIS Docker Benchmark-ის გაშვება
            run: |
              docker run --rm \
                -v /var/run/docker.sock:/var/run/docker.sock \
                docker/docker-bench-security --check-sh 5
          - name: დამტკიცებული საბაზისო image-ების ვერიფიკაცია
            run: |
              docker inspect myapp:latest | jq -r '.[].Config.Image' | grep -q "^approved-base-image:"
      

Multi-Environment Deployment

Environment-Specific Deployment Strategy

# Example deployment script with advanced environment handling
#!/bin/bash
set -eo pipefail

# Set variables based on environment
case "$ENVIRONMENT" in
  "dev")
    DOCKER_COMPOSE_FILE="docker-compose.dev.yml"
    REPLICAS=1
    RESOURCES="--cpus=0.5 --memory=512m"
    REGISTRY="dev-registry.example.com"
    ;;
  "qa")
    DOCKER_COMPOSE_FILE="docker-compose.qa.yml"
    REPLICAS=2
    RESOURCES="--cpus=1 --memory=1g"
    REGISTRY="qa-registry.example.com"
    ;;
  "staging")
    DOCKER_COMPOSE_FILE="docker-compose.staging.yml"
    REPLICAS=2
    RESOURCES="--cpus=2 --memory=2g"
    REGISTRY="staging-registry.example.com"
    ;;
  "production")
    DOCKER_COMPOSE_FILE="docker-compose.prod.yml"
    REPLICAS=5
    RESOURCES="--cpus=4 --memory=4g"
    REGISTRY="production-registry.example.com"
    # Additional production safeguards
    DEPLOY_TIMEOUT="--timeout 300s"
    HEALTHCHECK="--health-cmd 'curl -f http://localhost/health || exit 1' --health-interval=10s --health-retries=5"
    ;;
  *)
    echo "Unknown environment: $ENVIRONMENT"
    exit 1
    ;;
esac

# Pull the specific image version
IMAGE_TAG=${VERSION:-latest}
docker pull $REGISTRY/myapp:$IMAGE_TAG

# Apply environment-specific configurations
envsubst < ${DOCKER_COMPOSE_FILE}.template > ${DOCKER_COMPOSE_FILE}

# Deploy with environment-specific settings
if [ "$ENVIRONMENT" == "production" ]; then
  # Production uses a more careful deployment strategy
  echo "Deploying to production with rolling update"

  # Verify image security before deployment
  docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
    aquasec/trivy:latest image --severity HIGH,CRITICAL \
    --exit-code 1 $REGISTRY/myapp:$IMAGE_TAG || { echo "Security check failed"; exit 1; }

  # Backup current state
  docker-compose -f docker-compose.prod.yml config > docker-compose.prev.yml

  # Deploy new version
  docker-compose -f $DOCKER_COMPOSE_FILE up -d --remove-orphans $DEPLOY_TIMEOUT

  # Verify deployment health
  timeout 60s bash -c 'until docker-compose -f $DOCKER_COMPOSE_FILE ps | grep -q "(healthy)"; do sleep 2; done'

  # Run smoke tests
  ./run_smoke_tests.sh || {
    echo "Smoke tests failed, rolling back"
    docker-compose -f docker-compose.prev.yml up -d
    exit 1
  }
else
  # Development and staging environments
  echo "Deploying to $ENVIRONMENT"
  docker-compose -f $DOCKER_COMPOSE_FILE up -d --remove-orphans
fi

# Cleanup
if [ "$ENVIRONMENT" != "production" ]; then
  echo "Pruning old images from $ENVIRONMENT"
  docker image prune -a -f --filter "until=24h"
fi

echo "Deployment to $ENVIRONMENT complete"

Environment Configuration Examples

# Base docker-compose configuration
# docker-compose.base.yml
version: '3.8'
services:
  app:
    image: ${REGISTRY}/myapp:${IMAGE_TAG:-latest}
    restart: unless-stopped
    environment:
      - NODE_ENV=${ENVIRONMENT}
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
      interval: 10s
      timeout: 5s
      retries: 3
      start_period: 30s
    deploy:
      resources:
        limits:
          cpus: "${CPU_LIMIT:-0.5}"
          memory: "${MEMORY_LIMIT:-512M}"

# Development-specific overrides
# docker-compose.dev.yml
version: '3.8'
services:
  app:
    extends:
      file: docker-compose.base.yml
      service: app
    environment:
      - NODE_ENV=development
      - DEBUG=app:*
      - LOG_LEVEL=debug
    volumes:
      - ./src:/app/src:ro
      - ./config:/app/config:ro
    ports:
      - "3000:3000"
      - "9229:9229" # Debug port
    command: ["npm", "run", "dev"]

# Production-specific overrides
# docker-compose.prod.yml
version: '3.8'
services:
  app:
    extends:
      file: docker-compose.base.yml
      service: app
    environment:
      - NODE_ENV=production
      - LOG_LEVEL=info
    secrets:
      - app_config
      - db_credentials
    deploy:
      replicas: 5
      update_config:
        order: start-first
        failure_action: rollback
        delay: 10s
      restart_policy:
        condition: any
        delay: 5s
        max_attempts: 3
        window: 120s
      resources:
        limits:
          cpus: '4'
          memory: 4G
        reservations:
          cpus: '2'
          memory: 2G

secrets:
  app_config:
    external: true
  db_credentials:
    external: true

Continuous Delivery vs. Deployment

Continuous Delivery

  • Automated build and test
    • Automatic code verification at every commit
    • Comprehensive test suite execution
    • Code quality and security checks
    • Artifact generation and validation
    • Example: npm test && npm run lint && npm run build
  • Manual approval for production
    • Human decision point before production deployment
    • Approval gates with required reviewers
    • Compliance and change management integration
    • Documentation of approval process
    • Example CI configuration:
      deploy-production:
        needs: [build, test]
        environment: production
        when: manual
        rules:
          - if: $CI_COMMIT_BRANCH == "main"
      
  • Ready-to-deploy artifacts
    • Immutable container images
    • Versioned and labeled for traceability
    • Pre-validated in lower environments
    • Stored in secure container registry
    • Example image tagging strategy:
      docker tag myapp:latest myapp:1.2.3-${CI_COMMIT_SHORT_SHA}
      docker push myapp:1.2.3-${CI_COMMIT_SHORT_SHA}
      
  • Environment promotion
    • Systematic progression

ცისფერი-მწვანე განლაგებები

# ახალი ვერსიის განლაგება (მწვანე)
docker-compose -f docker-compose.green.yml up -d

# smoke ტესტების გაშვება
./run_smoke_tests.sh

# ტრაფიკის მწვანეზე გადართვა
nginx -s reload

# ძველი ვერსიის ამოღება (ცისფერი)
docker-compose -f docker-compose.blue.yml down

საუბნო განლაგებები

საიდუმლოების მართვა

version: '3.8'
services:
  app:
    image: myapp:latest
    secrets:
      - db_password
      - api_key

secrets:
  db_password:
    external: true
  api_key:
    external: true

CI/CD ხელსაწყოებთან ინტეგრაცია

კონტეინერზე დაფუძნებული CI/CD ხელსაწყოები

  • Jenkins-ი Docker agent-ებით
  • Drone CI
  • Tekton
  • Concourse CI
  • GitLab CI/CD Runner-ები

ღრუბლოვანი CI/CD სერვისები

  • GitHub Actions
  • CircleCI
  • AWS CodeBuild/CodePipeline
  • Google Cloud Build
  • Azure DevOps Pipelines

საუკეთესო პრაქტიკები

მოწინავე CI/CD პატერნები

# Matrix build-ების მაგალითი GitHub Actions-ით
strategy:
  matrix:
    node-version: [14.x, 16.x, 18.x]
    os: [ubuntu-latest, windows-latest]

steps:
  - uses: actions/checkout@v3
  - name: Node.js ${{ matrix.node-version }}-ის გამოყენება
    uses: actions/setup-node@v3
    with:
      node-version: ${{ matrix.node-version }}
  - run: docker build --build-arg NODE_VERSION=${{ matrix.node-version }} -t myapp:${{ matrix.node-version }} .

მონიტორინგი და უკუკავშირი

Deployment-ის მეტრიკები

  • Deployment-ის სიხშირე
  • ცვლილებების დანერგვის დრო
  • ცვლილებების წარუმატებლობის მაჩვენებელი
  • აღდგენის საშუალო დრო
  • Build-ის ხანგრძლივობა

უკუკავშირის ციკლები

  • შეტყობინებები წარუმატებელი build-ების შესახებ
  • შეტყობინებები deployment-ის შესახებ
  • გაფრთხილებები წარმადობაზე ზემოქმედების შესახებ
  • შეცდომების მაჩვენებლის მონიტორინგი
  • მომხმარებლის უკუკავშირის შეგროვება

CI/CD პრობლემების მოგვარება