We are using n8n enterprise for our company and we have a large multi worker/runner setup. Most of the time everything works fine but from time to time we get un-reproducable, no-useful-log hangs. Reloading the page and restarting the flow works. Nothing useful at all in container logs. This all started after switching to 2.0. Since I can’t give a useful log I just want to share our docker compose setup so that hopeufully somebody can pinpoint if we’re doing something obviously wrong in our configuration.
The biggest change we did on docker-compose file compared to v1.x is addition of runners.
docker-compose.yml
volumes:
db_storage:
n8n_storage:
redis_storage:
# Main specific
x-n8n-main-env: &n8n_main_env
N8N_DISABLE_PRODUCTION_MAIN_PROCESS: false
# Worker specific
x-n8n-worker-env: &n8n_worker_env
N8N_DISABLE_UI: true
N8N_DISABLE_ACTIVE_WORKFLOWS: true
# Main & Worker common vars
x-n8n-common-env: &n8n_common_env
# Execution & queue
EXECUTIONS_MODE: queue
EXECUTIONS_TIMEOUT: 600
EXECUTIONS_TIMEOUT_MAX: 1200
EXECUTIONS_DATA_MAX_AGE: 72
EXECUTIONS_DATA_PRUNE_MAX_COUNT: 5000
OFFLOAD_MANUAL_EXECUTIONS_TO_WORKERS: true
QUEUE_BULL_REDIS_HOST: redis
QUEUE_BULL_REDIS_PORT: 6379
QUEUE_HEALTH_CHECK_ACTIVE: true
QUEUE_WORKER_STALLED_INTERVAL: 1200000 # 20 minutes in ms
QUEUE_WORKER_LOCK_DURATION: 1200000 # 20 minutes lock in ms
QUEUE_WORKER_LOCK_RENEW_TIME: 300000 # Renew lock every 5 minutes
# Runners (safe code execution)
N8N_RUNNERS_ENABLED: true
N8N_RUNNERS_MODE: external
N8N_RUNNERS_AUTH_TOKEN: ${N8N_RUNNERS_AUTH_TOKEN}
N8N_RUNNERS_BROKER_LISTEN_ADDRESS: 0.0.0.0
N8N_NATIVE_PYTHON_RUNNER: true
# Misc / runtime / security
N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS: true
N8N_BLOCK_ENV_ACCESS_IN_NODE: true
N8N_SKIP_AUTH_ON_OAUTH_CALLBACK: true
N8N_GIT_NODE_DISABLE_BARE_REPOS: true
N8N_DEFAULT_BINARY_DATA_MODE: database
N8N_CONCURRENCY_PRODUCTION_LIMIT: 6 # Number of concurrent 'active workflow' executions
N8N_HOST: ${N8N_HOST}
N8N_PROXY_HOPS: 1
N8N_VERSION_NOTIFICATIONS_ENABLED: false
N8N_DATA_TABLES_MAX_SIZE_BYTES: 256000000
WEBHOOK_URL: ${WEBHOOK_URL}
GENERIC_TIMEZONE: Europe/Amsterdam
# Logs
N8N_LOG_OUTPUT: file,console
N8N_LOG_FORMAT: json
# N8N_LOG_LEVEL: debug
# DB
DB_TYPE: postgresdb
DB_POSTGRESDB_HOST: postgres
DB_POSTGRESDB_PORT: 5432
DB_POSTGRESDB_DATABASE: ${POSTGRES_DB}
DB_POSTGRESDB_USER: ${POSTGRES_NON_ROOT_USER}
DB_POSTGRESDB_PASSWORD: ${POSTGRES_NON_ROOT_PASSWORD}
DB_POSTGRESDB_POOL_SIZE: 10
# SMTP
N8N_SMTP_SENDER: ${N8N_SMTP_SENDER}
N8N_SMTP_HOST: ${N8N_SMTP_HOST}
N8N_SMTP_PORT: ${N8N_SMTP_PORT}
N8N_SMTP_USER: ${N8N_SMTP_USER}
N8N_SMTP_PASS: ${N8N_SMTP_PASS}
N8N_SMTP_STARTTLS: false
N8N_SMTP_SSL: true
# License
N8N_LICENSE_ACTIVATION_KEY: ${N8N_LICENSE_ACTIVATION_KEY}
# Credentials overwrite (quoted to keep YAML happy)
CREDENTIALS_OVERWRITE_DATA: ${CREDENTIALS_OVERWRITE_DATA}
x-n8n-worker: &n8n_worker
image: n8nio/n8n
command: worker
restart: unless-stopped
volumes:
- n8n_storage:/home/node/.n8n
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
x-n8n-runner: &n8n_runner
build:
context: .
dockerfile: runners.Dockerfile
image: n8nio/runners
restart: unless-stopped
x-n8n-runner-env: &n8n_runner_env
N8N_RUNNERS_AUTH_TOKEN: ${N8N_RUNNERS_AUTH_TOKEN}
NODE_FUNCTION_ALLOW_BUILTIN: "*"
NODE_FUNCTION_ALLOW_EXTERNAL: "*"
N8N_RUNNERS_STDLIB_ALLOW: "*"
N8N_RUNNERS_EXTERNAL_ALLOW: "*"
services:
n8n:
image: n8nio/n8n
restart: unless-stopped
ports:
- "80:5678"
volumes:
- n8n_storage:/home/node/.n8n
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
environment:
<<: [*n8n_main_env, *n8n_common_env]
postgres:
image: postgres:16
restart: unless-stopped
environment:
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- POSTGRES_DB=${POSTGRES_DB}
- POSTGRES_NON_ROOT_USER=${POSTGRES_NON_ROOT_USER}
- POSTGRES_NON_ROOT_PASSWORD=${POSTGRES_NON_ROOT_PASSWORD}
volumes:
- db_storage:/var/lib/postgresql/data
- ./init-data.sh:/docker-entrypoint-initdb.d/init-data.sh
healthcheck:
test: ["CMD-SHELL", "pg_isready -h localhost -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
interval: 5s
timeout: 5s
retries: 10
redis:
image: redis:7
restart: unless-stopped
command: ["redis-server", "--appendonly", "yes"]
volumes:
- redis_storage:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 5s
retries: 10
n8n-worker-1:
<<: *n8n_worker
environment:
<<: [*n8n_worker_env, *n8n_common_env]
n8n-worker-2:
<<: *n8n_worker
environment:
<<: [*n8n_worker_env, *n8n_common_env]
n8n-worker-3:
<<: *n8n_worker
environment:
<<: [*n8n_worker_env, *n8n_common_env]
n8n-worker-4:
<<: *n8n_worker
environment:
<<: [*n8n_worker_env, *n8n_common_env]
n8n-runner-1:
<<: *n8n_runner
environment:
<<: *n8n_runner_env
N8N_RUNNERS_TASK_BROKER_URI: "http://n8n-worker-1:5679"
N8N_RUNNERS_LAUNCHER_HEALTH_CHECK_PORT: 5691
depends_on:
- n8n-worker-1
n8n-runner-2:
<<: *n8n_runner
environment:
<<: *n8n_runner_env
N8N_RUNNERS_TASK_BROKER_URI: "http://n8n-worker-2:5679"
N8N_RUNNERS_LAUNCHER_HEALTH_CHECK_PORT: 5692
depends_on:
- n8n-worker-2
n8n-runner-3:
<<: *n8n_runner
environment:
<<: *n8n_runner_env
N8N_RUNNERS_TASK_BROKER_URI: "http://n8n-worker-3:5679"
N8N_RUNNERS_LAUNCHER_HEALTH_CHECK_PORT: 5693
depends_on:
- n8n-worker-3
n8n-runner-4:
<<: *n8n_runner
environment:
<<: *n8n_runner_env
N8N_RUNNERS_TASK_BROKER_URI: "http://n8n-worker-4:5679"
N8N_RUNNERS_LAUNCHER_HEALTH_CHECK_PORT: 5694
depends_on:
- n8n-worker-4
runners.Dockerfile (For some reason below packages are not accessible from n8n code noes, but that’s another issue)
FROM n8nio/runners
USER root
RUN cd /opt/runners/task-runner-javascript && pnpm add nodejs-polars danfojs-node
RUN cd /opt/runners/task-runner-python && uv pip install numpy pandas
USER runner
