Przejdź do treści

stack i tech

Docker + n8n: produkcyjnie, bez niespodzianek.

Docker to domyślna metoda uruchamiania n8n poza domowym laptopem. Poniżej opis produkcyjnego setup'u z Docker Compose, który stawiam u klientów: volumes, backup, upgrade, skalowanie poziome. Wszystko tak, żeby po handoff'ie Twój zespół nie błądził.

Ostatnia aktualizacja: 23 kwietnia 2026 Autor: Adrian Krawczyk

Dlaczego Docker dla n8n

Trzy powody, dla których Docker wygrywa z natywną instalacją n8n:

  • Powtarzalność środowiska: identyczny image n8n 1.76 działa tak samo u Ciebie, u mnie, na stagingu, na produkcji. Brak "u mnie na lokalu działa". Wersja node.js, libów systemowych, zależności Python jest zamrożona w obrazie.
  • Upgrade w jeden krok: docker compose pull && docker compose up -d. Rollback to cofnięcie tag'a obrazu. Bez Dockera aktualizacja n8n to manualne updaty node.js, npm, migrated bazy.
  • Izolacja od hosta: n8n nie dotyka systemowego node.js, nie instaluje globalnych pakietów, nie dopuszcza zewnętrznych skryptów do fs hosta bez wyraźnej konfiguracji volume. Bezpieczeństwo z pudełka.

Dla kogo Docker nie ma sensu: deweloperzy, którzy chcą grzebać w kodzie n8n (custom patches, forked repo). Dla 99 procent wdrożeń produkcyjnych Docker jest standardem.

Docker Compose stack produkcyjny

Minimalny plik docker-compose.yml, który stawiam u klienta:

services:
  n8n:
    image: n8nio/n8n:stable
    restart: unless-stopped
    env_file: .env
    environment:
      - N8N_HOST=workflow.klient.pl
      - N8N_PROTOCOL=https
      - WEBHOOK_URL=https://workflow.klient.pl/
      - DB_TYPE=postgresdb
      - DB_POSTGRESDB_HOST=postgres
      - QUEUE_BULL_REDIS_HOST=redis
      - EXECUTIONS_MODE=queue
    volumes:
      - n8n_data:/home/node/.n8n
    depends_on: [postgres, redis]
    labels:
      - "com.centurylinklabs.watchtower.enable=true"
  n8n-worker:
    image: n8nio/n8n:stable
    restart: unless-stopped
    command: worker
    env_file: .env
    depends_on: [redis, postgres]
  postgres:
    image: postgres:16-alpine
    restart: unless-stopped
    environment:
      - POSTGRES_DB=n8n
      - POSTGRES_USER=n8n
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
    volumes:
      - postgres_data:/var/lib/postgresql/data
  redis:
    image: redis:7-alpine
    restart: unless-stopped
    command: redis-server --requirepass ${REDIS_PASSWORD}
  caddy:
    image: caddy:2-alpine
    restart: unless-stopped
    ports: ["80:80", "443:443"]
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - caddy_data:/data
volumes:
  n8n_data:
  postgres_data:
  caddy_data:

Caddy jako reverse proxy przed n8n (automatic TLS z Let's Encrypt), Postgres i Redis w oddzielnych kontenerach. Worker oddzielony od main node dla queue mode. Watchtower label tylko dla n8n, żeby auto-aktualizacje nie poruszały bazy.

Volumes i co w nich siedzi

Trzy nazwane volumes, które absolutnie muszą być backupowane:

  • n8n_data: /home/node/.n8n wewnątrz kontenera. Zawiera: konfigurację user management, local SQLite (jeśli używasz SQLite zamiast Postgres), encryption key (jeśli nie explicite w env). Przy backup trzeba mieć cały katalog.
  • postgres_data: baza Postgres z wszystkimi workflow, executions, credentials (szyfrowane), user accounts. Główny backup target: pg_dump codziennie.
  • caddy_data: certyfikaty TLS i challenge state Let's Encrypt. Strata tego volumes to regeneracja certów przy następnym renewal, nic dramatycznego ale warto backupować.

Co nie potrzebuje backupu: redis (cache plus kolejka, można odtworzyć), logi Docker (ephemeral), metadata kontenerów.

Backup strategia, którą testuje się przy deploy'u

Backup bez testu restore to życzenie. Mój standard:

  • Postgres dump codziennie o 03:00: cron job w kontenerze postgres albo osobny kontener postgres-backup. pg_dump --format=custom z flagi -Fc, kompresja automatyczna.
  • Upload do Object Storage: GCS, S3, Hetzner Storage Box, Backblaze B2. Cokolwiek tanie i offsite. Retencja: 30 dni codziennych plus 12 miesięcznych plus 3 roczne (GFS grandfather-father-son).
  • Encryption key osobno: N8N_ENCRYPTION_KEY w Secret Manager, nie w backup. Bez tego klucza backup bazy jest bezużyteczny (credentials zaszyfrowane).
  • Test restore raz na kwartał: restore backup na staging environment, sprawdzam czy workflow'y się otwierają, czy credentials działają. Bez tego testu backup to niepotwierdzona obietnica.

Narzędzia: restic dla offsite backup z enkryp, pg_basebackup dla large baz (powyżej 100 GB). Dla małych wdrożeń prosty pg_dump | gzip | gpg | aws s3 cp w jednej linii.

Upgrade path między wersjami n8n

n8n wypuszcza nowy release co 2-4 tygodnie (patch) plus minor co 3-6 miesięcy. Mój upgrade workflow:

  1. Changelog review: przed każdym minor release (np. 1.76 → 1.80) czytam release notes. Breaking changes, deprecated nodes, migrations bazy.
  2. Test na staging: pull nowy image, restart staging stack, sprawdzam 5 krytycznych workflow'ów. Jeśli padły, rollback do poprzedniej wersji.
  3. Backup bazy przed produkcją: pg_dump bazy production PRZED aktualizacją. Gdyby coś poszło nie tak, rollback bazy plus obrazu.
  4. Rolling update production: docker compose pull n8n && docker compose up -d n8n. Worker nodes aktualizuję sekwencyjnie, nie wszystkie naraz (zero-downtime).
  5. Post-upgrade check: 15 minut obserwacji executions, czy nie ma nowych errorów, czy latency w normie.

Patch releases (np. 1.76.1 → 1.76.2) zwykle bezpieczne, minor releases (1.76 → 1.80) wymagają testu, major (1.x → 2.x) wymagałyby osobnego projektu migracyjnego.

Skalowanie od single-host po Kubernetes

Trzy poziomy skali, do których prowadzę klientów:

  • Poziom 1: single-host Docker Compose: VPS 2-4 vCPU, n8n plus n8n-worker plus Postgres plus Redis plus Caddy. Obsługuje do około 10 000 executions dziennie. 95 procent wdrożeń, z których korzystam, zostaje na tym poziomie.
  • Poziom 2: multi-host Docker Compose z managed DB: główny host dla n8n i Caddy, managed Postgres (Cloud SQL, RDS, Hetzner managed), osobny host dla worker nodes. Skaluje do około 100 000 executions dziennie. Potrzebne dla klientów z wysokim wolumenem.
  • Poziom 3: Kubernetes: n8n jako Deployment, worker jako osobny Deployment z HPA, Postgres jako StatefulSet albo managed cluster, Redis jako Sentinel/Cluster. Sensowne powyżej 100 000 executions dziennie i gdy klient ma już Kubernetes dla innych usług.

Migracja poziom 1 → 2 to zwykle 1-2 dni pracy. Poziom 2 → 3 to znacznie większy projekt (setup Helm charts, service mesh, monitoring, testing). Rzadko konieczne dla single tenant.

Najczęstsze pytania

Czy Docker Desktop na Windowsie wystarcza?

Dla developer workflow tak. Dla produkcji rekomenduję Linux server z Docker Engine (bez Desktop). Docker Desktop ma narzuty (VM Hyper-V albo WSL2), które na produkcji niepotrzebnie komplikują setup. Dla Windows serwerów preferuję natywne Docker for Windows w trybie Linux containers.

Czy używać watchtower do auto-update?

Tak dla patch releases, ostrożnie dla minor. Konfiguruję watchtower z flagą --label-enable i opóźnieniem 24-48 godzin po release (daje czas n8n.io na reakcję gdy release ma bug). Dla minor updatów wolę manual upgrade z pełnym testowaniem na stagingu.

Docker Compose v1 czy v2?

Zdecydowanie v2 (polecenie docker compose, nie docker-compose). v1 jest deprecated i nie dostaje bug fixów. Sprawdź wersję: docker compose version. Compose v2 plugin dla Docker Engine 20.10+.

Czy stawiać Postgres w kontenerze czy managed?

Dla małych wdrożeń (do 10 tysięcy executions dziennie) kontener w ramach tego samego stack'u wystarcza. Dla produkcji enterprise albo high-availability managed (Cloud SQL, RDS, DigitalOcean Managed PG) daje automatic backups, failover, point-in-time recovery. Koszt: 50-200 PLN miesięcznie zamiast 'za darmo' w kontenerze.

Jak bezpiecznie aktualizować Postgres między major versions?

Nigdy przez zwykłe docker compose pull postgres. Major upgrade Postgres wymaga pg_dump ze starej wersji i pg_restore do nowej (ewentualnie pg_upgrade offline). Planuję to jako osobny projekt, nie rutynowy update. W Compose trzymam się konkretnej major version (postgres:16-alpine, nie postgres:alpine).

Chcesz pogadać o konkretnym projekcie?

Warsztat otwierający to 90 minut, zdalnie albo w Poznaniu, bez zobowiązań. Mówimy, czy Twój proces nadaje się do automatyzacji i w jakiej skali.

napisz do mnie →