Menu
Szybki wybór
Hosting Domeny VPS SSL Kalkulator Porównania FAQ
Aktywne kody
Wszystkie kody rabatowe

Docker Compose w produkcji — best practices

Opublikowano: 9 kwietnia 2026 · Kategoria: VPS / Docker

Docker Compose świetnie sprawdza się w developmencie. Ale produkcja ma inne wymagania: trwałe dane, izolacja sieci, bezpieczne sekrety, automatyczny restart po awarii. Oto kompletny przewodnik jak skonfigurować Compose na VPS tak, żeby nie budzić się w nocy z alertem.

Pełny docker-compose.yml dla produkcji

Przykładowy stack: aplikacja Node.js + PostgreSQL + Nginx reverse proxy:

services:
  # Baza danych
  db:
    image: postgres:16-alpine
    restart: unless-stopped
    env_file: .env          # Ładuje zmienne z pliku .env
    environment:
      POSTGRES_DB: ${DB_NAME}
      POSTGRES_USER: ${DB_USER}
      POSTGRES_PASSWORD: ${DB_PASSWORD}
    volumes:
      - db_data:/var/lib/postgresql/data   # Named volume — persystentne dane
    networks:
      - backend
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${DB_USER} -d ${DB_NAME}"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 30s

  # Aplikacja
  app:
    image: myapp:latest
    restart: unless-stopped
    env_file: .env
    environment:
      DATABASE_URL: postgresql://${DB_USER}:${DB_PASSWORD}@db:5432/${DB_NAME}
      NODE_ENV: production
    networks:
      - backend
      - frontend
    depends_on:
      db:
        condition: service_healthy   # Czeka aż DB jest gotowa
    healthcheck:
      test: ["CMD", "wget", "-qO-", "http://localhost:3000/health"]
      interval: 30s
      timeout: 10s
      retries: 3
    deploy:
      resources:
        limits:
          memory: 512m      # Limit RAM
          cpus: '0.5'       # Limit CPU

  # Reverse proxy
  nginx:
    image: nginx:alpine
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro    # Bind mount — config
      - ./nginx/certs:/etc/nginx/certs:ro              # Certyfikaty SSL
      - nginx_cache:/var/cache/nginx                   # Named volume — cache
    networks:
      - frontend
    depends_on:
      - app

volumes:
  db_data:
    driver: local
  nginx_cache:
    driver: local

networks:
  backend:
    driver: bridge
    internal: true    # Brak dostępu z zewnątrz — tylko między serwisami
  frontend:
    driver: bridge

Plik .env — bezpieczne sekrety

Plik .env trzyma wrażliwe dane. Nigdy nie commituj go do gita:

# .env (dodaj do .gitignore!)
DB_NAME=myapp_prod
DB_USER=myapp
DB_PASSWORD=super_secret_password_here
SECRET_KEY=32_char_random_string_here
REDIS_URL=redis://redis:6379

# Uprawnienia — tylko właściciel może czytać
chmod 600 .env
# .env.example (commituj — szablon bez wartości)
DB_NAME=
DB_USER=
DB_PASSWORD=
SECRET_KEY=
REDIS_URL=

Healthchecks — automatyczna detekcja awarii

Healthchecks pozwalają Compose (i Docker) wiedzieć czy kontener naprawdę działa, a nie tylko że proces się uruchomił. Stany kontenera: startinghealthy lub unhealthy. Przy unhealthy można automatycznie zrestartować.

Parametr Opis Wartość domyślna
interval Co ile sprawdzać 30s
timeout Czas oczekiwania na odpowiedź 30s
retries Ile nieudanych prób = unhealthy 3
start_period Grace period przy starcie (błędy nie liczą się) 0s

Deploy i aktualizacje

# Podstawowe komendy produkcyjne

# Uruchom w tle
docker compose up -d

# Sprawdź stan
docker compose ps
docker compose logs -f app

# Aktualizacja aplikacji (pobierz nowy obraz + restart)
docker compose pull app
docker compose up -d app    # Zatrzymuje i startuje tylko zmieniony serwis

# Pełna aktualizacja wszystkich serwisów
docker compose pull
docker compose up -d

# Zatrzymaj bez usuwania danych
docker compose stop

# Usuń kontenery (dane w volumes są bezpieczne)
docker compose down

# NIEBEZPIECZNE: usuń kontenery + volumes (utrata danych!)
docker compose down -v

Backup named volumes

# Backup named volume do pliku tar
docker run --rm \
  -v myapp_db_data:/data \
  -v ${PWD}/backups:/backup \
  alpine tar czf /backup/db_data_$(date +%Y%m%d).tar.gz -C /data .

# Restore z backupu
docker run --rm \
  -v myapp_db_data:/data \
  -v ${PWD}/backups:/backup \
  alpine tar xzf /backup/db_data_20260409.tar.gz -C /data

Traefik zamiast Nginx — automatyczne SSL

Traefik to nowoczesna alternatywa dla Nginx jako reverse proxy w środowisku Docker. Automatycznie wykrywa kontenery i wystawia certyfikaty Let's Encrypt bez konfiguracji ręcznej:

services:
  traefik:
    image: traefik:v3
    restart: unless-stopped
    command:
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      - "[email protected]"
      - "--certificatesresolvers.letsencrypt.acme.storage=/certs/acme.json"
      - "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web"
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - traefik_certs:/certs
    networks:
      - frontend

  app:
    image: myapp:latest
    restart: unless-stopped
    networks:
      - frontend
      - backend
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.app.rule=Host(`example.com`)"
      - "traefik.http.routers.app.tls.certresolver=letsencrypt"
      - "traefik.http.services.app.loadbalancer.server.port=3000"

volumes:
  traefik_certs:

networks:
  frontend:
  backend:
    internal: true

Best practices — lista kontrolna

  • restart: unless-stopped na wszystkich serwisach produkcyjnych — kontenery restartują po restarcie hosta.
  • Limity zasobów — bez deploy.resources.limits jeden serwis może zagłodzić pozostałe z pamięci.
  • Internal networks — baza danych nie powinna mieć dostępu do internetu. Użyj internal: true.
  • Read-only bind mounts — dodaj :ro dla plików konfiguracyjnych (Nginx, certyfikaty).
  • Pinuj wersje obrazówpostgres:16-alpine zamiast postgres:latest. Unikasz niespodzianek po auto-update.
  • Logowanie — ustaw logging.driver: json-file z max-size i max-file żeby logi nie zapełniły dysku.

Najczęstsze pytania

Czy Docker Compose nadaje się do produkcji? +
Tak, dla pojedynczego VPS lub małego klastra Docker Compose jest bardzo dobrym wyborem. Jest prostszy niż Kubernetes, ma mniejszy overhead i wystarczy dla zdecydowanej większości aplikacji webowych. Kubernetes warto rozważyć przy potrzebie automatycznego skalowania horyzontalnego (dziesiątki/setki nodów) lub gdy masz dedykowany DevOps team. Dla startupu lub aplikacji do kilku tysięcy użytkowników Compose + VPS to często najlepsza opcja.
Jak bezpiecznie przechowywać sekrety w Docker Compose? +
Najlepsza praktyka: plik .env z sekretami (w .gitignore), ładowany przez Compose jako env_file. Nigdy nie hardcoduj haseł w docker-compose.yml — ten plik idzie do gita. Dla zaawansowanego podejścia: Docker Secrets (dla Swarm) lub zewnętrzny vault (HashiCorp Vault, AWS Secrets Manager). Na VPS produkcyjnym ustaw restrykcyjne uprawnienia: chmod 600 .env.
Jak wykonać rolling update bez przestoju w Docker Compose? +
Docker Compose (nie Swarm) nie ma wbudowanego rolling update. Strategie: (1) Blue-Green: odpal nową wersję na innym porcie, przestaw proxy (Nginx/Traefik), zatrzymaj starą. (2) Traefik jako reverse proxy z automatycznym service discovery — wykrywa nowe kontenery i przełącza ruch. (3) Dla Docker Swarm: deploy.update_config z parallelism=1 i delay. Najprostszy pattern dla Compose: najpierw docker compose pull, potem docker compose up -d (Compose zatrzyma i uruchomi zmienione serwisy z minimalnym przestojem).
Jaka jest różnica między named volumes a bind mounts? +
Named volumes (volumes: db_data:) są zarządzane przez Docker, przechowywane w /var/lib/docker/volumes/. Łatwiejsze w backupie (docker run --volumes-from), przenośne, działają lepiej na Linuksie (brak overhead filesystemu). Bind mounts (./data:/app/data) mapują katalog hosta bezpośrednio. Lepsze do developmentu (hot reload kodu), do konfiguracji na produkcji. W produkcji: named volumes dla danych (bazy, przesyłki), bind mounts dla plików konfiguracyjnych i certyfikatów.

Sprawdź oferty pasujące do tego scenariusza

Poniżej masz szybkie przejścia do ofert i stron z kodami rabatowymi tam, gdzie są dostępne.