Objectif de ce guide pratique n8n

Bienvenue dans ce guide pratique dédié au déploiement de n8n en local via Docker.

n8n est un outil d'automatisation de flux de travail (workflow automation) ultra-puissant et extensible. Que ce soit pour connecter des API, automatiser des tâches répétitives ou synchroniser des données entre différentes applications, n8n offre une flexibilité exceptionnelle.

Pour les projets personnels ou les tests, une installation standard de n8n sur une seule instance Docker suffit amplement. Cependant, dès que l'on commence à manipuler des volumes de données importants, des tâches gourmandes en ressources ou des déclencheurs (triggers) intensifs, une seule instance peut rapidement devenir un goulot d'étranglement. C'est là qu'intervient l'architecture distribuée grâce aux Runners (ou Workers).

Ce wiki a pour but de vous guider pas à pas dans la mise en place d'un environnement n8n robuste, résilient et prêt pour la mise à l'échelle, directement sur votre machine locale.

Prérequis pour créer une instance N8N

Ici, tout se fera sur Docker. Il faut donc un environnement Docker (ou WSL sur Windows) fonctionnel.

L'architecture de n8n

Pour comprendre l'intérêt d'un Runner, il faut d'abord comprendre comment n8n fonctionne par défaut.

L'architecture par défaut (Monolithique)

Dans une configuration de base, l'instance principale de n8n (le Main Process) fait tout :

  1. Elle charge l'interface graphique (l'éditeur de workflows).
  2. Elle gère la base de données et l'authentification.
  3. Elle écoute les déclencheurs (Webhooks, cron...).
  4. Elle exécute le code et les nœuds des workflows.

Si un workflow lourd (comme le traitement d'un gros fichier CSV ou de l'IA en local) s'exécute, il s'accapare le processeur et la mémoire de cette unique instance. Résultat : l'interface fige, et les autres automatisations prennent du retard.

Le rôle du Runner : Diviser pour régner

Un Runner (parfois appelé Worker dans la documentation officielle de n8n) est une instance secondaire de n8n configurée exclusivement pour exécuter les tâches.

Dans cette configuration dite "en mode file d'attente" ("Queue Mode") :

  • L'instance Principale (Main) ne s'occupe plus que de l'affichage de l'interface, de la configuration et de la réception des événements. Dès qu'un workflow doit se lancer, elle crée une tâche et l'envoie dans une file d'attente (gérée par Redis).
  • Le(s) Runner(s) écoute(nt) cette file d'attente, récupère(nt) les tâches au fil de l'eau, et les exécute(nt) en arrière-plan.

 L'avantage clé : La mise à l'échelle (Scalabilité)

C'est ici que la magie opère, notamment avec Docker :

  • Scalabilité Horizontale : Si votre volume d'automatisation double du jour au lendemain, vous n'avez pas besoin de modifier votre instance principale. Il vous suffit de lancer un deuxième, un troisième ou un dixième Runner Docker
    docker compose up --scale worker=3

Ils se partageront la charge de travail automatiquement.

  • Isolation des pannes : Si un workflow mal conçu fait planter un Runner (consommation excessive de mémoire par exemple), l'interface de n8n reste accessible, les webhooks continuent d'être reçus, et Docker va simplement redémarrer le Runner défaillant sans interrompre le reste du système.

Étape 1 - Préparer les éléments pour Docker

Voici l’arborescence du setup n8n Docker que l’on va mettre en place :

Créer son instance N8N

 Ci dessous, la description des différents fichiers dans l'arborescence. 

config\n8n-task-runners.json

Il s’agit du manuel d’instruction donné à mon instance n8n pour savoir comment lancer, sécuriser et isoler l’exécution des nœuds de code (Code Nodes) en JavaScript et en Python. Il est divisé en deux blocs principaux : un pour JavaScript et un autre pour Python.

Contenu du fichier :

{
"task-runners": [
{
"runner-type": "javascript",
"workdir": "/home/runner",
"command": "/usr/local/bin/node",
"args": [
"--disallow-code-generation-from-strings",
"--disable-proto=delete",
"/opt/runners/task-runner-javascript/dist/start.js"
],
"health-check-server-port": "5681",
"allowed-env": [
"PATH", "GENERIC_TIMEZONE", "NODE_OPTIONS",
"N8N_RUNNERS_AUTO_SHUTDOWN_TIMEOUT",
"N8N_RUNNERS_TASK_TIMEOUT",
"N8N_RUNNERS_MAX_CONCURRENCY",
"N8N_SENTRY_DSN", "N8N_VERSION", "ENVIRONMENT",
"DEPLOYMENT_NAME", "HOME"
],
"env-overrides": {
"NODE_FUNCTION_ALLOW_BUILTIN": "crypto",
"NODE_FUNCTION_ALLOW_EXTERNAL": "moment",
"N8N_RUNNERS_HEALTH_CHECK_SERVER_HOST": "0.0.0.0"
}
},
{
"runner-type": "python",
"workdir": "/home/runner",
"command": "/opt/runners/task-runner-python/.venv/bin/python",
"args": ["-m", "src.main"],
"health-check-server-port": "5682",
"allowed-env": [
"PATH", "N8N_RUNNERS_LAUNCHER_LOG_LEVEL",
"N8N_RUNNERS_AUTO_SHUTDOWN_TIMEOUT",
"N8N_RUNNERS_TASK_TIMEOUT",
"N8N_RUNNERS_MAX_CONCURRENCY",
"N8N_RUNNERS_EXTERNAL_ALLOW",
"N8N_RUNNERS_STDLIB_ALLOW",
"N8N_SENTRY_DSN", "N8N_VERSION", "ENVIRONMENT",
"DEPLOYMENT_NAME"
],
"env-overrides": {
"PYTHONPATH": "/opt/runners/task-runner-python"
}
}
]
}

Le Dockerfile va permettre de construire une nouvelle image (en s’appuyant sur l’officielle n8nio/runners) pour y inclure des librairies Python à installer dès le début. 

Runners\Dockerfile

Le Dockerfile va permettre de construire une nouvelle image (en s’appuyant sur l’officielle n8nio/runners) pour y inclure des librairies Python à installer dès le début.

# Start from the official n8n runners image (it already has Python & Node setup correctly)
FROM n8nio/runners:latest
# Switch to root just to install packages
USER root
# 1. (Optional) Install extra JS libraries if you need them
RUN cd /opt/runners/task-runner-javascript && pnpm add moment uuid
# 2. Copy your python requirements
COPY requirements.txt /opt/runners/task-runner-python/requirements.txt
# 3. Install them using 'uv' (It's built-in and much faster than pip)
RUN cd /opt/runners/task-runner-python && uv pip install -r requirements.txt
# Switch back to the secure runner user
USER runner

Runners\requirements.txt

Un simple fichier dans lequel on vient lister toutes les librairies Python à installer au build du Dockerfile :

requests
pandas
numpy

Docker-compose.yml

Enfin, le coeur qui vient tout lier : le docker compose. Ce fichier contient la description du n8n + son runner (basé sur le Dockerfile précédent). Ici, on active les runners et on passe en mode external. Le but est bien de conifer les traitements JavaScript / Python au runner. Également, on n’oublie pas de permettre l’exécution et l’intégration des librairies Python (Il reste bien sûr possible de les limiter, au contraire) :

version: '3.8'
services:
n8n:
image: docker.n8n.io/n8nio/n8n:latest
ports:
- "5678:5678"
environment:
GENERIC_TIMEZONE: "Europe/Paris"
N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS: "true"
# Tell n8n to use external runners
N8N_RUNNERS_ENABLED: "true"
N8N_RUNNERS_MODE: "external"
N8N_RUNNERS_AUTH_TOKEN: "secret_runner_token"
# Broker settings (listening for the runner)
N8N_RUNNERS_BROKER_LISTEN_ADDRESS: "0.0.0.0"
N8N_RUNNERS_BROKER_PORT: "5679"
N8N_RUNNERS_STDLIB_ALLOW: "*"
N8N_RUNNERS_EXTERNAL_ALLOW: "*"
WEBHOOK_URL: "https://localhost:5678"
# Javascript
N8N_CODE_EXECUTION_MODE: "regular"
volumes:
- n8n_data:/home/node/.n8n
runners:
build:
context: ./runners # This builds our custom Dockerfile
environment:
# Connect back to n8n
N8N_RUNNERS_AUTH_TOKEN: "secret_runner_token"
N8N_RUNNERS_TASK_BROKER_URI: "http://n8n:5679"
N8N_RUNNERS_STDLIB_ALLOW: "*"
N8N_RUNNERS_EXTERNAL_ALLOW: "*"
volumes:
# Mount the config so the runner knows what to do
- ./config/n8n-task-runners.json:/etc/n8n-task-runners.json
depends_on:
- n8n

volumes:
n8n_data:

Étape 2 : Lancer la stack

Il ne reste plus qu’à lancer notre stack avec la commande suivante :

docker compose up -- build -d

Créer son instance N8N

Mon environnement N8N est maintenant disponible à l'adresse suivante : http://localhost:5678

Créer son instance N8N

Faites confiance aux experts Data & IA de Next Decision, rendez-vous sur la page Contact