Skip to main content
Docker is the recommended way to deploy n8n, providing a consistent environment and easy updates. This guide covers everything from simple deployments to production-ready setups.

Quick Start

Simple Docker Run

The fastest way to get n8n running:
1

Create a Docker volume

docker volume create n8n_data
This persists your workflows, credentials, and settings between container restarts.
2

Run n8n container

docker run -it --rm \
  --name n8n \
  -p 5678:5678 \
  -v n8n_data:/home/node/.n8n \
  ghcr.io/n8n-io/n8n
3

Access n8n

Open your browser to http://localhost:5678
The /home/node/.n8n folder contains critical data including:
  • Encryption key for credentials
  • Webhook URLs
  • SQLite database (default)
  • User settings and configuration
Always persist this folder or your credentials cannot be decrypted after restart!

Docker Compose Deployments

Single Instance with PostgreSQL

A production-ready single instance setup:
version: '3.8'

volumes:
  n8n_data:
  postgres_data:

services:
  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
    healthcheck:
      test: ['CMD-SHELL', 'pg_isready -U n8n']
      interval: 5s
      timeout: 5s
      retries: 10

  n8n:
    image: ghcr.io/n8n-io/n8n:latest
    restart: unless-stopped
    ports:
      - 5678:5678
    environment:
      - DB_TYPE=postgresdb
      - DB_POSTGRESDB_HOST=postgres
      - DB_POSTGRESDB_PORT=5432
      - DB_POSTGRESDB_DATABASE=n8n
      - DB_POSTGRESDB_USER=n8n
      - DB_POSTGRESDB_PASSWORD=${POSTGRES_PASSWORD}
      - N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
      - N8N_HOST=${N8N_HOST}
      - N8N_PROTOCOL=https
      - NODE_ENV=production
      - WEBHOOK_URL=https://${N8N_HOST}/
    volumes:
      - n8n_data:/home/node/.n8n
    depends_on:
      postgres:
        condition: service_healthy
Generate a secure encryption key:
openssl rand -base64 32
Store this key securely! If lost, you cannot decrypt existing credentials.

With External Task Runners

Deploy n8n with isolated task runners for enhanced security:
version: '3.8'

volumes:
  n8n_data:
  postgres_data:

services:
  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
    healthcheck:
      test: ['CMD-SHELL', 'pg_isready -U n8n']
      interval: 5s
      timeout: 5s
      retries: 10

  n8n:
    image: ghcr.io/n8n-io/n8n:latest
    restart: unless-stopped
    ports:
      - 5678:5678
    environment:
      - DB_TYPE=postgresdb
      - DB_POSTGRESDB_HOST=postgres
      - DB_POSTGRESDB_DATABASE=n8n
      - DB_POSTGRESDB_USER=n8n
      - DB_POSTGRESDB_PASSWORD=${POSTGRES_PASSWORD}
      - N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
      # Task Runner configuration
      - N8N_RUNNERS_MODE=external
      - N8N_RUNNERS_BROKER_LISTEN_ADDRESS=0.0.0.0
      - N8N_RUNNERS_AUTH_TOKEN=${RUNNERS_AUTH_TOKEN}
      - N8N_RUNNERS_MAX_CONCURRENCY=10
    volumes:
      - n8n_data:/home/node/.n8n
    depends_on:
      postgres:
        condition: service_healthy

  n8n-runner:
    image: ghcr.io/n8n-io/runners:latest
    restart: unless-stopped
    environment:
      - N8N_RUNNERS_TASK_BROKER_URI=http://n8n:5679
      - N8N_RUNNERS_AUTH_TOKEN=${RUNNERS_AUTH_TOKEN}
    depends_on:
      n8n:
        condition: service_healthy
    # Scale runners as needed
    deploy:
      replicas: 2

Queue Mode (Scaling Setup)

Deploy n8n in queue mode with Redis and multiple workers:
version: '3.8'

volumes:
  n8n_data:
  postgres_data:
  redis_data:

services:
  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
    healthcheck:
      test: ['CMD-SHELL', 'pg_isready -U n8n']
      interval: 5s
      timeout: 5s
      retries: 10

  redis:
    image: redis:6.2.14-alpine
    restart: unless-stopped
    volumes:
      - redis_data:/data
    command: redis-server --appendonly yes
    healthcheck:
      test: ['CMD', 'redis-cli', 'ping']
      interval: 5s
      timeout: 3s
      retries: 5

  n8n:
    image: ghcr.io/n8n-io/n8n:latest
    restart: unless-stopped
    ports:
      - 5678:5678
    environment:
      - DB_TYPE=postgresdb
      - DB_POSTGRESDB_HOST=postgres
      - DB_POSTGRESDB_DATABASE=n8n
      - DB_POSTGRESDB_USER=n8n
      - DB_POSTGRESDB_PASSWORD=${POSTGRES_PASSWORD}
      - N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
      # Queue mode configuration
      - EXECUTIONS_MODE=queue
      - QUEUE_BULL_REDIS_HOST=redis
      - QUEUE_BULL_REDIS_PORT=6379
      - QUEUE_BULL_REDIS_DB=0
      # Metrics
      - N8N_METRICS=true
    volumes:
      - n8n_data:/home/node/.n8n
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy

  n8n-worker:
    image: ghcr.io/n8n-io/n8n:latest
    restart: unless-stopped
    command: worker
    environment:
      - DB_TYPE=postgresdb
      - DB_POSTGRESDB_HOST=postgres
      - DB_POSTGRESDB_DATABASE=n8n
      - DB_POSTGRESDB_USER=n8n
      - DB_POSTGRESDB_PASSWORD=${POSTGRES_PASSWORD}
      - N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
      # Queue mode configuration
      - EXECUTIONS_MODE=queue
      - QUEUE_BULL_REDIS_HOST=redis
      - QUEUE_BULL_REDIS_PORT=6379
      - QUEUE_HEALTH_CHECK_ACTIVE=true
      # Worker concurrency
      - N8N_CONCURRENCY_PRODUCTION_LIMIT=10
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
    # Scale workers as needed
    deploy:
      replicas: 2
Worker Scaling: Adjust deploy.replicas based on your execution volume. Monitor CPU and memory usage to determine the optimal number of workers.

Docker Image Options

n8n provides multiple Docker images:

ghcr.io/n8n-io/n8n

Official n8n image from GitHub Container Registry.Tags:
  • latest - Latest stable release
  • 1.x.x - Specific version (e.g., 1.25.0)
  • next - Latest unstable/beta release
# Pull latest stable
docker pull ghcr.io/n8n-io/n8n:latest

# Pull specific version
docker pull ghcr.io/n8n-io/n8n:1.25.0

# Pull next/beta
docker pull ghcr.io/n8n-io/n8n:next

Environment Variables for Docker

Key environment variables for Docker deployments:
# PostgreSQL (recommended for production)
DB_TYPE=postgresdb
DB_POSTGRESDB_HOST=postgres
DB_POSTGRESDB_PORT=5432
DB_POSTGRESDB_DATABASE=n8n
DB_POSTGRESDB_USER=n8n
DB_POSTGRESDB_PASSWORD=secure-password
DB_POSTGRESDB_SCHEMA=public

# SQLite (default, development only)
DB_TYPE=sqlite
DB_SQLITE_DATABASE=database.sqlite
EXECUTIONS_MODE=queue
QUEUE_BULL_REDIS_HOST=redis
QUEUE_BULL_REDIS_PORT=6379
QUEUE_BULL_REDIS_DB=0
QUEUE_BULL_REDIS_PASSWORD=redis-password  # if using auth
QUEUE_HEALTH_CHECK_ACTIVE=true
# n8n main process
N8N_RUNNERS_MODE=external
N8N_RUNNERS_BROKER_LISTEN_ADDRESS=0.0.0.0
N8N_RUNNERS_BROKER_PORT=5679
N8N_RUNNERS_AUTH_TOKEN=your-secure-token
N8N_RUNNERS_MAX_CONCURRENCY=10

# Runner process
N8N_RUNNERS_TASK_BROKER_URI=http://n8n:5679
N8N_RUNNERS_AUTH_TOKEN=your-secure-token
N8N_ENCRYPTION_KEY=your-secure-key-min-10-chars
N8N_HOST=your-domain.com
N8N_PROTOCOL=https
N8N_PORT=5678
WEBHOOK_URL=https://your-domain.com/

Volume Mounts

Critical Data LocationsThe /home/node/.n8n directory contains:
  • config - Instance configuration
  • database.sqlite - Default database (if using SQLite)
  • .n8n.settings.json - Encryption key and settings
Always mount this directory to preserve data between restarts!
volumes:
  # Primary data directory (required)
  - n8n_data:/home/node/.n8n
  
  # Custom certificates (optional)
  - ./custom-certs:/opt/custom-certificates:ro
  
  # Custom nodes (optional)
  - ./custom-nodes:/home/node/.n8n/custom

Updating n8n

1

Pull the latest image

docker compose pull
2

Stop and remove old containers

docker compose down
This preserves your data volumes. Your workflows and credentials remain safe.
3

Start with new image

docker compose up -d
4

Verify the update

docker compose logs -f n8n
Check for successful startup and database migrations.
Before Updating:
  1. Check Breaking Changes
  2. Backup your database and encryption key
  3. Test updates in a staging environment first
  4. Plan for brief downtime during the update

Health Checks

n8n exposes a health check endpoint at /healthz:
healthcheck:
  test: ['CMD-SHELL', 'wget --spider -q http://localhost:5678/healthz || exit 1']
  interval: 5s
  timeout: 5s
  retries: 10
  start_period: 30s
The health endpoint checks:
  • Database connectivity
  • Redis connectivity (queue mode)
  • Application readiness
Returns HTTP 200 when healthy, 503 when unhealthy.

Timezone Configuration

Configure timezone for scheduled workflows:
# Set both for consistency
docker run \
  -e GENERIC_TIMEZONE="Europe/Berlin" \
  -e TZ="Europe/Berlin" \
  ghcr.io/n8n-io/n8n
  • GENERIC_TIMEZONE - Used by n8n’s Schedule node
  • TZ - System timezone for container commands

Custom SSL Certificates

Trust custom SSL certificates:
services:
  n8n:
    volumes:
      - ./custom-certs:/opt/custom-certificates:ro
    environment:
      - NODE_OPTIONS=--use-openssl-ca
      - SSL_CERT_DIR=/opt/custom-certificates
The entrypoint script automatically runs c_rehash on the certificate directory.

Troubleshooting

# Check logs
docker compose logs -f n8n

# Common issues:
# 1. Port 5678 already in use
# 2. Database connection failed
# 3. Invalid encryption key
# 4. Insufficient permissions
This happens when:
  • Encryption key changed or lost
  • /home/node/.n8n volume not mounted
  • Different encryption key between containers
Solution: Ensure consistent N8N_ENCRYPTION_KEY and persistent volumes.
# Verify Redis connection
docker compose exec redis redis-cli ping

# Check worker logs
docker compose logs -f n8n-worker

# Verify same encryption key and database
docker compose exec n8n env | grep N8N_ENCRYPTION_KEY
docker compose exec n8n-worker env | grep N8N_ENCRYPTION_KEY
# Set resource limits
services:
  n8n:
    deploy:
      resources:
        limits:
          memory: 2G
        reservations:
          memory: 1G
Also consider:
  • Reducing N8N_CONCURRENCY_PRODUCTION_LIMIT
  • Adding more workers instead of increasing main process memory
  • Enabling execution data pruning

Next Steps

Configuration

Deep dive into all configuration options

Scaling

Learn about scaling with queue mode