← Blog / CI/CD

GitLab CI/CD pipeline dla aplikacji Dockerowej — krok po kroku

Wprowadzenie

Ręczne wdrożenia to prosta droga do błędów i przestojów. Dobrze skonfigurowany pipeline CI/CD sprawia, że każda zmiana w kodzie automatycznie przechodzi przez testy, budowanie obrazu i deployment — bez udziału człowieka. W tym artykule zbudujemy kompletny pipeline GitLab CI/CD dla aplikacji Dockerowej, od zera do automatycznego wdrożenia na serwer produkcyjny.


Architektura pipeline’u

git push → GitLab CI → test → build → push do registry → deploy na serwer

Etapy (stages):

  1. test — uruchomienie testów jednostkowych
  2. build — zbudowanie obrazu Docker
  3. push — wysłanie obrazu do GitLab Container Registry
  4. deploy:staging — wdrożenie na środowisko staging
  5. deploy:production — wdrożenie na produkcję (ręczne zatwierdzenie)

Dockerfile

FROM python:3.12-slim

WORKDIR /app

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY src/ .

EXPOSE 8000

RUN useradd -m -u 1001 appuser && chown -R appuser:appuser /app
USER appuser

CMD ["gunicorn", "--bind", "0.0.0.0:8000", "app:app"]

Plik .gitlab-ci.yml — kompletna konfiguracja

variables:
  IMAGE_NAME: $CI_REGISTRY_IMAGE
  IMAGE_TAG: $CI_COMMIT_SHORT_SHA
  DOCKER_DRIVER: overlay2

stages:
  - test
  - build
  - push
  - deploy

cache:
  key: "$CI_COMMIT_REF_SLUG"
  paths:
    - .pip-cache/

unit-tests:
  stage: test
  image: python:3.12-slim
  script:
    - pip install -r requirements.txt
    - pip install pytest pytest-cov
    - pytest tests/ -v --cov=src --cov-report=xml
  artifacts:
    reports:
      coverage_report:
        coverage_format: cobertura
        path: coverage.xml

build-image:
  stage: build
  image: docker:24
  services:
    - docker:24-dind
  before_script:
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
  script:
    - docker build --tag $IMAGE_NAME:$IMAGE_TAG --tag $IMAGE_NAME:latest .
  rules:
    - if: '$CI_COMMIT_BRANCH == "main"'
    - if: '$CI_COMMIT_BRANCH == "develop"'

push-image:
  stage: push
  image: docker:24
  services:
    - docker:24-dind
  before_script:
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
  script:
    - docker push $IMAGE_NAME:$IMAGE_TAG
    - docker push $IMAGE_NAME:latest

deploy-staging:
  stage: deploy
  environment:
    name: staging
    url: https://staging.example.com
  script:
    - |
      ssh $STAGING_USER@$STAGING_HOST << EOF
        docker pull $IMAGE_NAME:$IMAGE_TAG
        docker stop myapp-staging || true
        docker run -d --name myapp-staging --restart unless-stopped \
          -p 8001:8000 $IMAGE_NAME:$IMAGE_TAG
      EOF
  rules:
    - if: '$CI_COMMIT_BRANCH == "develop"'

deploy-production:
  stage: deploy
  environment:
    name: production
  when: manual
  script:
    - |
      ssh $PROD_USER@$PROD_HOST << EOF
        docker pull $IMAGE_NAME:$IMAGE_TAG
        docker stop myapp-prod || true
        docker run -d --name myapp-prod --restart unless-stopped \
          -p 8000:8000 $IMAGE_NAME:$IMAGE_TAG
      EOF
  rules:
    - if: '$CI_COMMIT_BRANCH == "main"'

Konfiguracja zmiennych w GitLab

Przejdź do Settings → CI/CD → Variables i dodaj:

ZmiennaTypOpis
SSH_PRIVATE_KEY_STAGINGFileKlucz SSH do serwera staging
SSH_PRIVATE_KEY_PRODFileKlucz SSH do serwera produkcyjnego
STAGING_HOSTVariableIP/hostname serwera staging
PROD_HOSTVariableIP/hostname serwera produkcyjnego

Przygotowanie serwera docelowego

curl -fsSL https://get.docker.com | sh
usermod -aG docker deploy

useradd -m -s /bin/bash deploy
mkdir -p /home/deploy/.ssh
echo "$(cat id_rsa_deploy.pub)" >> /home/deploy/.ssh/authorized_keys
chmod 700 /home/deploy/.ssh
chmod 600 /home/deploy/.ssh/authorized_keys

Podsumowanie

Masz teraz kompletny pipeline CI/CD, który:

  • Automatycznie testuje kod przy każdym pushu
  • Buduje i publikuje obraz Docker do rejestru
  • Wdraża na staging automatycznie po pushu do develop
  • Wdraża na produkcję po ręcznym zatwierdzeniu z brancha main

W kolejnym artykule rozbudujemy pipeline o skanowanie bezpieczeństwa obrazu z Trivy i analizę jakości kodu z SonarQube.