DEV Community

Cover image for Setting up n8n with Docker: The Complete Guide
Brooke Harris
Brooke Harris

Posted on

Setting up n8n with Docker: The Complete Guide

Docker has become the gold standard for deploying applications in consistent, isolated environments, and n8n is no exception. Setting up n8n with Docker offers numerous advantages including easy deployment, consistent environments across different systems, simplified updates, and excellent scalability options. This comprehensive guide will walk you through everything you need to know about running n8n with Docker, from basic setups to production-ready deployments.

Why Choose Docker for n8n?
Docker provides several compelling advantages for n8n deployment:

Consistency and Isolation
Docker ensures n8n runs in a clean, isolated environment regardless of your host system. This eliminates compatibility issues and provides consistent behavior across development, staging, and production environments.

Easy Deployment and Updates
With Docker, deploying n8n is as simple as running a single command. Updates are equally straightforward – just pull the latest image and restart your container.

Scalability
Docker makes it easy to scale n8n horizontally by running multiple instances or implementing queue mode for high-throughput scenarios.

Database Integration
Docker Compose allows you to easily integrate n8n with databases like PostgreSQL, creating a complete automation stack with minimal configuration.

Prerequisites
Before starting, ensure you have:

Docker: Latest version of Docker Desktop (Windows/Mac) or Docker Engine (Linux)
Docker Compose: Included with Docker Desktop or installed separately on Linux
Basic Command Line Knowledge: Familiarity with terminal/command prompt
System Resources: At least 2GB RAM and 10GB free disk space
Installing Docker
Windows and macOS
Download Docker Desktop from the official Docker website and follow the installation instructions.

Linux (Ubuntu/Debian)
Copy code

Remove old Docker versions

for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do
sudo apt-get remove $pkg
done

Install prerequisites

sudo apt-get update
sudo apt-get install ca-certificates curl

Add Docker's official GPG key

sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

Add Docker repository

echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}") stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

Install Docker

sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
Verify your installation:

Copy code
docker --version
docker compose version
Method 1: Simple Docker Run (Quick Start)
The fastest way to get n8n running with Docker is using a simple docker run command:

Basic Setup
Copy code

Create a volume for persistent data

docker volume create n8n_data

Run n8n container

docker run -it --rm \
--name n8n \
-p 5678:5678 \
-v n8n_data:/home/node/.n8n \
docker.n8n.io/n8nio/n8n
This command:

Creates a named volume n8n_data for persistent storage
Maps port 5678 from the container to your host
Mounts the volume to preserve your workflows and settings
Uses the official n8n Docker image
Access n8n by opening http://localhost:5678 in your browser.

With Environment Variables
Copy code
docker run -it --rm \
--name n8n \
-p 5678:5678 \
-e GENERIC_TIMEZONE="America/New_York" \
-e TZ="America/New_York" \
-v n8n_data:/home/node/.n8n \
docker.n8n.io/n8nio/n8n
With PostgreSQL Database
Copy code
docker run -it --rm \
--name n8n \
-p 5678:5678 \
-e DB_TYPE=postgresdb \
-e DB_POSTGRESDB_DATABASE=n8n \
-e DB_POSTGRESDB_HOST=your-postgres-host \
-e DB_POSTGRESDB_PORT=5432 \
-e DB_POSTGRESDB_USER=n8n_user \
-e DB_POSTGRESDB_PASSWORD=your-password \
-e DB_POSTGRESDB_SCHEMA=public \
-v n8n_data:/home/node/.n8n \
docker.n8n.io/n8nio/n8n
Method 2: Docker Compose (Recommended)
Docker Compose provides a more manageable way to run n8n, especially when integrating with databases and other services.

Basic Docker Compose Setup
Create a project directory:

Copy code
mkdir n8n-docker
cd n8n-docker
Create a docker-compose.yml file:

Copy code
version: '3.8'

services:
n8n:
image: docker.n8n.io/n8nio/n8n
restart: always
ports:
- "5678:5678"
environment:
- N8N_HOST=localhost
- N8N_PORT=5678
- N8N_PROTOCOL=http
- NODE_ENV=production
- GENERIC_TIMEZONE=America/New_York
volumes:
- n8n_data:/home/node/.n8n
- ./local-files:/files

volumes:
n8n_data:
Start the services:

Copy code
docker compose up -d
Production-Ready Setup with PostgreSQL
For production environments, use PostgreSQL for better performance and reliability:

Create an .env file:

Copy code

Database Configuration

POSTGRES_DB=n8n
POSTGRES_USER=n8n_user
POSTGRES_PASSWORD=your_secure_password

n8n Configuration

N8N_HOST=your-domain.com
N8N_PORT=5678
N8N_PROTOCOL=https
GENERIC_TIMEZONE=America/New_York
WEBHOOK_URL=https://your-domain.com/

Security

N8N_ENCRYPTION_KEY=your-encryption-key-here
Create a comprehensive docker-compose.yml:

Copy code
version: '3.8'

services:
postgres:
image: postgres:15
restart: always
environment:
- POSTGRES_DB=${POSTGRES_DB}
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ['CMD-SHELL', 'pg_isready -h localhost -U ${POSTGRES_USER} -d ${POSTGRES_DB}']
interval: 5s
timeout: 5s
retries: 10

n8n:
image: docker.n8n.io/n8nio/n8n
restart: always
ports:
- "5678:5678"
environment:
- DB_TYPE=postgresdb
- DB_POSTGRESDB_DATABASE=${POSTGRES_DB}
- DB_POSTGRESDB_HOST=postgres
- DB_POSTGRESDB_PORT=5432
- DB_POSTGRESDB_USER=${POSTGRES_USER}
- DB_POSTGRESDB_PASSWORD=${POSTGRES_PASSWORD}
- DB_POSTGRESDB_SCHEMA=public
- N8N_HOST=${N8N_HOST}
- N8N_PORT=${N8N_PORT}
- N8N_PROTOCOL=${N8N_PROTOCOL}
- NODE_ENV=production
- WEBHOOK_URL=${WEBHOOK_URL}
- GENERIC_TIMEZONE=${GENERIC_TIMEZONE}
- N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
volumes:
- n8n_data:/home/node/.n8n
- ./local-files:/files
depends_on:
postgres:
condition: service_healthy

volumes:
n8n_data:
postgres_data:
Method 3: Production Setup with SSL/TLS (Traefik)
For production deployments with automatic SSL certificates, use Traefik as a reverse proxy:

Environment Configuration
Create an .env file:

Copy code

Domain Configuration

DOMAIN_NAME=example.com
SUBDOMAIN=n8n
SSL_EMAIL=admin@example.com

Database Configuration

POSTGRES_DB=n8n
POSTGRES_USER=n8n_user
POSTGRES_PASSWORD=your_secure_password

n8n Configuration

GENERIC_TIMEZONE=America/New_York
N8N_ENCRYPTION_KEY=your-encryption-key-here
Complete Production Docker Compose
Copy code
version: '3.8'

services:
traefik:
image: traefik:v3.0
restart: always
command:
- "--api.insecure=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
- "--entrypoints.web.http.redirections.entryPoint.to=websecure"
- "--entrypoints.web.http.redirections.entrypoint.scheme=https"
- "--entrypoints.websecure.address=:443"
- "--certificatesresolvers.mytlschallenge.acme.tlschallenge=true"
- "--certificatesresolvers.mytlschallenge.acme.email=${SSL_EMAIL}"
- "--certificatesresolvers.mytlschallenge.acme.storage=/letsencrypt/acme.json"
ports:
- "80:80"
- "443:443"
volumes:
- traefik_data:/letsencrypt
- /var/run/docker.sock:/var/run/docker.sock:ro

postgres:
image: postgres:15
restart: always
environment:
- POSTGRES_DB=${POSTGRES_DB}
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ['CMD-SHELL', 'pg_isready -h localhost -U ${POSTGRES_USER} -d ${POSTGRES_DB}']
interval: 5s
timeout: 5s
retries: 10

n8n:
image: docker.n8n.io/n8nio/n8n
restart: always
ports:
- "127.0.0.1:5678:5678"
labels:
- traefik.enable=true
- traefik.http.routers.n8n.rule=Host(${SUBDOMAIN}.${DOMAIN_NAME})
- traefik.http.routers.n8n.tls=true
- traefik.http.routers.n8n.entrypoints=web,websecure
- traefik.http.routers.n8n.tls.certresolver=mytlschallenge
- traefik.http.middlewares.n8n.headers.SSLRedirect=true
- traefik.http.middlewares.n8n.headers.STSSeconds=315360000
- traefik.http.middlewares.n8n.headers.browserXSSFilter=true
- traefik.http.middlewares.n8n.headers.contentTypeNosniff=true
- traefik.http.middlewares.n8n.headers.forceSTSHeader=true
- traefik.http.middlewares.n8n.headers.SSLHost=${DOMAIN_NAME}
- traefik.http.middlewares.n8n.headers.STSIncludeSubdomains=true
- traefik.http.middlewares.n8n.headers.STSPreload=true
- traefik.http.routers.n8n.middlewares=n8n@docker
environment:
- DB_TYPE=postgresdb
- DB_POSTGRESDB_DATABASE=${POSTGRES_DB}
- DB_POSTGRESDB_HOST=postgres
- DB_POSTGRESDB_PORT=5432
- DB_POSTGRESDB_USER=${POSTGRES_USER}
- DB_POSTGRESDB_PASSWORD=${POSTGRES_PASSWORD}
- DB_POSTGRESDB_SCHEMA=public
- N8N_HOST=${SUBDOMAIN}.${DOMAIN_NAME}
- N8N_PORT=5678
- N8N_PROTOCOL=https
- NODE_ENV=production
- WEBHOOK_URL=https://${SUBDOMAIN}.${DOMAIN_NAME}/
- GENERIC_TIMEZONE=${GENERIC_TIMEZONE}
- N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
volumes:
- n8n_data:/home/node/.n8n
- ./local-files:/files
depends_on:
postgres:
condition: service_healthy

volumes:
n8n_data:
postgres_data:
traefik_data:
Essential Environment Variables
Core Configuration
Copy code

Basic Settings

N8N_HOST=localhost # Hostname for n8n
N8N_PORT=5678 # Port number
N8N_PROTOCOL=http # Protocol (http/https)
NODE_ENV=production # Environment mode

Timezone

GENERIC_TIMEZONE=America/New_York # Timezone for scheduling
TZ=America/New_York # System timezone

Security

N8N_ENCRYPTION_KEY=your-key-here # Encryption key for credentials
Database Configuration
Copy code

PostgreSQL

DB_TYPE=postgresdb
DB_POSTGRESDB_DATABASE=n8n
DB_POSTGRESDB_HOST=postgres
DB_POSTGRESDB_PORT=5432
DB_POSTGRESDB_USER=n8n_user
DB_POSTGRESDB_PASSWORD=secure_password
DB_POSTGRESDB_SCHEMA=public
Webhook Configuration
Copy code
WEBHOOK_URL=https://your-domain.com/ # Base URL for webhooks
N8N_PAYLOAD_SIZE_MAX=16 # Max payload size in MB
Performance Settings
Copy code
EXECUTIONS_TIMEOUT=3600 # Execution timeout in seconds
EXECUTIONS_TIMEOUT_MAX=3600 # Maximum execution timeout
N8N_CONCURRENCY_PRODUCTION=10 # Concurrent executions
Security Best Practices

  1. Use Strong Encryption Keys Generate a secure encryption key:

Copy code
openssl rand -base64 32

  1. Secure Database Credentials Use strong, unique passwords Consider using Docker secrets for sensitive data Regularly rotate credentials
  2. Network Security Copy code # Restrict database access postgres: # ... other config networks:
    • internal

networks:
internal:
driver: bridge
internal: true

  1. File Permissions Copy code # Create local-files directory with proper permissions mkdir -p local-files chmod 755 local-files
  2. Regular Updates Copy code # Update to latest version docker compose pull docker compose up -d Advanced Configurations Queue Mode for High Performance For high-throughput scenarios, enable queue mode:

Copy code
services:
redis:
image: redis:7-alpine
restart: always
volumes:
- redis_data:/data

n8n-main:
image: docker.n8n.io/n8nio/n8n
restart: always
environment:
- QUEUE_BULL_REDIS_HOST=redis
- EXECUTIONS_MODE=queue
# ... other config

n8n-worker:
image: docker.n8n.io/n8nio/n8n
restart: always
command: worker
environment:
- QUEUE_BULL_REDIS_HOST=redis
- EXECUTIONS_MODE=queue
# ... other config

volumes:
redis_data:
Custom Node Modules
To add custom npm packages:

Copy code
FROM docker.n8n.io/n8nio/n8n

USER root
RUN npm install -g your-custom-package
USER node
Monitoring and Logging
Copy code
services:
n8n:
# ... other config
environment:
- N8N_LOG_LEVEL=info
- N8N_LOG_OUTPUT=console
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
Maintenance and Operations
Backup Strategies
Copy code

Backup volumes

docker run --rm -v n8n_data:/data -v $(pwd):/backup alpine tar czf /backup/n8n-backup.tar.gz /data

Backup database

docker compose exec postgres pg_dump -U n8n_user n8n > backup.sql
Updates and Rollbacks
Copy code

Update to latest version

docker compose pull
docker compose up -d

Rollback to specific version

docker compose down

Edit docker-compose.yml to specify version

docker compose up -d
Monitoring
Copy code

View logs

docker compose logs -f n8n

Monitor resource usage

docker stats

Health checks

docker compose ps
Troubleshooting Common Issues
Container Won't Start
Copy code

Check logs

docker compose logs n8n

Verify environment variables

docker compose config

Check port conflicts

netstat -tulpn | grep 5678
Database Connection Issues
Copy code

Test database connectivity

docker compose exec n8n ping postgres

Check database logs

docker compose logs postgres

Verify credentials

docker compose exec postgres psql -U n8n_user -d n8n
Performance Issues
Increase container memory limits
Optimize database queries
Enable queue mode for high throughput
Monitor resource usage
SSL Certificate Issues
Copy code

Check Traefik logs

docker compose logs traefik

Verify domain DNS

nslookup your-domain.com

Check certificate status

docker compose exec traefik cat /letsencrypt/acme.json
Conclusion
Setting up n8n with Docker provides a robust, scalable, and maintainable automation platform. Whether you're starting with a simple single-container setup or deploying a production-ready system with SSL, databases, and queue processing, Docker offers the flexibility to meet your needs.

The key to success is starting simple and gradually adding complexity as your requirements grow. Begin with the basic Docker Compose setup, then enhance it with PostgreSQL for better performance, add SSL/TLS for security, and implement queue mode for high-throughput scenarios.

Remember to follow security best practices, maintain regular backups, and keep your installation updated. With proper setup and maintenance, your Dockerized n8n instance will provide reliable workflow automation for years to come.

The examples and configurations provided in this guide serve as a solid foundation, but don't hesitate to customize them based on your specific requirements. The n8n community and official documentation are excellent resources for additional guidance and troubleshooting support.

Top comments (0)