I’ve seen similar topics but I haven’t figured it out yet so I’ll leave my case here.
I’m trying to build and run Docker image based on the official image in order to install Python in it to use Code in Python node with the task runner internal mode.
Now I successfully installed Python in the image with the Dockerfile below, but when I run the container, I get error message below.
How do I use Code in Python node in n8n 2.7.4 with the task runner internal mode?
The reason for the choice of internal mode is because it’s intended to deploy to a VM in our private network, so the ease of use is more prioritized than security and performance.
I tried manually creating .venv inside /home/node and set N8N_PYTHON_BINARY and PATH etc, but this didn’t work either.
venv module is installed by default and it can correctly create virtual environment.
I’ve seen some comment here is saying that new n8n is supposed to create its own virtual environment so that I don’t have to write docker instructions or something, but I don’t see any virtual environment created by n8n inside the container when I check inside.
Dockerfile
FROM n8nio/n8n:latest
# Switch to root to install packages
USER root
# Install apk
RUN wget https://gitlab.alpinelinux.org/api/v4/projects/5/packages/generic/v2.14.4/x86_64/apk.static
RUN chmod +x apk.static && \
./apk.static -X http://dl-cdn.alpinelinux.org/alpine/v3.22/main -U --allow-untrusted --initdb add apk-tools
# Install Python and required build tools
RUN apk add --update --no-cache python3 py3-pip py3-setuptools py3-wheel
# Set Task Runners internal model
ENV N8N_RUNNERS_MODE=internal
# Switch back to node
USER node
What is the error message (if any)?
Error message
n8n-1 | Failed to start Python task runner in internal mode. because its virtual environment is missing from this system. Launching a Python runner in internal mode is intended only for debugging and is not recommended for production. Users are encouraged to deploy in external mode. See: https://docs.n8n.io/hosting/configuration/task-runners/#setting-up-external-mode
Run a sidecar container with the matching n8nio/runners image and the same auth token, as shown in the docs: [External mode]
task-runners:
image: n8nio/runners:2.7.4 # version must match n8nio/n8n
environment:
- N8N_RUNNERS_TASK_BROKER_URI=http://n8n-main:5679
- N8N_RUNNERS_AUTH_TOKEN=your-secret-here
depends_on:
- n8n
If you need extra Python packages, you have to extend the n8nio/runners image, install them there, and allowlist them via n8n-task-runners.json, not to modify the main n8nio/n8n container: [Adding dependencies]
Based on my research, I now have a clear picture. The internal mode for Python expects n8n to manage its own venv at a specific path inside the @n8n/task-runner-python package, but the official Docker image doesn’t ship with the Python task runner package — it’s only in the separate n8nio/runners image. So internal mode with Python basically doesn’t work properly from the base n8n image. The real solution is external mode with the runners sidecar container.
Here’s my reply:
Internal mode for the Python runner doesn’t really work with the base n8nio/n8n image, the error you’re seeing is because the @n8n/task-runner-python package (which includes its own managed .venv) only ships in the separate n8nio/runners image. Just installing Python into the main container isn’t enough since n8n expects that whole task runner package with its venv already set up at a specific path. Your best bet is to switch to external mode and run the n8nio/runners container as a sidecar, it’s honestly not much more complicated and it actually works. Set N8N_RUNNERS_MODE=external, N8N_RUNNERS_ENABLED=true, and N8N_RUNNERS_AUTH_TOKEN on the n8n container, then spin up the runners container with the matching token pointed at your broker URI.
The internal mode Python runner expects a venv at /opt/runners/task-runner-python/.venv/bin/python with the runner source code at /opt/runners/task-runner-python/. That whole directory doesn’t exist in the base n8n image, it only ships with the separate n8nio/n8n-task-runners image. So just installing Python via apk won’t cut it, internal mode still looks for that specific runner setup. Honestly for Docker the easiest path is to just use external mode with the n8nio/n8n-task-runners image as a sidecar container in your docker-compose, even on a private VM it’s not much extra config and it actually works out of the box without fighting the venv path stuff.
Now I have a clear picture. The internal mode expects the venv at /opt/runners/task-runner-python/.venv/bin/python which is only present in the dedicated n8nio/n8n-runner image, not the main n8nio/n8n image. For internal mode in the main n8n image, they’d need to replicate that setup or just use external mode with the runner sidecar.
Hey, internal mode expects a pre-built venv at /opt/runners/task-runner-python/.venv/bin/python which only exists in the separate n8nio/n8n-runner image, not the base n8nio/n8n image you’re building from. Just installing python3 via apk won’t create that. The easiest path is to switch to external mode and run the official n8nio/n8n-runner image as a sidecar container alongside your n8n container, it already has everything set up including the venv and the python task runner code. You’d set N8N_RUNNERS_MODE=external on the n8n container and share an auth token between them, there’s a docker-compose example in the docs here: Task runners | n8n Docs