n8nen.nl logo n8nen.nl

N8N Docker Installatie: Complete Gids voor Container Deployment (2025)

2025-08-25 Sam H.T.
N8N Docker Installatie: Complete Gids voor Container Deployment (2025)
n8n Docker + N8N = ❤️ Container Geïsoleerd Schaalbaar Multi-instance Productie Enterprise-ready

🐳 Docker Power! Met Docker kun je N8N in enkele minuten deployen, schalen en beheren. Deze gids behandelt alles van basis installatie tot enterprise-ready setups met automatische backups, SSL en monitoring.

1. Waarom N8N met Docker? 🚀

Docker is de meest populaire deployment methode voor N8N, en daar zijn goede redenen voor:

✅ Voordelen van Docker

  • Snelle deployment: N8N draait binnen minuten
  • Isolatie: Geen conflicten met system packages
  • Portabiliteit: Draait overal waar Docker draait
  • Versie management: Makkelijk upgraden/downgraden
  • Schaalbaarheid: Multi-container setups mogelijk
  • Reproduceerbaar: Identieke environments

🎯 Perfect voor

  • Development: Lokale test omgevingen
  • Staging: Pre-productie testing
  • Productie: Enterprise deployments
  • CI/CD: Automated deployments
  • Cloud: AWS, Azure, GCP, DigitalOcean
  • On-premise: Eigen servers

2. Systeemvereisten & Voorbereiding 📋

Minimale Hardware Vereisten

Component Development Productie Enterprise
CPU 2 vCPU 4 vCPU 8+ vCPU
RAM 2 GB 4-8 GB 16+ GB
Storage 10 GB SSD 40 GB SSD 100+ GB SSD
OS Ubuntu 22.04+, Debian 11+, CentOS 8+, of Windows met WSL2

Docker Installatie

# Ubuntu/Debian - Officiële Docker installatie script
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh

# Voeg gebruiker toe aan docker groep (geen sudo nodig)
sudo usermod -aG docker $USER
newgrp docker

# Installeer Docker Compose v2
sudo apt-get update
sudo apt-get install docker-compose-plugin

# Verifieer installatie
docker --version
docker compose version

⚠️ Belangrijk voor Windows gebruikers

Gebruik WSL2 met Docker Desktop voor de beste ervaring. Native Windows containers worden niet ondersteund.

3. Quick Start: N8N in 5 Minuten ⚡

De snelste manier om N8N te starten met Docker:

Optie 1: Docker Run (Simpel)

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

# Met basic authentication
docker run -it --rm \
  --name n8n \
  -p 5678:5678 \
  -e N8N_BASIC_AUTH_ACTIVE=true \
  -e N8N_BASIC_AUTH_USER=admin \
  -e N8N_BASIC_AUTH_PASSWORD=password \
  -v ~/.n8n:/home/node/.n8n \
  n8nio/n8n

Open nu je browser en ga naar: http://localhost:5678

Optie 2: Docker Compose (Aanbevolen)

Maak een docker-compose.yml bestand:

version: '3.8'

services:
  n8n:
    image: n8nio/n8n:latest
    container_name: n8n
    restart: unless-stopped
    ports:
      - "5678:5678"
    environment:
      - N8N_BASIC_AUTH_ACTIVE=true
      - N8N_BASIC_AUTH_USER=admin
      - N8N_BASIC_AUTH_PASSWORD=changeme
      - N8N_ENCRYPTION_KEY=your-encryption-key-min-32-chars-long
      - TZ=Europe/Amsterdam
    volumes:
      - n8n_data:/home/node/.n8n
      - ./local-files:/files

volumes:
  n8n_data:

Start N8N met:

# Start in detached mode
docker compose up -d

# Bekijk logs
docker compose logs -f n8n

# Stop N8N
docker compose down

4. Docker Compose Configuratie 🔧

Voor productie gebruik je een uitgebreidere Docker Compose configuratie:

Complete docker-compose.yml

version: '3.8'

services:
  n8n:
    image: n8nio/n8n:1.64.0  # Gebruik altijd specifieke versies in productie!
    container_name: n8n
    restart: unless-stopped
    ports:
      - "5678:5678"
    environment:
      # Database configuratie
      - DB_TYPE=postgresdb
      - DB_POSTGRESDB_HOST=postgres
      - DB_POSTGRESDB_PORT=5432
      - DB_POSTGRESDB_DATABASE=n8n
      - DB_POSTGRESDB_USER=n8n
      - DB_POSTGRESDB_PASSWORD=${POSTGRES_PASSWORD}
      
      # Security
      - N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
      - N8N_BASIC_AUTH_ACTIVE=true
      - N8N_BASIC_AUTH_USER=${N8N_USER}
      - N8N_BASIC_AUTH_PASSWORD=${N8N_PASSWORD}
      
      # Network configuratie
      - N8N_HOST=0.0.0.0
      - N8N_PORT=5678
      - N8N_PROTOCOL=https
      - WEBHOOK_URL=https://n8n.jouwdomein.nl
      - N8N_EDITOR_BASE_URL=https://n8n.jouwdomein.nl
      
      # Performance
      - NODE_OPTIONS=--max-old-space-size=4096
      - N8N_DEFAULT_BINARY_DATA_MODE=filesystem
      - EXECUTIONS_DATA_PRUNE=true
      - EXECUTIONS_DATA_MAX_AGE=336
      
      # Timezone
      - TZ=Europe/Amsterdam
      - GENERIC_TIMEZONE=Europe/Amsterdam
      
      # Logging
      - N8N_LOG_LEVEL=info
      - N8N_LOG_OUTPUT=console
    volumes:
      - n8n_data:/home/node/.n8n
      - ./local-files:/files
      - ./backups:/backups
    depends_on:
      postgres:
        condition: service_healthy
    healthcheck:
      test: ["CMD", "wget", "--spider", "-q", "http://localhost:5678/healthz"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 30s
    deploy:
      resources:
        limits:
          memory: 4G
          cpus: '2'
        reservations:
          memory: 2G
          cpus: '1'

  postgres:
    image: postgres:15-alpine
    container_name: n8n-postgres
    restart: unless-stopped
    environment:
      - POSTGRES_DB=n8n
      - POSTGRES_USER=n8n
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
      - POSTGRES_NON_ROOT_USER=n8n
    volumes:
      - postgres_data:/var/lib/postgresql/data
      - ./init-db.sql:/docker-entrypoint-initdb.d/init.sql:ro
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U n8n -d n8n"]
      interval: 10s
      timeout: 5s
      retries: 5

volumes:
  n8n_data:
    driver: local
  postgres_data:
    driver: local

networks:
  default:
    name: n8n_network
    driver: bridge

.env File (Environment Variables)

Maak een .env bestand voor gevoelige informatie:

# Database
POSTGRES_PASSWORD=super_secure_database_password_here

# N8N Security
N8N_ENCRYPTION_KEY=your-32-character-encryption-key-minimum
N8N_USER=admin
N8N_PASSWORD=your_secure_admin_password

# External services (optional)
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USER=your-email@gmail.com
SMTP_PASS=your-app-password

🔐 Security Waarschuwing!

Voeg nooit je .env bestand toe aan Git! Voeg het toe aan .gitignore:

echo ".env" >> .gitignore

5. Database Setup (PostgreSQL/MySQL) 🗄️

Voor productie gebruik je altijd een externe database in plaats van SQLite:

PostgreSQL Setup (Aanbevolen)

version: '3.8'

services:
  postgres:
    image: postgres:15-alpine
    container_name: n8n-postgres
    restart: unless-stopped
    environment:
      POSTGRES_DB: n8n
      POSTGRES_USER: n8n
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
    volumes:
      - postgres_data:/var/lib/postgresql/data
      # Automatische backup elke nacht om 2:00
      - ./backup-script.sh:/etc/periodic/daily/backup:ro
    ports:
      - "5432:5432"  # Alleen voor debugging, verwijder in productie
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U n8n -d n8n"]
      interval: 10s
      timeout: 5s
      retries: 5

  n8n:
    image: n8nio/n8n:latest
    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}
      - DB_POSTGRESDB_SCHEMA=public
    depends_on:
      postgres:
        condition: service_healthy

MySQL Setup (Alternatief)

services:
  mysql:
    image: mysql:8
    container_name: n8n-mysql
    restart: unless-stopped
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      MYSQL_DATABASE: n8n
      MYSQL_USER: n8n
      MYSQL_PASSWORD: ${MYSQL_PASSWORD}
    volumes:
      - mysql_data:/var/lib/mysql
    command: --default-authentication-plugin=mysql_native_password
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 10s
      timeout: 5s
      retries: 5

  n8n:
    environment:
      - DB_TYPE=mysqldb
      - DB_MYSQLDB_HOST=mysql
      - DB_MYSQLDB_PORT=3306
      - DB_MYSQLDB_DATABASE=n8n
      - DB_MYSQLDB_USER=n8n
      - DB_MYSQLDB_PASSWORD=${MYSQL_PASSWORD}

Database Performance Tips

  • ✅ Gebruik PostgreSQL voor beste performance
  • ✅ Configureer connection pooling voor high-traffic
  • ✅ Stel memory limits in voor database container
  • ✅ Enable query logging voor debugging
  • ✅ Implementeer automatische backups

6. Environment Variables Uitgelegd 📝

N8N heeft vele environment variables voor configuratie. Hier zijn de belangrijkste:

🔐 Security Variables

Variable Beschrijving Voorbeeld
N8N_ENCRYPTION_KEY Encryptie voor credentials (min 32 chars) 32-char-long-encryption-key-here
N8N_BASIC_AUTH_ACTIVE Activeer basic authentication true
N8N_BASIC_AUTH_USER Username voor login admin
N8N_BASIC_AUTH_PASSWORD Password voor login SecurePassword123!

🌐 Network Variables

Variable Beschrijving Voorbeeld
N8N_HOST Bind address 0.0.0.0
N8N_PORT Port nummer 5678
N8N_PROTOCOL Protocol (http/https) https
WEBHOOK_URL Publieke webhook URL https://n8n.domain.nl
N8N_EDITOR_BASE_URL Editor URL https://n8n.domain.nl

⚡ Performance Variables

# Memory management
NODE_OPTIONS=--max-old-space-size=4096

# Binary data mode (filesystem is sneller dan database)
N8N_DEFAULT_BINARY_DATA_MODE=filesystem

# Execution pruning (verwijder oude executions)
EXECUTIONS_DATA_PRUNE=true
EXECUTIONS_DATA_MAX_AGE=336  # 14 dagen

# Queue mode voor scaling
EXECUTIONS_MODE=queue
QUEUE_BULL_REDIS_HOST=redis
QUEUE_BULL_REDIS_PORT=6379

7. SSL & Reverse Proxy (Traefik/Nginx) 🔒

Voor productie heb je altijd SSL/HTTPS nodig. Hier zijn twee populaire opties:

Optie 1: Traefik (Automatische SSL)

version: '3.8'

services:
  traefik:
    image: traefik:v3.0
    container_name: traefik
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    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=jouw@email.nl
      - --certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json
      # Redirect HTTP naar HTTPS
      - --entrypoints.web.http.redirections.entrypoint.to=websecure
      - --entrypoints.web.http.redirections.entrypoint.scheme=https
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - traefik_data:/letsencrypt

  n8n:
    image: n8nio/n8n:latest
    container_name: n8n
    restart: unless-stopped
    environment:
      - N8N_PROTOCOL=https
      - N8N_HOST=n8n.jouwdomein.nl
      - WEBHOOK_URL=https://n8n.jouwdomein.nl
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.n8n.rule=Host(`n8n.jouwdomein.nl`)"
      - "traefik.http.routers.n8n.entrypoints=websecure"
      - "traefik.http.routers.n8n.tls.certresolver=letsencrypt"
      - "traefik.http.services.n8n.loadbalancer.server.port=5678"
    volumes:
      - n8n_data:/home/node/.n8n

volumes:
  n8n_data:
  traefik_data:

Optie 2: Nginx Reverse Proxy

Maak een nginx.conf bestand:

server {
    listen 80;
    server_name n8n.jouwdomein.nl;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name n8n.jouwdomein.nl;
    
    # SSL Certificaten (gebruik Certbot voor Let's Encrypt)
    ssl_certificate /etc/letsencrypt/live/n8n.jouwdomein.nl/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/n8n.jouwdomein.nl/privkey.pem;
    
    # SSL Security Headers
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;
    
    # Proxy Headers
    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;
    
    # WebSocket Support
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    
    # Proxy naar N8N
    location / {
        proxy_pass http://n8n:5678;
        proxy_buffer_size 16k;
        proxy_buffers 8 16k;
        proxy_read_timeout 600s;
    }
}

8. Volumes & Data Persistentie 💾

Correct volume management is cruciaal voor data persistentie:

Volume Configuratie

services:
  n8n:
    volumes:
      # ESSENTIEEL: N8N data directory
      - n8n_data:/home/node/.n8n
      
      # Lokale bestanden voor workflows
      - ./local-files:/files
      
      # Custom nodes (optioneel)
      - ./custom-nodes:/home/node/.n8n/nodes
      
      # Backup directory
      - ./backups:/backups
      
      # SSL certificaten (read-only)
      - ./certs:/etc/ssl/certs:ro

volumes:
  n8n_data:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: /opt/n8n/data  # Absolute pad op host

Belangrijke Directories

Directory Inhoud Backup Nodig?
/home/node/.n8n Workflows, credentials, settings ✅ Ja, kritiek!
/home/node/.n8n/nodes Custom/community nodes ✅ Ja
/files Lokale bestanden voor workflows ⚠️ Afhankelijk van gebruik
/home/node/.n8n/binaryData Binary data storage ❌ Nee, kan groot worden

9. Productie-Ready Setup 🏭

Een complete productie setup met alle bells and whistles:

version: '3.8'

services:
  # Redis voor queue mode
  redis:
    image: redis:7-alpine
    container_name: n8n-redis
    restart: unless-stopped
    command: redis-server --requirepass ${REDIS_PASSWORD}
    volumes:
      - redis_data:/data
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 5

  # PostgreSQL database
  postgres:
    image: postgres:15-alpine
    container_name: n8n-postgres
    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 -d n8n"]
      interval: 10s
      timeout: 5s
      retries: 5

  # N8N main instance
  n8n:
    image: n8nio/n8n:1.64.0
    container_name: n8n-main
    restart: unless-stopped
    ports:
      - "5678:5678"
    environment:
      # Database
      - DB_TYPE=postgresdb
      - DB_POSTGRESDB_HOST=postgres
      - DB_POSTGRESDB_PORT=5432
      - DB_POSTGRESDB_DATABASE=n8n
      - DB_POSTGRESDB_USER=n8n
      - DB_POSTGRESDB_PASSWORD=${POSTGRES_PASSWORD}
      
      # Queue mode
      - EXECUTIONS_MODE=queue
      - QUEUE_BULL_REDIS_HOST=redis
      - QUEUE_BULL_REDIS_PORT=6379
      - QUEUE_BULL_REDIS_PASSWORD=${REDIS_PASSWORD}
      
      # Security
      - N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
      - N8N_BASIC_AUTH_ACTIVE=true
      - N8N_BASIC_AUTH_USER=${N8N_USER}
      - N8N_BASIC_AUTH_PASSWORD=${N8N_PASSWORD}
      
      # Performance
      - NODE_OPTIONS=--max-old-space-size=4096
      - N8N_DEFAULT_BINARY_DATA_MODE=filesystem
      - EXECUTIONS_DATA_PRUNE=true
      - EXECUTIONS_DATA_MAX_AGE=168
      
      # Network
      - N8N_PROTOCOL=https
      - WEBHOOK_URL=https://n8n.jouwdomein.nl
      - N8N_EDITOR_BASE_URL=https://n8n.jouwdomein.nl
      
      # Timezone
      - TZ=Europe/Amsterdam
      - GENERIC_TIMEZONE=Europe/Amsterdam
      
      # Logging
      - N8N_LOG_LEVEL=info
    volumes:
      - n8n_data:/home/node/.n8n
      - ./local-files:/files
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
    deploy:
      resources:
        limits:
          memory: 4G
          cpus: '2'
    healthcheck:
      test: ["CMD", "wget", "--spider", "-q", "http://localhost:5678/healthz"]
      interval: 30s
      timeout: 10s
      retries: 3

  # N8N worker voor heavy lifting
  n8n-worker:
    image: n8nio/n8n:1.64.0
    container_name: n8n-worker
    restart: unless-stopped
    command: worker
    environment:
      # Zelfde database config
      - DB_TYPE=postgresdb
      - DB_POSTGRESDB_HOST=postgres
      - DB_POSTGRESDB_PORT=5432
      - DB_POSTGRESDB_DATABASE=n8n
      - DB_POSTGRESDB_USER=n8n
      - DB_POSTGRESDB_PASSWORD=${POSTGRES_PASSWORD}
      
      # Zelfde queue config
      - EXECUTIONS_MODE=queue
      - QUEUE_BULL_REDIS_HOST=redis
      - QUEUE_BULL_REDIS_PORT=6379
      - QUEUE_BULL_REDIS_PASSWORD=${REDIS_PASSWORD}
      
      # Security
      - N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
      
      # Performance
      - NODE_OPTIONS=--max-old-space-size=2048
    volumes:
      - n8n_data:/home/node/.n8n
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
    deploy:
      resources:
        limits:
          memory: 2G
          cpus: '1'
      replicas: 2  # Meerdere workers voor load balancing

volumes:
  n8n_data:
  postgres_data:
  redis_data:

networks:
  default:
    name: n8n_production
    driver: bridge

10. Backup & Restore Strategieën 💾

Regelmatige backups zijn essentieel voor disaster recovery:

Automatische Backup Script

Maak een backup.sh script:

#!/bin/bash
# N8N Backup Script

# Configuratie
BACKUP_DIR="/opt/backups/n8n"
DATE=$(date +%Y%m%d_%H%M%S)
RETENTION_DAYS=7

# Maak backup directory
mkdir -p $BACKUP_DIR

echo "🔵 Starting N8N backup: $DATE"

# 1. Database backup
echo "📦 Backing up PostgreSQL database..."
docker exec n8n-postgres pg_dump -U n8n -d n8n | gzip > $BACKUP_DIR/database_$DATE.sql.gz

# 2. N8N data volume backup
echo "📂 Backing up N8N data volume..."
docker run --rm \
  -v n8n_data:/data \
  -v $BACKUP_DIR:/backup \
  alpine tar czf /backup/n8n_volume_$DATE.tar.gz -C /data .

# 3. Environment backup
echo "🔐 Backing up environment files..."
cp .env $BACKUP_DIR/env_$DATE.backup
cp docker-compose.yml $BACKUP_DIR/compose_$DATE.backup

# 4. Cleanup oude backups
echo "🧹 Cleaning old backups (older than $RETENTION_DAYS days)..."
find $BACKUP_DIR -name "*.gz" -mtime +$RETENTION_DAYS -delete
find $BACKUP_DIR -name "*.backup" -mtime +$RETENTION_DAYS -delete

echo "✅ Backup completed successfully!"
echo "📍 Location: $BACKUP_DIR"
ls -lh $BACKUP_DIR/*$DATE*

Maak het script executable en voeg toe aan crontab:

# Maak executable
chmod +x backup.sh

# Voeg toe aan crontab (dagelijks om 2:00 AM)
crontab -e
0 2 * * * /opt/scripts/backup.sh >> /var/log/n8n-backup.log 2>&1

Restore Procedure

Restore script (restore.sh):

#!/bin/bash
# N8N Restore Script

if [ $# -eq 0 ]; then
    echo "Usage: ./restore.sh YYYYMMDD_HHMMSS"
    echo "Example: ./restore.sh 20250825_020000"
    exit 1
fi

BACKUP_DATE=$1
BACKUP_DIR="/opt/backups/n8n"

echo "⚠️  WARNING: This will restore N8N to backup from $BACKUP_DATE"
read -p "Are you sure? (yes/no): " confirm

if [ "$confirm" != "yes" ]; then
    echo "Restore cancelled."
    exit 1
fi

# Stop N8N
echo "🛑 Stopping N8N containers..."
docker-compose down

# Restore database
echo "📦 Restoring database..."
docker-compose up -d postgres
sleep 10
gunzip -c $BACKUP_DIR/database_$BACKUP_DATE.sql.gz | \
  docker exec -i n8n-postgres psql -U n8n -d n8n

# Restore volume
echo "📂 Restoring N8N data..."
docker run --rm \
  -v n8n_data:/data \
  -v $BACKUP_DIR:/backup \
  alpine sh -c "cd /data && tar xzf /backup/n8n_volume_$BACKUP_DATE.tar.gz"

# Restore environment
echo "🔐 Restoring environment files..."
cp $BACKUP_DIR/env_$BACKUP_DATE.backup .env
cp $BACKUP_DIR/compose_$BACKUP_DATE.backup docker-compose.yml

# Start N8N
echo "🚀 Starting N8N..."
docker-compose up -d

echo "✅ Restore completed!"
docker-compose ps

11. Updates & Rollback Procedures 🔄

Veilig updaten van N8N zonder downtime:

Update Strategie

#!/bin/bash
# N8N Update Script

NEW_VERSION="1.65.0"
OLD_VERSION=$(docker inspect n8n --format='{{.Config.Image}}' | cut -d: -f2)

echo "📊 Current version: $OLD_VERSION"
echo "🆕 New version: $NEW_VERSION"

# 1. Backup maken
echo "💾 Creating backup before update..."
./backup.sh

# 2. Pull nieuwe image
echo "📥 Pulling new N8N image..."
docker pull n8nio/n8n:$NEW_VERSION

# 3. Update docker-compose.yml
echo "📝 Updating docker-compose.yml..."
sed -i.bak "s/n8nio\/n8n:$OLD_VERSION/n8nio\/n8n:$NEW_VERSION/g" docker-compose.yml

# 4. Recreate containers (met minimal downtime)
echo "🔄 Recreating containers..."
docker-compose up -d --no-deps --build n8n

# 5. Health check
echo "🏥 Checking health..."
sleep 30
curl -f http://localhost:5678/healthz || {
    echo "❌ Health check failed! Rolling back..."
    ./rollback.sh $OLD_VERSION
    exit 1
}

echo "✅ Update completed successfully!"
docker-compose ps

Rollback Script

#!/bin/bash
# N8N Rollback Script

ROLLBACK_VERSION=$1

echo "⏪ Rolling back to version: $ROLLBACK_VERSION"

# Restore docker-compose.yml
cp docker-compose.yml.bak docker-compose.yml

# Recreate containers met oude versie
docker-compose up -d --force-recreate

echo "✅ Rollback completed!"
docker-compose ps

12. Monitoring & Health Checks 📊

Monitor je N8N installatie voor optimale performance:

Docker Health Checks

services:
  n8n:
    healthcheck:
      test: ["CMD", "wget", "--spider", "-q", "http://localhost:5678/healthz"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s

Monitoring met Prometheus & Grafana

services:
  prometheus:
    image: prom/prometheus:latest
    container_name: prometheus
    ports:
      - "9090:9090"
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
      - prometheus_data:/prometheus
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.path=/prometheus'

  grafana:
    image: grafana/grafana:latest
    container_name: grafana
    ports:
      - "3000:3000"
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=admin
      - GF_INSTALL_PLUGINS=redis-datasource
    volumes:
      - grafana_data:/var/lib/grafana
      - ./grafana-dashboards:/etc/grafana/provisioning/dashboards

Health Check Script

#!/bin/bash
# N8N Health Monitor

# Check N8N status
N8N_STATUS=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:5678/healthz)

if [ $N8N_STATUS -eq 200 ]; then
    echo "✅ N8N is healthy"
else
    echo "❌ N8N is unhealthy (HTTP $N8N_STATUS)"
    # Send alert (email/Slack/Discord)
    curl -X POST -H 'Content-type: application/json' \
      --data '{"text":"⚠️ N8N is down!"}' \
      $SLACK_WEBHOOK_URL
fi

# Check database
docker exec n8n-postgres pg_isready -U n8n || {
    echo "❌ Database is down!"
    exit 1
}

# Check disk space
DISK_USAGE=$(df -h /opt/n8n | awk 'NR==2 {print $5}' | sed 's/%//')
if [ $DISK_USAGE -gt 80 ]; then
    echo "⚠️ Disk usage critical: $DISK_USAGE%"
fi

# Check memory
docker stats --no-stream --format "table {{.Container}}\t{{.MemUsage}}" | grep n8n

13. Troubleshooting & FAQ 🔧

Veelvoorkomende Problemen

❌ Problem: Container start niet

Symptoom: docker-compose up faalt

Oplossing:

# Check logs docker-compose logs n8n # Check permissions sudo chown -R 1000:1000 ./n8n_data # Clean restart docker-compose down -v docker-compose up -d

❌ Problem: Database connection failed

Symptoom: Error: "ECONNREFUSED"

Oplossing:

# Test database connectivity docker exec n8n ping postgres docker exec n8n nc -zv postgres 5432 # Check database logs docker-compose logs postgres # Verify credentials docker exec postgres psql -U n8n -d n8n -c "SELECT 1;"

❌ Problem: Out of memory

Symptoom: Container crashes met "OOMKilled"

Oplossing:

# Increase memory limit environment: - NODE_OPTIONS=--max-old-space-size=8192 deploy: resources: limits: memory: 8G

FAQ

Hoe upgrade ik van SQLite naar PostgreSQL?

Export je workflows via de UI, stop N8N, configureer PostgreSQL in docker-compose.yml, start N8N, importeer workflows.

Kan ik meerdere N8N instances draaien?

Ja! Gebruik queue mode met Redis en meerdere worker containers. Zie de productie setup sectie.

Hoe migreer ik naar een andere server?

Maak een backup, kopieer alle bestanden naar nieuwe server, restore backup, update DNS.

14. Best Practices & Security 🛡️

Security Checklist

  • Gebruik specifieke versie tags, niet :latest
  • Enable authentication (basic auth of SSO)
  • Gebruik HTTPS met valid SSL certificaten
  • Isoleer containers in eigen network
  • Limit resources met deploy constraints
  • Regelmatige updates voor security patches
  • Gebruik secrets voor gevoelige data
  • Monitor logs voor verdachte activiteit
  • Backup encryption key veilig opslaan
  • Firewall rules alleen noodzakelijke ports

Performance Tips

🚀 Database

  • Gebruik PostgreSQL ipv SQLite
  • Enable connection pooling
  • Regelmatige VACUUM runs
  • Index optimization

💾 Storage

  • Gebruik SSD storage
  • Binary data op filesystem
  • Prune oude executions
  • External object storage (S3)

🎯 Klaar om N8N met Docker te deployen?

Met deze complete gids heb je alle kennis om N8N professioneel te deployen. Van development tot enterprise-ready productie setups!

Wij installeren N8N voor je - €100 all-in! →

📚 Aanvullende Resources

"Docker maakt N8N deployment een fluitje van een cent. Van lokale development tot enterprise productie - alles draait smooth in containers!" - DevOps Engineer, 2025

#n8n #docker #docker-compose #containerization #deployment #postgresql #ssl #traefik #nginx #devops