Before I try this on a different server, does anyone see any issues with my docker-compose.yml and .env file here? When I run the container(s), it ends up spitting out “PostgreSQL Database directory appears to contain a database; Skipping initialization” and then doesn’t accept the database login, I assume because it wasn’t able to create it. I’ve completely blown away all the containers, images, and directories and started over and I’m still running into this same issue. I’m spinning up another docker host later today and can test it on that one, but in the meantime, thoughts?
docker-compose.yml:
version: "3.1"
services:
traefik:
image: "traefik"
restart: always
command:
- "--api=true"
- "--api.insecure=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.websecure.address=:443"
- "--certificatesresolvers.mytlschallenge.acme.tlschallenge=true"
- "--certificatesresolvers.mytlschallenge.acme.email=${SSL_EMAIL}"
- "--certificatesresolvers.mytlschallenge.acme.storage=/letsencrypt/acme.json"
ports:
- "443:443"
volumes:
- ${DATA_FOLDER}/letsencrypt:/letsencrypt
- /var/run/docker.sock:/var/run/docker.sock:ro
postgres:
image: postgres:11
restart: always
environment:
- POSTGRES_USER
- POSTGRES_PASSWORD
- POSTGRES_DB
- POSTGRES_NON_ROOT_USER
- POSTGRES_NON_ROOT_PASSWORD
volumes:
- ./init-data.sh:/docker-entrypoint-initdb.d/init-data.sh
n8n:
image: 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=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
environment:
- 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}
- N8N_BASIC_AUTH_ACTIVE=true
- N8N_BASIC_AUTH_USER
- N8N_BASIC_AUTH_PASSWORD
- N8N_HOST=${SUBDOMAIN}.${DOMAIN_NAME}
- N8N_PORT=5678
- N8N_PROTOCOL=https
- NODE_ENV=production
- WEBHOOK_TUNNEL_URL=https://${SUBDOMAIN}.${DOMAIN_NAME}/
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ${DATA_FOLDER}/.n8n:/home/node/.n8n
- /local-files:/files
links:
- postgres
command: /bin/sh -c "sleep 5; n8n start"
.env
# Folder where data should be saved
DATA_FOLDER=/root/n8n/
# The top level domain to serve from
DOMAIN_NAME=patinkin.com
# The subdomain to serve from
SUBDOMAIN=n8n
# DOMAIN_NAME and SUBDOMAIN combined decide where n8n will be reachable from
# above example would result in: https://n8n.example.com
# The user name to use for autentication - IMPORTANT ALWAYS CHANGE!
N8N_BASIC_AUTH_USER=westley
# The password to use for autentication - IMPORTANT ALWAYS CHANGE!
N8N_BASIC_AUTH_PASSWORD="asyouwish"
# Optional timezone to set which gets used by Cron-Node by default
# If not set New York time will be used
GENERIC_TIMEZONE=America/Edmonton
# The email address to use for the SSL certificate creation
SSL_EMAIL=strongbad@red.com
EXECUTIONS_PROCESS=main
EXECUTIONS_TIMEOUT=3599
EXECUTIONS_TIMEOUT_MAX=14399
# DATABASE
POSTGRES_USER=dbroot
POSTGRES_PASSWORD="iamgroot"
POSTGRES_DB=n8n
POSTGRES_NON_ROOT_USER=n8nuser
POSTGRES_NON_ROOT_PASSWORD="hacktheplanet"
While I can’t answer your question, I just needed to say that I love where you are taking this. I’m playing with Docker and Kubernetes behind Traefik with Raspberry Pi clusters right now with n8n and it is encouraging to see others thinking likewise!
Figured it out. It helps if you have the init-data.sh file. 
Hey, @cleveradmin did you get a solution for the above issue, I am also doing the same hacktainer and I’m also still unable to get good results.
I have another post on here with some additional issues and a problem with the commonly linked sample docker-compose.yml. Here is what I have now. You’ll need to modify occurrences of CHANGEME to suit your environment and also this uses Cloudflare DNS to facilitate getting an SSL certificate because I have Cloudflare handling SSL in strict mode. You may need to remove it.
docker-compose.yml
version: "3"
services:
postgres:
image: postgres:11
restart: always
environment:
- POSTGRES_USER=CHANGEME
- POSTGRES_PASSWORD=CHANGEME
- POSTGRES_DB=n8n
- POSTGRES_NON_ROOT_USER=CHANGEME
- POSTGRES_NON_ROOT_PASSWORD=CHANGEME
volumes:
- ./init-data.sh:/docker-entrypoint-initdb.d/init-data.sh
- /root/n8n/postgres-data:/var/lib/postgresql/data
traefik:
image: "traefik"
restart: always
command:
- "--api=true"
- "--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.myresolver.acme.dnschallenge=true"
- "--certificatesresolvers.myresolver.acme.dnschallenge.provider=cloudflare"
- "--certificatesresolvers.mytlschallenge.acme.email=${SSL_EMAIL}"
- "--certificatesresolvers.mytlschallenge.acme.storage=/letsencrypt/acme.json"
- "--providers.file.filename=/traefik_conf.yaml"
ports:
- "80:80"
- "443:443"
environment:
- "CF_DNS_API_TOKEN=CHANGEME"
volumes:
- ${DATA_FOLDER}/letsencrypt:/letsencrypt
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./traefik_conf.yaml:/traefik_conf.yaml
n8n:
image: 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
environment:
- N8N_BASIC_AUTH_ACTIVE=true
- N8N_BASIC_AUTH_USER
- N8N_BASIC_AUTH_PASSWORD
- N8N_HOST=${SUBDOMAIN}.${DOMAIN_NAME}
- N8N_PORT=5678
- N8N_PROTOCOL=https
- NODE_ENV=production
- WEBHOOK_URL=https://${SUBDOMAIN}.${DOMAIN_NAME}/
- GENERIC_TIMEZONE=${GENERIC_TIMEZONE}
- 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}
links:
- postgres
volumes:
- ${DATA_FOLDER}/.n8n:/root/.n8n
command: /bin/sh -c "sleep 5; n8n start"
.env
# Folder where data should be saved
DATA_FOLDER=/root/n8n/
# The top level domain to serve from
DOMAIN_NAME=CHANGEME
# The subdomain to serve from
SUBDOMAIN=n8n
# DOMAIN_NAME and SUBDOMAIN combined decide where n8n will be reachable from
# above example would result in: https://n8n.example.com
# The user name to use for authentication - IMPORTANT ALWAYS CHANGE!
N8N_BASIC_AUTH_USER=CHANGEME
# The password to use for authentication - IMPORTANT ALWAYS CHANGE!
N8N_BASIC_AUTH_PASSWORD=CHANGEME
# Optional timezone to set which gets used by Cron-Node by default
# If not set New York time will be used
GENERIC_TIMEZONE=America/Edmonton
# The email address to use for the SSL certificate creation
SSL_EMAIL=CHANGEME
POSTGRES_USER=CHANGEME
POSTGRES_PASSWORD=CHANGEME
POSTGRES_DB=n8n
POSTGRES_NON_ROOT_USER=n8n
POSTGRES_NON_ROOT_PASSWORD=CHANGEME
EXECUTIONS_DATA_PRUNE=true
EXECUTIONS_DATA_MAX_AGE=168
I also ran into issues with the postgres data directory permissions. For me it was related to running the container as a non-root user. The workaround which worked for me was the following:
- let the container run and initialize the data directory using it’s internal ‘postgres’ user
- docker stop postgres
- sudo chown -R $PUID:$PGID $DOCKERDIR/postgres/data
- add in the
user: $PUID:$PGID directive to the docker compose file and start up the container as the desired user
At the time the postgres docker image had hardcoded uid of 999 which on Ubuntu 20.04 corresponded to systemd-coredump user.