Working 2.x docker compose example

Describe the problem/error/question

I tired to update to 2.x my docker setup and basic functions are broken, so I check the documentation Docker Compose | n8n Docs read forum posts, random dudes GH repos, chat to AI agents, vented out my frustration Self hosted 2.x an just given up, but now turning to the community.

There is no single error I can highlight, as I tried so many different options, and most have a different error.

What might makes my setup unique is that I still use:

  • sqlite3 as a database
  • single container with 1.x version
  • blind mounts in docker
  • python code blocks exclusively

I would like to update to 2.x while keeping the database, the blind mounts , I want to keep using python code block with the least amount of complexity / containers.

What is the error message (if any)?

Depends on the day or the way I try.

Please share your workflow

(Select the nodes on your canvas and use the keyboard shortcuts CMD+C/CTRL+C and CMD+V/CTRL+V to copy and paste the workflow.){
  "nodes": [
    {
      "parameters": {
        "language": "python",
        "pythonCode": "# Loop over input items and add a new field called 'myNewField' to the JSON of each one\nfor item in _input.all():\n  item.json.myNewField = 1\nreturn _input.all()"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        208,
        0
      ],
      "id": "8e21494e-cdf0-43aa-94a6-af0c02b8b1ad",
      "name": "Code in Python (Native)"
    },
    {
      "parameters": {},
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [
        0,
        -208
      ],
      "id": "16e0537c-3d2b-4147-be2a-0b788137cbdd",
      "name": "When clicking ‘Execute workflow’"
    },
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "minutes"
            }
          ]
        }
      },
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.3,
      "position": [
        0,
        0
      ],
      "id": "ad72a85e-391a-47b1-85b6-9fd5b4c92496",
      "name": "Schedule Trigger"
    },
    {
      "parameters": {
        "jsCode": "// Loop over input items and add a new field called 'myNewField' to the JSON of each one\nfor (const item of $input.all()) {\n  item.json.myNewField = 1;\n}\n\nreturn $input.all();"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        208,
        -208
      ],
      "id": "ad7a64c6-8227-4061-b87b-63c44151db1e",
      "name": "Code in JavaScript"
    }
  ],
  "connections": {
    "Code in Python (Native)": {
      "main": [
        []
      ]
    },
    "When clicking ‘Execute workflow’": {
      "main": [
        [
          {
            "node": "Code in Python (Native)",
            "type": "main",
            "index": 0
          },
          {
            "node": "Code in JavaScript",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "Code in Python (Native)",
            "type": "main",
            "index": 0
          },
          {
            "node": "Code in JavaScript",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "pinData": {},
  "meta": {
    "instanceId": "dc09a57def958482a6f655ae99b38636865e650e02c18374ef6475e57e109d9d"
  }
}

Share the output returned by the last node

Information on your n8n setup

  • n8n version: 1.123.17
  • Database (default: SQLite): sqlite
  • n8n EXECUTIONS_PROCESS setting (default: own, main): default
  • Running n8n via (Docker, npm, n8n cloud, desktop app): docker compose
  • Operating system: Linux
services:
  n8n:
    image: n8nio/n8n:1
    container_name: n8n
    restart: unless-stopped
    ports:
      - "5678:5678"
    env_file:
      - .env
    volumes:
      - ./data:/home/node/.n8n
      - ./n8n-files:/home/node/.n8n-files
    sysctls:
      - net.ipv4.ping_group_range=1000 1000
    security_opt:
      - apparmor:unconfined
    depends_on:
      - redis
    networks:
      - n8n_network

  redis:
    image: redis:7-alpine
    container_name: redis
    restart: unless-stopped
    volumes:
      - ./redis_data:/data
    command: redis-server --save 60 1 --bind 0.0.0.0
    networks:
      - n8n_network

networks:
  n8n_network:
    driver: bridge

My compose file above
… and the ( sanitised ) .env bellow

[email protected]
N8N_SMTP_PASS=super-good-smtp-password
N8N_RUNNERS_AUTH_TOKEN=generated-token
WEBHOOK_URL=https://n8n.domain.tld/
GENERIC_TIMEZONE=region/city
N8N_EMAIL_MODE=smtp
N8N_SMTP_HOST=mail.domain.tld
N8N_SMTP_PORT=587
N8N_DIAGNOSTICS_ENABLED=false
N8N_VERSION_NOTIFICATIONS_ENABLED=false
N8N_TEMPLATES_ENABLED=false
EXECUTIONS_DATA_SAVE_MANUAL_EXECUTIONS=true
EXECUTIONS_DATA_PRUNE=true
EXECUTIONS_DATA_MAX_AGE=2160
EXECUTIONS_DATA_PRUNE_MAX_COUNT=0
NODES_EXCLUDE=[]
N8N_RUNNERS_ENABLED=true

hello @kisst

I have a Docker config with Postgres. You can adapt it:

services:
  postgres:
    image: arm64v8/postgres:16.2-alpine3.19
    restart: always
    container_name: postgres
    environment:
      - POSTGRES_USER
      - POSTGRES_PASSWORD
      - POSTGRES_DB
    volumes:
      - db_storage:/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: n8nio/n8n:2.4.8
    container_name: n8n
    restart: always
    environment:
      - DB_TYPE=postgresdb
      - DB_POSTGRESDB_HOST
      - DB_POSTGRESDB_PORT
      - DB_POSTGRESDB_DATABASE
      - DB_POSTGRESDB_USER
      - DB_POSTGRESDB_PASSWORD
      - NODE_FUNCTION_ALLOW_BUILTIN=*
      - GENERIC_TIMEZONE
      - NODES_EXCLUDE="[]"
      - N8N_BLOCK_ENV_ACCESS_IN_NODE=false
      - N8N_DEFAULT_BINARY_DATA_MODE=filesystem
      - N8N_SKIP_AUTH_ON_OAUTH_CALLBACK=false
      - N8N_PROXY_HOPS=1  # if behind reverse proxy
      - N8N_RUNNERS_ENABLED=true
      - N8N_RUNNERS_MODE=external
      - N8N_RUNNERS_BROKER_LISTEN_ADDRESS=0.0.0.0
      - N8N_RUNNERS_AUTH_TOKEN
      - N8N_NATIVE_PYTHON_RUNNER=true
      - N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=true
      - WEBHOOK_URL
    ports:
      - "5678:5678"
    links:
      - postgres
    volumes:
      - n8n_storage:/home/node/.n8n
      - n8n_files_storage:/home/node/.n8n-files
      - n8n_certs:/opt/custom-certificates
    depends_on:
      postgres:
        condition: service_healthy

  n8n-runners:
    image: n8nio/runners:2.4.8
    container_name: n8n-runners
    environment:
      - N8N_RUNNERS_TASK_BROKER_URI=http://n8n:5679
      - N8N_RUNNERS_AUTH_TOKEN
    depends_on:
      - n8n

volumes:
  db_storage:
    driver: local
    driver_opts:
      type: none
      device: ./db_data
      o: bind
  n8n_storage:
    driver: local
    driver_opts:
      type: none
      device: ./n8n_data
      o: bind
  n8n_files_storage:
    driver: local
    driver_opts:
      type: none
      device: ./n8n_files_storage
      o: bind
  n8n_certs:
    driver: local
    driver_opts:
      type: none
      device: ./certificates
      o: bind

but keep in mind, that python code will not work, if you have imported custom libraries, as the python logic has been redesigned