Back to Blog

Complete Guide to Running n8n on Docker: Setup, Configuration & Best Practices

TheDBAdmin Team8 min read
Complete Guide to Running n8n on Docker: Setup, Configuration & Best Practices

Learn how to deploy n8n workflow automation platform on Docker with production-ready configurations, security settings, and scaling strategies for business automation.

n8n is a powerful workflow automation platform that can transform your business processes. Running n8n on Docker provides scalability, consistency, and easy deployment. This comprehensive guide covers everything from basic setup to production-ready configurations.

Table of Contents

  1. Introduction to n8n and Docker
  2. Prerequisites and System Requirements
  3. Basic n8n Docker Setup
  4. Production Docker Compose Configuration
  5. Environment Variables and Security
  6. Database Configuration
  7. SSL/TLS Setup and Domain Configuration
  8. Scaling and Performance Optimization
  9. Backup and Monitoring Strategies
  10. Troubleshooting Common Issues

Introduction to n8n and Docker

n8n (pronounced "nodemation") is an open-source workflow automation tool that allows you to connect different services and automate repetitive tasks. Docker containerization provides:

  • Consistent Environment: Same configuration across development and production
  • Easy Scaling: Horizontal scaling with multiple containers
  • Isolation: Secure separation from host system
  • Version Control: Easy rollbacks and updates

Why Use Docker for n8n?

bash
# Benefits of Docker deployment
✅ Rapid deployment and scaling
✅ Environment consistency
✅ Easy backup and migration
✅ Resource isolation
✅ Simplified updates

Prerequisites and System Requirements

System Requirements

bash
# Minimum Requirements
- CPU: 2 cores
- RAM: 4GB
- Storage: 20GB SSD
- OS: Linux/Windows/macOS with Docker support

# Recommended for Production
- CPU: 4+ cores
- RAM: 8GB+
- Storage: 50GB+ SSD
- Load Balancer: Nginx/Traefik

Required Software

bash
# Install Docker and Docker Compose
# Ubuntu/Debian
sudo apt update
sudo apt install docker.io docker-compose

# CentOS/RHEL
sudo yum install docker docker-compose

# Verify installation
docker --version
docker-compose --version

Basic n8n Docker Setup

Quick Start with Docker Run

bash
# Basic n8n container
docker run -it --rm \
  --name n8n \
  -p 5678:5678 \
  -v ~/.n8n:/home/node/.n8n \
  n8nio/n8n

# With custom timezone
docker run -it --rm \
  --name n8n \
  -p 5678:5678 \
  -e GENERIC_TIMEZONE="America/New_York" \
  -v ~/.n8n:/home/node/.n8n \
  n8nio/n8n

Simple Docker Compose Setup

yaml
# docker-compose.yml
version: '3.8'

services:
  n8n:
    image: n8nio/n8n:latest
    container_name: n8n
    restart: unless-stopped
    ports:
      - "5678:5678"
    environment:
      - GENERIC_TIMEZONE=UTC
      - N8N_BASIC_AUTH_ACTIVE=true
      - N8N_BASIC_AUTH_USER=admin
      - N8N_BASIC_AUTH_PASSWORD=your_secure_password
    volumes:
      - n8n_data:/home/node/.n8n

volumes:
  n8n_data:
bash
# Start the service
docker-compose up -d

# Check status
docker-compose ps

# View logs
docker-compose logs -f n8n

Production Docker Compose Configuration

Complete Production Setup

yaml
# docker-compose.production.yml
version: '3.8'

services:
  # PostgreSQL Database
  postgres:
    image: postgres:15
    container_name: n8n_postgres
    restart: unless-stopped
    environment:
      POSTGRES_DB: n8n
      POSTGRES_USER: n8n_user
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
    volumes:
      - postgres_data:/var/lib/postgresql/data
    networks:
      - n8n_network
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U n8n_user -d n8n"]
      interval: 30s
      timeout: 10s
      retries: 3

  # n8n Application
  n8n:
    image: n8nio/n8n:latest
    container_name: n8n_app
    restart: unless-stopped
    depends_on:
      postgres:
        condition: service_healthy
    environment:
      # Database Configuration
      - DB_TYPE=postgresdb
      - DB_POSTGRESDB_HOST=postgres
      - DB_POSTGRESDB_PORT=5432
      - DB_POSTGRESDB_DATABASE=n8n
      - DB_POSTGRESDB_USER=n8n_user
      - DB_POSTGRESDB_PASSWORD=${POSTGRES_PASSWORD}
      
      # n8n Configuration
      - N8N_HOST=${N8N_HOST}
      - N8N_PORT=5678
      - N8N_PROTOCOL=https
      - WEBHOOK_URL=${WEBHOOK_URL}
      
      # Security
      - N8N_BASIC_AUTH_ACTIVE=false
      - N8N_USER_MANAGEMENT_DISABLED=false
      - N8N_JWT_AUTH_ACTIVE=true
      - N8N_JWT_AUTH_HEADER=authorization
      - N8N_JWT_AUTH_HEADER_VALUE_PREFIX=Bearer
      
      # Performance
      - EXECUTIONS_PROCESS=main
      - EXECUTIONS_DATA_PRUNE=true
      - EXECUTIONS_DATA_MAX_AGE=168
      - N8N_METRICS=true
      
      # Timezone
      - GENERIC_TIMEZONE=${TIMEZONE}
    volumes:
      - n8n_data:/home/node/.n8n
      - n8n_files:/files
    networks:
      - n8n_network
    labels:
      # Traefik labels for reverse proxy
      - "traefik.enable=true"
      - "traefik.http.routers.n8n.rule=Host(`${N8N_HOST}`)"
      - "traefik.http.routers.n8n.tls=true"
      - "traefik.http.routers.n8n.tls.certresolver=letsencrypt"

  # Redis for Queue Management
  redis:
    image: redis:7-alpine
    container_name: n8n_redis
    restart: unless-stopped
    volumes:
      - redis_data:/data
    networks:
      - n8n_network
    command: redis-server --appendonly yes

  # Traefik Reverse Proxy
  traefik:
    image: traefik:v3.0
    container_name: n8n_traefik
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - traefik_data:/data
    command:
      - --api.dashboard=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=${EMAIL}
      - --certificatesresolvers.letsencrypt.acme.storage=/data/acme.json
    networks:
      - n8n_network

volumes:
  n8n_data:
  n8n_files:
  postgres_data:
  redis_data:
  traefik_data:

networks:
  n8n_network:
    driver: bridge

Environment File (.env)

bash
# .env file for production
# Database
POSTGRES_PASSWORD=your_very_secure_password_here

# n8n Configuration
N8N_HOST=n8n.yourdomain.com
WEBHOOK_URL=https://n8n.yourdomain.com/
TIMEZONE=America/New_York

# SSL Certificate
[email protected]

# Security Keys (generate unique values)
N8N_ENCRYPTION_KEY=your_encryption_key_32_chars_long
N8N_USER_MANAGEMENT_JWT_SECRET=jwt_secret_key_here

Environment Variables and Security

Essential Security Variables

bash
# Authentication & Security
N8N_BASIC_AUTH_ACTIVE=true
N8N_BASIC_AUTH_USER=admin
N8N_BASIC_AUTH_PASSWORD=secure_password

# JWT Configuration
N8N_JWT_AUTH_ACTIVE=true
N8N_JWT_AUTH_HEADER=authorization
N8N_JWT_AUTH_HEADER_VALUE_PREFIX=Bearer

# Encryption
N8N_ENCRYPTION_KEY=your_32_character_encryption_key

# User Management
N8N_USER_MANAGEMENT_DISABLED=false
N8N_USER_MANAGEMENT_JWT_SECRET=jwt_secret

# CORS Settings
N8N_CORS_ORIGIN=https://yourdomain.com

Performance Optimization Variables

bash
# Execution Settings
EXECUTIONS_PROCESS=main
EXECUTIONS_TIMEOUT=3600
EXECUTIONS_TIMEOUT_MAX=14400

# Data Retention
EXECUTIONS_DATA_SAVE_ON_ERROR=all
EXECUTIONS_DATA_SAVE_ON_SUCCESS=all
EXECUTIONS_DATA_PRUNE=true
EXECUTIONS_DATA_MAX_AGE=168

# Metrics and Monitoring
N8N_METRICS=true
N8N_METRICS_PREFIX=n8n_

# Node.js Performance
NODE_OPTIONS=--max-old-space-size=4096

Database Configuration

PostgreSQL Setup

sql
-- Create n8n database and user
CREATE DATABASE n8n;
CREATE USER n8n_user WITH PASSWORD 'secure_password';
GRANT ALL PRIVILEGES ON DATABASE n8n TO n8n_user;

-- Optimize PostgreSQL for n8n
ALTER SYSTEM SET shared_preload_libraries = 'pg_stat_statements';
ALTER SYSTEM SET max_connections = 200;
ALTER SYSTEM SET shared_buffers = '256MB';
ALTER SYSTEM SET effective_cache_size = '1GB';

MySQL Configuration (Alternative)

yaml
# MySQL service in docker-compose
mysql:
  image: mysql:8.0
  container_name: n8n_mysql
  restart: unless-stopped
  environment:
    MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
    MYSQL_DATABASE: n8n
    MYSQL_USER: n8n_user
    MYSQL_PASSWORD: ${MYSQL_PASSWORD}
  volumes:
    - mysql_data:/var/lib/mysql
  command: --default-authentication-plugin=mysql_native_password
bash
# n8n MySQL environment variables
DB_TYPE=mysqldb
DB_MYSQLDB_HOST=mysql
DB_MYSQLDB_PORT=3306
DB_MYSQLDB_DATABASE=n8n
DB_MYSQLDB_USER=n8n_user
DB_MYSQLDB_PASSWORD=${MYSQL_PASSWORD}

SSL/TLS Setup and Domain Configuration

Nginx Reverse Proxy Configuration

nginx
# /etc/nginx/sites-available/n8n
server {
    listen 80;
    server_name n8n.yourdomain.com;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name n8n.yourdomain.com;

    ssl_certificate /etc/letsencrypt/live/n8n.yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/n8n.yourdomain.com/privkey.pem;

    # SSL Configuration
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512;
    ssl_prefer_server_ciphers off;

    # Security Headers
    add_header X-Frame-Options DENY;
    add_header X-Content-Type-Options nosniff;
    add_header X-XSS-Protection "1; mode=block";

    location / {
        proxy_pass http://localhost:5678;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_cache_bypass $http_upgrade;
    }
}

Let's Encrypt SSL Certificate

bash
# Install Certbot
sudo apt install certbot python3-certbot-nginx

# Obtain certificate
sudo certbot --nginx -d n8n.yourdomain.com

# Auto-renewal
sudo crontab -e
# Add: 0 12 * * * /usr/bin/certbot renew --quiet

Scaling and Performance Optimization

Horizontal Scaling Setup

yaml
# docker-compose.scale.yml
version: '3.8'

services:
  n8n-main:
    image: n8nio/n8n:latest
    environment:
      - EXECUTIONS_PROCESS=main
      - QUEUE_BULL_REDIS_HOST=redis
    depends_on:
      - redis
      - postgres

  n8n-worker:
    image: n8nio/n8n:latest
    command: n8n worker
    environment:
      - EXECUTIONS_PROCESS=own
      - QUEUE_BULL_REDIS_HOST=redis
    depends_on:
      - redis
      - postgres
    deploy:
      replicas: 3

  n8n-webhook:
    image: n8nio/n8n:latest
    command: n8n webhook
    environment:
      - EXECUTIONS_PROCESS=own
      - QUEUE_BULL_REDIS_HOST=redis
    ports:
      - "5679:5678"
    depends_on:
      - redis
      - postgres

Performance Monitoring

yaml
# Add monitoring services
  prometheus:
    image: prom/prometheus:latest
    container_name: n8n_prometheus
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
    ports:
      - "9090:9090"

  grafana:
    image: grafana/grafana:latest
    container_name: n8n_grafana
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=admin
    ports:
      - "3000:3000"
    volumes:
      - grafana_data:/var/lib/grafana

Backup and Monitoring Strategies

Database Backup Script

bash
#!/bin/bash
# backup-n8n.sh

# Configuration
BACKUP_DIR="/backups/n8n"
DATE=$(date +%Y%m%d_%H%M%S)
CONTAINER_NAME="n8n_postgres"

# Create backup directory
mkdir -p $BACKUP_DIR

# Database backup
docker exec $CONTAINER_NAME pg_dump -U n8n_user -d n8n | gzip > $BACKUP_DIR/n8n_db_$DATE.sql.gz

# n8n data backup
docker run --rm -v n8n_data:/data -v $BACKUP_DIR:/backup alpine tar czf /backup/n8n_data_$DATE.tar.gz -C /data .

# Cleanup old backups (keep last 7 days)
find $BACKUP_DIR -name "*.gz" -mtime +7 -delete

echo "Backup completed: $DATE"

Health Check Script

bash
#!/bin/bash
# health-check.sh

# Check n8n container health
if ! docker ps --filter "name=n8n_app" --filter "status=running" | grep -q n8n_app; then
    echo "n8n container is not running!"
    exit 1
fi

# Check n8n web interface
if ! curl -f http://localhost:5678/healthz > /dev/null 2>&1; then
    echo "n8n web interface is not responding!"
    exit 1
fi

echo "n8n is healthy"

Monitoring with Docker Healthcheck

yaml
# Add to n8n service in docker-compose
healthcheck:
  test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:5678/healthz"]
  interval: 30s
  timeout: 10s
  retries: 3
  start_period: 40s

Troubleshooting Common Issues

Container Won't Start

bash
# Check logs
docker-compose logs n8n

# Common issues and solutions:

# 1. Permission issues
sudo chown -R 1000:1000 /path/to/n8n/data

# 2. Port conflicts
netstat -tulpn | grep :5678
# Change port in docker-compose.yml

# 3. Memory issues
docker stats
# Increase memory allocation

Database Connection Issues

bash
# Test database connectivity
docker exec -it n8n_postgres psql -U n8n_user -d n8n -c "SELECT version();"

# Check environment variables
docker exec n8n_app env | grep DB_

# Recreate with correct settings
docker-compose down
docker-compose up -d

Performance Issues

bash
# Monitor resource usage
docker stats n8n_app

# Check execution logs
docker-compose logs -f n8n | grep -i error

# Optimize database
docker exec -it n8n_postgres psql -U n8n_user -d n8n -c "VACUUM ANALYZE;"

SSL Certificate Issues

bash
# Check certificate validity
openssl x509 -in /etc/letsencrypt/live/n8n.yourdomain.com/fullchain.pem -noout -dates

# Renew certificate
sudo certbot renew --dry-run

# Check Nginx configuration
sudo nginx -t

Conclusion

Running n8n on Docker provides a robust, scalable platform for workflow automation. This guide covered:

  • ✅ Basic and production Docker setups
  • ✅ Security configurations and best practices
  • ✅ Database setup and optimization
  • ✅ SSL/TLS configuration
  • ✅ Scaling strategies
  • ✅ Backup and monitoring solutions
  • ✅ Troubleshooting common issues

Next Steps

  1. Start with basic setup for development
  2. Implement production configuration for live environments
  3. Set up monitoring and backups for reliability
  4. Scale horizontally as your automation needs grow

Key Benefits Achieved

  • Reliable deployment with Docker containerization
  • Secure configuration with proper authentication
  • Scalable architecture for growing automation needs
  • Professional monitoring and backup strategies

Ready to automate your business processes with n8n on Docker? Start with our basic setup and gradually implement production features as your needs evolve.


Need help with n8n Docker deployment or want a custom automation solution? Contact our automation experts for professional setup and configuration services.

Written by

TheDBAdmin Team

KEEP LEARNING WITH THEDBADMIN

Turn this guide into a skill you can prove

Keep reading

Featured course · New batch

NextGen DBA + AI Engineer Bootcamp

Instructor-led, lab-first training for production DBAs: PostgreSQL, MongoDB, Docker, Kubernetes and AI.

  • Live labs on real execution plans
  • Backup, PITR & HA in production
  • pgvector, RAG & AI for DBAs

🛒 FROM THE SHOP

Building a Production-Style Cluster with Production-Style Cluster with Percona XtraDB Cluster, ProxySQL, and Keepalived

PDF · 35 pages

₹199₹5,00096% off

View product