first commit
Some checks failed
Security: Sync from Public / sync-from-public (push) Has been cancelled
Test: Benchmark Nightly / build (push) Has been cancelled
Test: Benchmark Nightly / Notify Cats on failure (push) Has been cancelled
CI: Python / Checks (push) Has been cancelled
Test: Evals Python / Workflow Comparison Python (push) Has been cancelled
Util: Check Docs URLs / check-docs-urls (push) Has been cancelled
Test: Visual Storybook / Cloudflare Pages (push) Has been cancelled
Test: E2E Performance / build-and-test-performance (push) Has been cancelled
Test: Workflows Nightly / Run Workflow Tests (push) Has been cancelled
Util: Cleanup CI Docker Images / Delete stale CI images (push) Has been cancelled
Test: Benchmark Destroy Env / build (push) Has been cancelled
Util: Update Node Popularity / update-popularity (push) Has been cancelled
Test: E2E Coverage Weekly / Coverage Tests (push) Has been cancelled

This commit is contained in:
2026-03-17 16:22:57 +03:30
commit 3d5eaf9445
15349 changed files with 2847338 additions and 0 deletions

View File

@@ -0,0 +1,35 @@
ARG NODE_VERSION=24.13.1
FROM dhi.io/node:${NODE_VERSION}-alpine3.22-dev
ARG NODE_VERSION
# Install all dependencies in a single layer to minimize image size
RUN apk add --no-cache busybox-binsh && \
# Install fonts
apk --no-cache add --virtual .build-deps-fonts msttcorefonts-installer fontconfig && \
update-ms-fonts && \
fc-cache -f && \
apk del .build-deps-fonts && \
find /usr/share/fonts/truetype/msttcorefonts/ -type l -exec unlink {} \; && \
# Install OS dependencies
apk update && \
apk upgrade --no-cache && \
apk add --no-cache \
git \
openssh \
openssl \
graphicsmagick=1.3.45-r0 `# pinned to avoid ghostscript-fonts (AGPL)` \
tini \
tzdata \
ca-certificates \
libc6-compat && \
# Cleanup
rm -rf /tmp/* /root/.npm /root/.cache/node /opt/yarn* && \
apk del apk-tools
WORKDIR /home/node
# DHI images use a non-standard global npm path, so we need to set NODE_PATH
# to allow externally installed npm packages to be found by require()
ENV NODE_PATH=/opt/nodejs/node-v${NODE_VERSION}/lib/node_modules
EXPOSE 5678/tcp

View File

@@ -0,0 +1,32 @@
ARG NODE_VERSION=24.13.1
ARG N8N_VERSION=snapshot
FROM n8nio/base:${NODE_VERSION}
ARG N8N_VERSION
ARG N8N_RELEASE_TYPE=dev
ENV NODE_ENV=production
ENV N8N_RELEASE_TYPE=${N8N_RELEASE_TYPE}
ENV SHELL=/bin/sh
WORKDIR /home/node
COPY ./compiled /usr/local/lib/node_modules/n8n
COPY docker/images/n8n/docker-entrypoint.sh /
RUN cd /usr/local/lib/node_modules/n8n && \
npm rebuild sqlite3 && \
ln -s /usr/local/lib/node_modules/n8n/bin/n8n /usr/local/bin/n8n && \
mkdir -p /home/node/.n8n && \
chown -R node:node /home/node && \
rm -rf /root/.npm /tmp/*
EXPOSE 5678/tcp
USER node
ENTRYPOINT ["tini", "--", "/docker-entrypoint.sh"]
LABEL org.opencontainers.image.title="n8n" \
org.opencontainers.image.description="Workflow Automation Tool" \
org.opencontainers.image.source="https://github.com/n8n-io/n8n" \
org.opencontainers.image.url="https://n8n.io" \
org.opencontainers.image.version=${N8N_VERSION}

255
docker/images/n8n/README.md Normal file
View File

@@ -0,0 +1,255 @@
![n8n.io - Workflow Automation](https://user-images.githubusercontent.com/65276001/173571060-9f2f6d7b-bac0-43b6-bdb2-001da9694058.png)
# n8n - Secure Workflow Automation for Technical Teams
n8n is a workflow automation platform that gives technical teams the flexibility of code with the speed of no-code. With 400+ integrations, native AI capabilities, and a fair-code license, n8n lets you build powerful automations while maintaining full control over your data and deployments.
![n8n.io - Screenshot](https://raw.githubusercontent.com/n8n-io/n8n/master/assets/n8n-screenshot-readme.png)
## Key Capabilities
- **Code When You Need It**: Write JavaScript/Python, add npm packages, or use the visual interface
- **AI-Native Platform**: Build AI agent workflows based on LangChain with your own data and models
- **Full Control**: Self-host with our fair-code license or use our [cloud offering](https://app.n8n.cloud/login)
- **Enterprise-Ready**: Advanced permissions, SSO, and air-gapped deployments
- **Active Community**: 400+ integrations and 900+ ready-to-use [templates](https://n8n.io/workflows)
## Contents
- [n8n - Workflow automation tool](#n8n---workflow-automation-tool)
- [Key Capabilities](#key-capabilities)
- [Contents](#contents)
- [Demo](#demo)
- [Available integrations](#available-integrations)
- [Documentation](#documentation)
- [Start n8n in Docker](#start-n8n-in-docker)
- [Use with PostgreSQL](#use-with-postgresql)
- [Passing sensitive data using files](#passing-sensitive-data-using-files)
- [Example server setups](#example-server-setups)
- [Updating](#updating)
- [Pull latest (stable) version](#pull-latest-stable-version)
- [Pull specific version](#pull-specific-version)
- [Pull next (unstable) version](#pull-next-unstable-version)
- [Updating with Docker Compose](#updating-with-docker-compose)
- [Setting Timezone](#setting-the-timezone)
- [Build Docker-Image](#build-docker-image)
- [What does n8n mean and how do you pronounce it?](#what-does-n8n-mean-and-how-do-you-pronounce-it)
- [Support](#support)
- [Jobs](#jobs)
- [License](#license)
## Demo
This [:tv: short video (< 4 min)](https://www.youtube.com/watch?v=RpjQTGKm-ok) goes over key concepts of creating workflows in n8n.
## Available integrations
n8n has 200+ different nodes to automate workflows. A full list can be found at [https://n8n.io/integrations](https://n8n.io/integrations).
## Documentation
The official n8n documentation can be found at [https://docs.n8n.io](https://docs.n8n.io).
Additional information and example workflows are available on the website at [https://n8n.io](https://n8n.io).
## Start n8n in Docker
In the terminal, enter the following:
```bash
docker volume create n8n_data
docker run -it --rm \
--name n8n \
-p 5678:5678 \
-v n8n_data:/home/node/.n8n \
docker.n8n.io/n8nio/n8n
```
This command will download the required n8n image and start your container.
You can then access n8n by opening:
[http://localhost:5678](http://localhost:5678)
To save your work between container restarts, it also mounts a docker volume, `n8n_data`. The workflow data gets saved in an SQLite database in the user folder (`/home/node/.n8n`). This folder also contains important data like the webhook URL and the encryption key used for securing credentials.
If this data can't be found at startup n8n automatically creates a new key and any existing credentials can no longer be decrypted.
## Use with PostgreSQL
By default, n8n uses SQLite to save credentials, past executions and workflows. However, n8n also supports using PostgreSQL.
> **WARNING**: Even when using a different database, it is still important to
persist the `/home/node/.n8n` folder, which also contains essential n8n
user data including the encryption key for the credentials.
In the following commands, replace the placeholders (depicted within angled brackets, e.g. `<POSTGRES_USER>`) with the actual data:
```bash
docker volume create n8n_data
docker run -it --rm \
--name n8n \
-p 5678:5678 \
-e DB_TYPE=postgresdb \
-e DB_POSTGRESDB_DATABASE=<POSTGRES_DATABASE> \
-e DB_POSTGRESDB_HOST=<POSTGRES_HOST> \
-e DB_POSTGRESDB_PORT=<POSTGRES_PORT> \
-e DB_POSTGRESDB_USER=<POSTGRES_USER> \
-e DB_POSTGRESDB_SCHEMA=<POSTGRES_SCHEMA> \
-e DB_POSTGRESDB_PASSWORD=<POSTGRES_PASSWORD> \
-v n8n_data:/home/node/.n8n \
docker.n8n.io/n8nio/n8n
```
A full working setup with docker-compose can be found [here](https://github.com/n8n-io/n8n-hosting/blob/main/docker-compose/withPostgres/README.md).
## Passing sensitive data using files
To avoid passing sensitive information via environment variables, "\_FILE" may be appended to some environment variable names. n8n will then load the data from a file with the given name. This makes it possible to load data easily from Docker and Kubernetes secrets.
The following environment variables support file input:
- DB_POSTGRESDB_DATABASE_FILE
- DB_POSTGRESDB_HOST_FILE
- DB_POSTGRESDB_PASSWORD_FILE
- DB_POSTGRESDB_PORT_FILE
- DB_POSTGRESDB_USER_FILE
- DB_POSTGRESDB_SCHEMA_FILE
## Example server setups
Example server setups for a range of cloud providers and scenarios can be found in the [Server Setup documentation](https://docs.n8n.io/hosting/installation/server-setups/).
## Updating
Before you upgrade to the latest version make sure to check here if there are any breaking changes which may affect you: [Breaking Changes](https://github.com/n8n-io/n8n/blob/master/packages/cli/BREAKING-CHANGES.md)
From your Docker Desktop, navigate to the Images tab and select Pull from the context menu to download the latest n8n image.
You can also use the command line to pull the latest, or a specific version:
### Pull latest (stable) version
```bash
docker pull docker.n8n.io/n8nio/n8n
```
### Pull specific version
```bash
docker pull docker.n8n.io/n8nio/n8n:0.220.1
```
### Pull next (unstable) version
```bash
docker pull docker.n8n.io/n8nio/n8n:next
```
Stop the container and start it again:
1. Get the container ID:
```bash
docker ps -a
```
2. Stop the container with ID container_id:
```bash
docker stop [container_id]
```
3. Remove the container (this does not remove your user data) with ID container_id:
```bash
docker rm [container_id]
```
4. Start the new container:
```bash
docker run --name=[container_name] [options] -d docker.n8n.io/n8nio/n8n
```
### Updating with Docker Compose
If you run n8n using a Docker Compose file, follow these steps to update n8n:
```bash
# Pull latest version
docker compose pull
# Stop and remove older version
docker compose down
# Start the container
docker compose up -d
```
## Setting the timezone
To specify the timezone n8n should use, the environment variable `GENERIC_TIMEZONE` can
be set. One example where this variable has an effect is the Schedule node.
The system's timezone can be set separately with the environment variable `TZ`.
This controls the output of certain scripts and commands such as `$ date`.
For example, to use the same timezone for both:
```bash
docker run -it --rm \
--name n8n \
-p 5678:5678 \
-e GENERIC_TIMEZONE="Europe/Berlin" \
-e TZ="Europe/Berlin" \
docker.n8n.io/n8nio/n8n
```
For more information on configuration and environment variables, please see the [n8n documentation](https://docs.n8n.io/hosting/configuration/environment-variables/).
Here's the refined version with good Markdown formatting, ready for your `README`:
## Build Docker Image
**Important Note for Releases 1.101.0 and Later:**
Building the n8n Docker image now requires a pre-compiled n8n application.
### Recommended Build Process:
For the simplest approach that handles both n8n compilation and Docker image creation, run from the root directory:
```bash
pnpm build:docker
```
### Alternative Builders:
If you are using a different build system that requires a separate build context, first compile the n8n application:
```bash
pnpm run build:deploy
```
Then, ensure your builder's context includes the `compiled` directory generated by this command.
## What does n8n mean and how do you pronounce it?
**Short answer:** It means "nodemation" and it is pronounced as n-eight-n.
**Long answer:** I get that question quite often (more often than I expected) so I decided it is probably best to answer it here. While looking for a good name for the project with a free domain I realized very quickly that all the good ones I could think of were already taken. So, in the end, I chose nodemation. "node-" in the sense that it uses a Node-View and that it uses Node.js and "-mation" for "automation" which is what the project is supposed to help with.
However, I did not like how long the name was and I could not imagine writing something that long every time in the CLI. That is when I then ended up on "n8n". Sure it does not work perfectly but neither does it for Kubernetes (k8s) and I did not hear anybody complain there. So I guess it should be ok.
## Support
If you need more help with n8n, you can ask for support in the [n8n community forum](https://community.n8n.io). This is the best source of answers, as both the n8n support team and community members can help.
## Jobs
If you are interested in working for n8n and so shape the future of the project check out our [job posts](https://jobs.ashbyhq.com/n8n).
## License
You can find the license information [here](https://github.com/n8n-io/n8n/blob/master/README.md#license).

View File

@@ -0,0 +1,15 @@
#!/bin/sh
if [ -d /opt/custom-certificates ]; then
echo "Trusting custom certificates from /opt/custom-certificates."
export NODE_OPTIONS="--use-openssl-ca $NODE_OPTIONS"
export SSL_CERT_DIR=/opt/custom-certificates
c_rehash /opt/custom-certificates
fi
if [ "$#" -gt 0 ]; then
# Got started with arguments
exec n8n "$@"
else
# Got started without arguments
exec n8n
fi

View File

@@ -0,0 +1,154 @@
ARG NODE_VERSION=24.13.1
ARG PYTHON_VERSION=3.13
# ==============================================================================
# STAGE 1: JavaScript runner (@n8n/task-runner) artifact from CI
# ==============================================================================
FROM node:${NODE_VERSION}-alpine AS javascript-runner-builder
COPY ./dist/task-runner-javascript /app/task-runner-javascript
WORKDIR /app/task-runner-javascript
RUN corepack enable pnpm
# Remove `catalog` and `workspace` references from package.json to allow `pnpm add` in extended images
RUN node -e "const pkg = require('./package.json'); \
Object.keys(pkg.dependencies || {}).forEach(k => { \
const val = pkg.dependencies[k]; \
if (val === 'catalog:' || val.startsWith('catalog:') || val.startsWith('workspace:')) \
delete pkg.dependencies[k]; \
}); \
Object.keys(pkg.devDependencies || {}).forEach(k => { \
const val = pkg.devDependencies[k]; \
if (val === 'catalog:' || val.startsWith('catalog:') || val.startsWith('workspace:')) \
delete pkg.devDependencies[k]; \
}); \
delete pkg.devDependencies; \
require('fs').writeFileSync('./package.json', JSON.stringify(pkg, null, 2));"
# Install moment (special case for backwards compatibility)
RUN rm -f node_modules/.modules.yaml && \
pnpm add moment@2.30.1 --prod --no-lockfile
# ==============================================================================
# STAGE 2: Python runner build (@n8n/task-runner-python) with uv
# Produces a relocatable venv tied to the python version used
# ==============================================================================
FROM python:${PYTHON_VERSION}-alpine AS python-runner-builder
ARG TARGETPLATFORM
ARG UV_VERSION=0.8.14
RUN set -e; \
case "$TARGETPLATFORM" in \
"linux/amd64") UV_ARCH="x86_64-unknown-linux-musl" ;; \
"linux/arm64") UV_ARCH="aarch64-unknown-linux-musl" ;; \
*) echo "Unsupported platform: $TARGETPLATFORM" >&2; exit 1 ;; \
esac; \
mkdir -p /tmp/uv && cd /tmp/uv; \
wget -q "https://github.com/astral-sh/uv/releases/download/${UV_VERSION}/uv-${UV_ARCH}.tar.gz"; \
wget -q "https://github.com/astral-sh/uv/releases/download/${UV_VERSION}/uv-${UV_ARCH}.tar.gz.sha256"; \
sha256sum -c "uv-${UV_ARCH}.tar.gz.sha256"; \
tar -xzf "uv-${UV_ARCH}.tar.gz"; \
install -m 0755 "uv-${UV_ARCH}/uv" /usr/local/bin/uv; \
cd / && rm -rf /tmp/uv
WORKDIR /app/task-runner-python
COPY packages/@n8n/task-runner-python/pyproject.toml \
packages/@n8n/task-runner-python/uv.lock** \
packages/@n8n/task-runner-python/.python-version** \
./
RUN uv venv
RUN uv sync \
--frozen \
--no-editable \
--no-install-project \
--no-dev \
--all-extras
COPY packages/@n8n/task-runner-python/ ./
RUN uv sync \
--frozen \
--no-dev \
--all-extras \
--no-editable
# Install the python runner package itself into site packages. We can remove the src directory then
RUN uv pip install . && rm -rf /app/task-runner-python/src
# ==============================================================================
# STAGE 3: Task Runner Launcher download
# ==============================================================================
FROM alpine:3.22 AS launcher-downloader
ARG TARGETPLATFORM
ARG LAUNCHER_VERSION=1.4.3
RUN set -e; \
case "$TARGETPLATFORM" in \
"linux/amd64") ARCH_NAME="amd64" ;; \
"linux/arm64") ARCH_NAME="arm64" ;; \
*) echo "Unsupported platform: $TARGETPLATFORM" && exit 1 ;; \
esac; \
mkdir /launcher-temp && cd /launcher-temp; \
wget -q "https://github.com/n8n-io/task-runner-launcher/releases/download/${LAUNCHER_VERSION}/task-runner-launcher-${LAUNCHER_VERSION}-linux-${ARCH_NAME}.tar.gz"; \
wget -q "https://github.com/n8n-io/task-runner-launcher/releases/download/${LAUNCHER_VERSION}/task-runner-launcher-${LAUNCHER_VERSION}-linux-${ARCH_NAME}.tar.gz.sha256"; \
echo "$(cat task-runner-launcher-${LAUNCHER_VERSION}-linux-${ARCH_NAME}.tar.gz.sha256) task-runner-launcher-${LAUNCHER_VERSION}-linux-${ARCH_NAME}.tar.gz" > checksum.sha256; \
sha256sum -c checksum.sha256; \
mkdir -p /launcher-bin; \
tar xzf task-runner-launcher-${LAUNCHER_VERSION}-linux-${ARCH_NAME}.tar.gz -C /launcher-bin; \
cd / && rm -rf /launcher-temp
# ==============================================================================
# STAGE 4: Node alpine base for JS task runner
# ==============================================================================
FROM node:${NODE_VERSION}-alpine AS node-alpine
# ==============================================================================
# STAGE 5: Runtime
# ==============================================================================
FROM python:${PYTHON_VERSION}-alpine AS runtime
ARG N8N_VERSION=snapshot
ARG N8N_RELEASE_TYPE=dev
ENV NODE_ENV=production \
N8N_RELEASE_TYPE=${N8N_RELEASE_TYPE} \
SHELL=/bin/sh
# Bring `uv` over from python-runner-builder, to make the image easier to extend
COPY --from=python-runner-builder /usr/local/bin/uv /usr/local/bin/uv
# Bring node over from node-alpine
COPY --from=node-alpine /usr/local/bin/node /usr/local/bin/node
# libstdc++ is required by Node
# libc6-compat is required by task-runner-launcher
RUN apk add --no-cache ca-certificates tini libstdc++ libc6-compat && \
apk del apk-tools
# Bring corepack and pnpm over, to make the image easier to extend
COPY --from=node-alpine /usr/local/lib/node_modules/corepack /usr/local/lib/node_modules/corepack
RUN ln -s ../lib/node_modules/corepack/dist/corepack.js /usr/local/bin/corepack && \
ln -s ../lib/node_modules/corepack/dist/pnpm.js /usr/local/bin/pnpm
RUN addgroup -g 1000 -S runner \
&& adduser -u 1000 -S -G runner -h /home/runner -D runner
WORKDIR /home/runner
COPY --from=javascript-runner-builder --chown=root:root /app/task-runner-javascript /opt/runners/task-runner-javascript
COPY --from=python-runner-builder --chown=root:root /app/task-runner-python /opt/runners/task-runner-python
COPY --from=launcher-downloader /launcher-bin/* /usr/local/bin/
COPY --chown=root:root docker/images/runners/n8n-task-runners.json /etc/n8n-task-runners.json
USER runner
EXPOSE 5680/tcp
ENTRYPOINT ["tini", "--", "/usr/local/bin/task-runner-launcher"]
CMD ["javascript", "python"]
LABEL org.opencontainers.image.title="n8n task runners" \
org.opencontainers.image.description="Sidecar image providing n8n task runners for JavaScript and Python code execution" \
org.opencontainers.image.source="https://github.com/n8n-io/n8n" \
org.opencontainers.image.url="https://n8n.io" \
org.opencontainers.image.version="${N8N_VERSION}"

View File

@@ -0,0 +1,198 @@
# ==============================================================================
# DISTROLESS RUNNERS IMAGE
# ==============================================================================
# This is a distroless variant of docker/images/runners/Dockerfile, intended
# for cloud deployments. It removes all shell, package managers, and system
# utilities for security hardening.
#
# Key differences:
# - Uses Debian-based builders (glibc instead of musl)
# - Final image is Google's distroless/cc-debian12
# - Extra runtime-prep stage to organize filesystem
# - Uses distroless nonroot user (UID 65532)
# ==============================================================================
ARG NODE_VERSION=24.13.1
ARG PYTHON_VERSION=3.13
# ==============================================================================
# STAGE 1: JavaScript runner (@n8n/task-runner) artifact from CI
# ==============================================================================
FROM node:${NODE_VERSION}-bookworm-slim AS javascript-runner-builder
COPY ./dist/task-runner-javascript /app/task-runner-javascript
WORKDIR /app/task-runner-javascript
RUN corepack enable pnpm
# Remove `catalog` and `workspace` references from package.json to allow `pnpm add`
RUN node -e "const pkg = require('./package.json'); \
Object.keys(pkg.dependencies || {}).forEach(k => { \
const val = pkg.dependencies[k]; \
if (val === 'catalog:' || val.startsWith('catalog:') || val.startsWith('workspace:')) \
delete pkg.dependencies[k]; \
}); \
Object.keys(pkg.devDependencies || {}).forEach(k => { \
const val = pkg.devDependencies[k]; \
if (val === 'catalog:' || val.startsWith('catalog:') || val.startsWith('workspace:')) \
delete pkg.devDependencies[k]; \
}); \
delete pkg.devDependencies; \
require('fs').writeFileSync('./package.json', JSON.stringify(pkg, null, 2));"
# Install moment by default (special case for n8n cloud)
RUN rm -f node_modules/.modules.yaml && \
pnpm add moment@2.30.1 --prod --no-lockfile
# ==============================================================================
# STAGE 2: Python runner build (@n8n/task-runner-python) with uv
# Produces a relocatable venv tied to the python version used
# ==============================================================================
FROM python:${PYTHON_VERSION}-slim-bookworm AS python-runner-builder
ARG TARGETPLATFORM
ARG UV_VERSION=0.8.14
RUN set -e; \
apt-get update && apt-get install -y --no-install-recommends wget ca-certificates && \
case "$TARGETPLATFORM" in \
"linux/amd64") UV_ARCH="x86_64-unknown-linux-gnu" ;; \
"linux/arm64") UV_ARCH="aarch64-unknown-linux-gnu" ;; \
*) echo "Unsupported platform: $TARGETPLATFORM" >&2; exit 1 ;; \
esac; \
mkdir -p /tmp/uv && cd /tmp/uv; \
wget -q "https://github.com/astral-sh/uv/releases/download/${UV_VERSION}/uv-${UV_ARCH}.tar.gz"; \
wget -q "https://github.com/astral-sh/uv/releases/download/${UV_VERSION}/uv-${UV_ARCH}.tar.gz.sha256"; \
sha256sum -c "uv-${UV_ARCH}.tar.gz.sha256"; \
tar -xzf "uv-${UV_ARCH}.tar.gz"; \
install -m 0755 "uv-${UV_ARCH}/uv" /usr/local/bin/uv; \
cd / && rm -rf /tmp/uv && \
apt-get clean && rm -rf /var/lib/apt/lists/*
WORKDIR /app/task-runner-python
COPY packages/@n8n/task-runner-python/pyproject.toml \
packages/@n8n/task-runner-python/uv.lock** \
packages/@n8n/task-runner-python/.python-version** \
./
RUN uv venv
RUN uv sync \
--frozen \
--no-editable \
--no-install-project \
--no-dev \
--all-extras
COPY packages/@n8n/task-runner-python/ ./
RUN uv sync \
--frozen \
--no-dev \
--all-extras \
--no-editable
# Install the python runner package itself into site packages. We can remove the src directory then
RUN uv pip install . && rm -rf /app/task-runner-python/src
# ==============================================================================
# STAGE 3: Task Runner Launcher download
# ==============================================================================
FROM debian:bookworm-slim AS launcher-downloader
ARG TARGETPLATFORM
ARG LAUNCHER_VERSION=1.4.3
RUN set -e; \
apt-get update && apt-get install -y --no-install-recommends wget ca-certificates && \
case "$TARGETPLATFORM" in \
"linux/amd64") ARCH_NAME="amd64" ;; \
"linux/arm64") ARCH_NAME="arm64" ;; \
*) echo "Unsupported platform: $TARGETPLATFORM" && exit 1 ;; \
esac; \
mkdir /launcher-temp && cd /launcher-temp; \
wget -q "https://github.com/n8n-io/task-runner-launcher/releases/download/${LAUNCHER_VERSION}/task-runner-launcher-${LAUNCHER_VERSION}-linux-${ARCH_NAME}.tar.gz"; \
wget -q "https://github.com/n8n-io/task-runner-launcher/releases/download/${LAUNCHER_VERSION}/task-runner-launcher-${LAUNCHER_VERSION}-linux-${ARCH_NAME}.tar.gz.sha256"; \
echo "$(cat task-runner-launcher-${LAUNCHER_VERSION}-linux-${ARCH_NAME}.tar.gz.sha256) task-runner-launcher-${LAUNCHER_VERSION}-linux-${ARCH_NAME}.tar.gz" > checksum.sha256; \
sha256sum -c checksum.sha256; \
mkdir -p /launcher-bin; \
tar xzf task-runner-launcher-${LAUNCHER_VERSION}-linux-${ARCH_NAME}.tar.gz -C /launcher-bin; \
cd / && rm -rf /launcher-temp && \
apt-get clean && rm -rf /var/lib/apt/lists/*
# ==============================================================================
# STAGE 4: Node Debian base for JS task runner
# ==============================================================================
FROM node:${NODE_VERSION}-bookworm-slim AS node-debian
# ==============================================================================
# STAGE 5: Runtime preparation
# ==============================================================================
# Prepare a clean filesystem structure with all necessary files before
# copying to the distroless base. This stage runs with a shell so we can
# create symlinks and organize files properly.
# ==============================================================================
FROM debian:bookworm-slim AS runtime-prep
# Copy Python runtime
COPY --from=python-runner-builder /usr/local/bin/python3.13 /runtime/usr/local/bin/python3.13
COPY --from=python-runner-builder /usr/local/lib/python3.13 /runtime/usr/local/lib/python3.13
COPY --from=python-runner-builder /usr/local/lib/libpython3.13.so* /runtime/usr/local/lib/
# Copy Python dependencies (architecture-specific directories)
# The /* glob will match x86_64-linux-gnu or aarch64-linux-gnu
COPY --from=python-runner-builder /lib/*-linux-gnu* /runtime/lib/
COPY --from=python-runner-builder /usr/lib/*-linux-gnu* /runtime/usr/lib/
# Copy Node.js runtime
COPY --from=node-debian /usr/local/bin/node /runtime/usr/local/bin/node
# Copy task runners
COPY --from=javascript-runner-builder /app/task-runner-javascript /runtime/opt/runners/task-runner-javascript
COPY --from=python-runner-builder /app/task-runner-python /runtime/opt/runners/task-runner-python
# Copy launcher
COPY --from=launcher-downloader /launcher-bin/* /runtime/usr/local/bin/
# Copy configuration
COPY docker/images/runners/n8n-task-runners.json /runtime/etc/n8n-task-runners.json
# Create necessary directories with proper permissions
RUN mkdir -p /runtime/home/runner && \
chmod 755 /runtime/home/runner && \
chmod +x /runtime/usr/local/bin/*
# ==============================================================================
# STAGE 6: Distroless Runtime
# ==============================================================================
# Uses Google's distroless/cc-debian12 which provides:
# - glibc, libgcc, libstdc++
# - CA certificates
# - Timezone data
# - nonroot user (UID 65532)
# - NO shell, NO package manager, NO system utilities
# ==============================================================================
FROM gcr.io/distroless/cc-debian12:latest AS runtime
ARG N8N_VERSION=snapshot
ARG N8N_RELEASE_TYPE=dev
ENV NODE_ENV=production \
N8N_RELEASE_TYPE=${N8N_RELEASE_TYPE} \
HOME=/home/runner
# Copy everything from the prepared runtime filesystem
COPY --from=runtime-prep --chown=root:root /runtime/ /
WORKDIR /home/runner
# Switch to nonroot user (UID 65532)
USER 65532:65532
EXPOSE 5680/tcp
ENTRYPOINT ["/usr/local/bin/task-runner-launcher"]
CMD ["javascript", "python"]
LABEL org.opencontainers.image.title="n8n task runners (distroless)" \
org.opencontainers.image.description="Distroless sidecar image providing n8n task runners for JavaScript and Python code execution" \
org.opencontainers.image.source="https://github.com/n8n-io/n8n" \
org.opencontainers.image.url="https://n8n.io" \
org.opencontainers.image.version="${N8N_VERSION}"

View File

@@ -0,0 +1,56 @@
# n8n - Task runners (`n8nio/runners`) - (PREVIEW)
`n8nio/runners` image includes [JavaScript runner](https://github.com/n8n-io/n8n/tree/master/packages/%40n8n/task-runner),
[Python runner](https://github.com/n8n-io/n8n/tree/master/packages/%40n8n/task-runner-python) and
[Task runner launcher](https://github.com/n8n-io/task-runner-launcher) that connects to a Task Broker
running on the main n8n instance when running in `external` mode. This image is to be launched as a sidecar
container to the main n8n container.
[Task runners](https://docs.n8n.io/hosting/configuration/task-runners/) are used to execute user-provided code
in the [Code Node](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.code/), isolated from the n8n instance.
For official documentation, please see [here](https://docs.n8n.io/hosting/configuration/task-runners/).
For a distroless variant of this image, see [here](./Dockerfile.distroless).
For development purposes only, see below.
## Testing locally
### 1) Make a production build of n8n
```
pnpm run build:n8n
```
### 2) Build the task runners image
```
docker buildx build \
-f docker/images/runners/Dockerfile \
-t n8nio/runners \
.
```
### 3) Start n8n on your host machine with Task Broker enabled
```
N8N_RUNNERS_MODE=external \
N8N_RUNNERS_AUTH_TOKEN=test \
N8N_LOG_LEVEL=debug \
pnpm start
```
### 4) Start the task runner container
```
docker run --rm -it \
-e N8N_RUNNERS_AUTH_TOKEN=test \
-e N8N_RUNNERS_LAUNCHER_LOG_LEVEL=debug \
-e N8N_RUNNERS_TASK_BROKER_URI=http://host.docker.internal:5679 \
-p 5680:5680 \
n8nio/runners
```
If you need to add extra dependencies (custom image), follow [these instructions](https://docs.n8n.io/hosting/configuration/task-runners/#adding-extra-dependencies).

View File

@@ -0,0 +1,55 @@
{
"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": ["-I", "-B", "-X", "disable_remote_debug", "-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_SENTRY_DSN",
"N8N_VERSION",
"ENVIRONMENT",
"DEPLOYMENT_NAME"
],
"env-overrides": {
"N8N_RUNNERS_STDLIB_ALLOW": "",
"N8N_RUNNERS_EXTERNAL_ALLOW": ""
}
}
]
}