Running n8n in production requires reliable deployment, scaling, and maintenance strategies. Docker containers provide the ideal platform for deploying n8n with consistency across environments, easy scaling, and simplified operations. This guide covers Docker deployment patterns for n8n, from basic single-container setups to production-grade multi-container architectures with external databases, reverse proxies, and monitoring solutions.
Why Docker for n8n Production Deployments?
Docker offers several advantages for n8n production deployments:
- Consistency across environments — Same container runs in dev, staging, production
- Isolation and security — n8n runs in isolated container with limited host access
- Easy scaling — Scale containers horizontally with orchestration tools
- Simplified updates — Update n8n version by pulling new container image
- Resource efficiency — Share host kernel, lower overhead than VMs
- Portability — Run on any Docker-compatible platform (cloud, on-prem, local)
Basic n8n Docker Deployment
Simple Docker Run Command
# Basic n8n Docker run command
docker run -d \
--name n8n \
-p 5678:5678 \
-v n8n_data:/home/node/.n8n \
-e N8N_BASIC_AUTH_ACTIVE=true \
-e N8N_BASIC_AUTH_USER=admin \
-e N8N_BASIC_AUTH_PASSWORD=securepassword \
n8nio/n8n
Docker Compose for Development
# docker-compose.yml for n8n with PostgreSQL
version: '3.8'
services:
n8n:
image: n8nio/n8n
container_name: n8n
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=n8n_password
- N8N_BASIC_AUTH_ACTIVE=true
- N8N_BASIC_AUTH_USER=admin
- N8N_BASIC_AUTH_PASSWORD=securepassword
- N8N_HOST=localhost
- N8N_PORT=5678
- N8N_PROTOCOL=http
- WEBHOOK_URL=http://localhost:5678/
volumes:
- n8n_data:/home/node/.n8n
depends_on:
- postgres
networks:
- n8n_network
postgres:
image: postgres:15
container_name: n8n_postgres
restart: unless-stopped
environment:
- POSTGRES_USER=n8n
- POSTGRES_PASSWORD=n8n_password
- POSTGRES_DB=n8n
volumes:
- postgres_data:/var/lib/postgresql/data
networks:
- n8n_network
volumes:
n8n_data:
postgres_data:
networks:
n8n_network:
driver: bridge
Production n8n Docker Architecture
Multi-Container Production Setup
# Production docker-compose.yml with Traefik, Redis, and monitoring
version: '3.8'
services:
traefik:
image: traefik:v3.0
container_name: traefik
command:
- "--api.insecure=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--certificatesresolvers.letsencrypt.acme.tlschallenge=true"
- "--certificatesresolvers.letsencrypt.acme.email=admin@example.com"
- "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
ports:
- "80:80"
- "443:443"
- "8080:8080"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
- "./letsencrypt:/letsencrypt"
networks:
- n8n_network
n8n:
image: n8nio/n8n
container_name: n8n
restart: unless-stopped
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_BASIC_AUTH_ACTIVE=true
- N8N_BASIC_AUTH_USER=${N8N_USER}
- N8N_BASIC_AUTH_PASSWORD=${N8N_PASSWORD}
- N8N_HOST=n8n.example.com
- N8N_PORT=5678
- N8N_PROTOCOL=https
- WEBHOOK_URL=https://n8n.example.com/
- EXECUTIONS_DATA_PRUNE=true
- EXECUTIONS_DATA_MAX_AGE=168
- QUEUE_BULL_REDIS_HOST=redis
- QUEUE_BULL_REDIS_PORT=6379
- EXECUTIONS_MODE=queue
volumes:
- n8n_data:/home/node/.n8n
labels:
- "traefik.enable=true"
- "traefik.http.routers.n8n.rule=Host(`n8n.example.com`)"
- "traefik.http.routers.n8n.entrypoints=websecure"
- "traefik.http.routers.n8n.tls.certresolver=letsencrypt"
- "traefik.http.services.n8n.loadbalancer.server.port=5678"
depends_on:
- postgres
- redis
networks:
- n8n_network
postgres:
image: postgres:15
container_name: n8n_postgres
restart: unless-stopped
environment:
- POSTGRES_USER=n8n
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- POSTGRES_DB=n8n
volumes:
- postgres_data:/var/lib/postgresql/data
- ./backup:/backup
command: >
postgres -c max_connections=200
-c shared_buffers=256MB
-c effective_cache_size=1GB
networks:
- n8n_network
redis:
image: redis:7-alpine
container_name: n8n_redis
restart: unless-stopped
command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD}
volumes:
- redis_data:/data
networks:
- n8n_network
pgadmin:
image: dpage/pgadmin4
container_name: pgadmin
restart: unless-stopped
environment:
- PGADMIN_DEFAULT_EMAIL=admin@example.com
- PGADMIN_DEFAULT_PASSWORD=${PGADMIN_PASSWORD}
volumes:
- pgadmin_data:/var/lib/pgadmin
labels:
- "traefik.enable=true"
- "traefik.http.routers.pgadmin.rule=Host(`pgadmin.example.com`)"
- "traefik.http.routers.pgadmin.entrypoints=websecure"
- "traefik.http.routers.pgadmin.tls.certresolver=letsencrypt"
- "traefik.http.services.pgadmin.loadbalancer.server.port=80"
networks:
- n8n_network
volumes:
n8n_data:
postgres_data:
redis_data:
pgadmin_data:
networks:
n8n_network:
driver: bridge
n8n Docker Configuration Best Practices
Environment Variables Configuration
# .env file for n8n Docker deployment
# Database Configuration
DB_TYPE=postgresdb
DB_POSTGRESDB_HOST=postgres
DB_POSTGRESDB_PORT=5432
DB_POSTGRESDB_DATABASE=n8n
DB_POSTGRESDB_USER=n8n
DB_POSTGRESDB_PASSWORD=secure_db_password_here
# Authentication
N8N_BASIC_AUTH_ACTIVE=true
N8N_BASIC_AUTH_USER=admin
N8N_BASIC_AUTH_PASSWORD=secure_n8n_password_here
# Server Configuration
N8N_HOST=n8n.yourdomain.com
N8N_PORT=5678
N8N_PROTOCOL=https
WEBHOOK_URL=https://n8n.yourdomain.com/
# Execution Settings
EXECUTIONS_DATA_PRUNE=true
EXECUTIONS_DATA_MAX_AGE=168 # Keep execution data for 7 days
EXECUTIONS_DATA_PRUNE_MAX_COUNT=10000
# Queue Mode (for scaling)
EXECUTIONS_MODE=queue
QUEUE_BULL_REDIS_HOST=redis
QUEUE_BULL_REDIS_PORT=6379
QUEUE_BULL_REDIS_PASSWORD=secure_redis_password_here
# Security
N8N_ENCRYPTION_KEY=your-32-character-encryption-key-here
N8N_DIAGNOSTICS_ENABLED=false
# External hooks
EXTERNAL_HOOK_FILES=/home/node/.n8n/external-hooks.js
Volume Management for Data Persistence
# Volume configuration for data persistence
docker volume create n8n_data
docker volume create postgres_data
docker volume create redis_data
# Backup script for n8n data
#!/bin/bash
# backup-n8n.sh
BACKUP_DIR="/backup/n8n"
DATE=$(date +%Y%m%d_%H%M%S)
# Backup PostgreSQL database
docker exec n8n_postgres pg_dump -U n8n n8n > ${BACKUP_DIR}/n8n_db_${DATE}.sql
# Backup n8n configuration and workflows
docker run --rm --volumes-from n8n -v ${BACKUP_DIR}:/backup alpine \
tar czf /backup/n8n_data_${DATE}.tar.gz /home/node/.n8n
# Backup Redis data
docker exec n8n_redis redis-cli --rdb /data/dump.rdb
docker cp n8n_redis:/data/dump.rdb ${BACKUP_DIR}/redis_${DATE}.rdb
# Rotate old backups (keep 30 days)
find ${BACKUP_DIR} -name "*.sql" -mtime +30 -delete
find ${BACKUP_DIR} -name "*.tar.gz" -mtime +30 -delete
find ${BACKUP_DIR} -name "*.rdb" -mtime +30 -delete
Scaling n8n with Docker
Queue Mode for Horizontal Scaling
# docker-compose.scale.yml for multiple n8n workers
version: '3.8'
services:
n8n_web:
image: n8nio/n8n
container_name: n8n_web
restart: unless-stopped
environment:
- EXECUTIONS_MODE=queue
- N8N_PROTOCOL=https
- N8N_HOST=n8n.example.com
- WEBHOOK_URL=https://n8n.example.com/
# ... other environment variables
labels:
- "traefik.enable=true"
- "traefik.http.routers.n8n.rule=Host(`n8n.example.com`)"
- "traefik.http.services.n8n.loadbalancer.server.port=5678"
networks:
- n8n_network
n8n_worker_1:
image: n8nio/n8n
container_name: n8n_worker_1
restart: unless-stopped
environment:
- EXECUTIONS_MODE=queue
- N8N_PROTOCOL=https
- N8N_HOST=n8n.example.com
- WEBHOOK_URL=https://n8n.example.com/
# ... other environment variables
command: n8n worker
networks:
- n8n_network
n8n_worker_2:
image: n8nio/n8n
container_name: n8n_worker_2
restart: unless-stopped
environment:
- EXECUTIONS_MODE=queue
- N8N_PROTOCOL=https
- N8N_HOST=n8n.example.com
- WEBHOOK_URL=https://n8n.example.com/
# ... other environment variables
command: n8n worker
networks:
- n8n_network
# Add more workers as needed
n8n_worker_3:
image: n8nio/n8n
container_name: n8n_worker_3
restart: unless-stopped
environment:
- EXECUTIONS_MODE=queue
- N8N_PROTOCOL=https
- N8N_HOST=n8n.example.com
- WEBHOOK_URL=https://n8n.example.com/
# ... other environment variables
command: n8n worker
networks:
- n8n_network
Monitoring and Maintenance
Docker Health Checks
# Health check configuration for n8n
services:
n8n:
image: n8nio/n8n
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:5678/healthz"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
# ... other configuration
Logging Configuration
# Docker logging configuration
services:
n8n:
image: n8nio/n8n
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
tag: "n8n"
# ... other configuration
# View logs
docker logs n8n --tail 100 --follow
# Log aggregation with Loki
docker run --name loki -d -p 3100:3100 grafana/loki
Security Considerations
Docker Security Best Practices
- Non-root user — Run n8n as non-root user (n8n image does this by default)
- Read-only root filesystem — Mount volumes for writable directories
- Resource limits — Set CPU and memory limits
- Network segmentation — Use Docker networks to isolate services
- Regular updates — Keep Docker, n8n, and base images updated
Getting Started with n8n Docker Deployment
- Install Docker and Docker Compose — On your production server
- Create project directory — Organize configuration files
- Set up environment variables — Create .env file with secure values
- Configure docker-compose.yml — Start with basic setup, then add production features
- Initialize volumes — Create Docker volumes for data persistence
- Start services — docker-compose up -d
- Configure reverse proxy — Set up Traefik or Nginx for HTTPS
- Implement monitoring — Set up health checks and logging
- Create backup strategy — Regular backups of database and n8n data
- Test failover — Ensure services restart properly
Docker provides the ideal platform for running n8n in production, offering consistency, scalability, and operational simplicity. By following container best practices and implementing proper architecture patterns, you can deploy n8n with confidence, knowing that your workflow automation platform is reliable, secure, and maintainable.
Need Help Building Your Automation Workflows?
Our team specializes in designing and implementing production-grade automation systems using n8n and other enterprise tools.
Get Free Consultation