mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-16 17:46:45 +00:00
ci: Add Dockerfile for multi-runner task runners image (#18975)
This commit is contained in:
121
docker/images/runners/Dockerfile
Normal file
121
docker/images/runners/Dockerfile
Normal file
@@ -0,0 +1,121 @@
|
||||
ARG PYTHON_IMAGE=python:3.13-slim
|
||||
|
||||
# ==============================================================================
|
||||
# STAGE 1: JavaScript runner (@n8n/task-runner) artifact from CI
|
||||
# ==============================================================================
|
||||
FROM alpine:3.22.1 AS app-artifact-processor
|
||||
COPY ./dist/task-runner-javascript /app/task-runner-javascript
|
||||
|
||||
# ==============================================================================
|
||||
# STAGE 2: Python runner build (@n8n/task-runner-python) with uv
|
||||
# Produces a relocatable venv tied to PYTHON_IMAGE
|
||||
# ==============================================================================
|
||||
FROM ${PYTHON_IMAGE} AS python-runner-builder
|
||||
ARG TARGETPLATFORM
|
||||
ARG UV_VERSION=0.8.14
|
||||
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
curl ca-certificates build-essential pkg-config git \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN set -e; \
|
||||
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; \
|
||||
curl -fsSLO "https://github.com/astral-sh/uv/releases/download/${UV_VERSION}/uv-${UV_ARCH}.tar.gz"; \
|
||||
curl -fsSLO "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 \
|
||||
--all-extras
|
||||
|
||||
COPY packages/@n8n/task-runner-python/ ./
|
||||
RUN uv sync \
|
||||
--frozen \
|
||||
--no-editable
|
||||
|
||||
# ==============================================================================
|
||||
# STAGE 3: Task Runner Launcher download
|
||||
# ==============================================================================
|
||||
FROM alpine:3.22.1 AS launcher-downloader
|
||||
ARG TARGETPLATFORM
|
||||
ARG LAUNCHER_VERSION=1.3.0
|
||||
|
||||
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: Runtime
|
||||
# ==============================================================================
|
||||
FROM ${PYTHON_IMAGE} AS runtime
|
||||
ARG NODE_VERSION=22
|
||||
ARG N8N_VERSION=snapshot
|
||||
ARG N8N_RELEASE_TYPE=dev
|
||||
|
||||
ENV NODE_ENV=production
|
||||
ENV N8N_RELEASE_TYPE=${N8N_RELEASE_TYPE}
|
||||
ENV SHELL=/bin/sh
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends curl gnupg ca-certificates tini \
|
||||
&& mkdir -p /etc/apt/keyrings \
|
||||
&& curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key \
|
||||
| gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg \
|
||||
&& echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_${NODE_VERSION}.x nodistro main" \
|
||||
> /etc/apt/sources.list.d/nodesource.list \
|
||||
&& apt-get update \
|
||||
&& apt-get install -y --no-install-recommends nodejs \
|
||||
&& apt-get remove curl -y \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/*.deb
|
||||
|
||||
RUN useradd -m -u 1000 runner
|
||||
WORKDIR /home/runner
|
||||
|
||||
COPY --from=app-artifact-processor /app/task-runner-javascript /opt/runners/task-runner-javascript
|
||||
COPY --from=python-runner-builder /app/task-runner-python /opt/runners/task-runner-python
|
||||
COPY --from=launcher-downloader /launcher-bin/* /usr/local/bin/
|
||||
|
||||
COPY docker/images/runners/n8n-task-runners.json /etc/n8n-task-runners.json
|
||||
|
||||
RUN chown -R runner:runner /opt/runners /home/runner
|
||||
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}"
|
||||
50
docker/images/runners/README.md
Normal file
50
docker/images/runners/README.md
Normal file
@@ -0,0 +1,50 @@
|
||||
# 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.
|
||||
|
||||
|
||||
## Testing locally
|
||||
|
||||
1. Make a production build of n8n
|
||||
|
||||
```
|
||||
pnpm run build:n8n
|
||||
```
|
||||
|
||||
2. Build the task runners image
|
||||
|
||||
```
|
||||
docker buildx build --no-cache \
|
||||
-f docker/images/runners/Dockerfile \
|
||||
-t n8nio/runners \
|
||||
.
|
||||
```
|
||||
|
||||
3. Start n8n on your host machine with Task Broker enabled
|
||||
|
||||
```
|
||||
N8N_RUNNERS_ENABLED=true \
|
||||
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
|
||||
```
|
||||
48
docker/images/runners/n8n-task-runners.json
Normal file
48
docker/images/runners/n8n-task-runners.json
Normal file
@@ -0,0 +1,48 @@
|
||||
{
|
||||
"task-runners": [
|
||||
{
|
||||
"runner-type": "javascript",
|
||||
"workdir": "/home/runner",
|
||||
"command": "/usr/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",
|
||||
"N8N_RUNNERS_MAX_CONCURRENCY",
|
||||
"NODE_OPTIONS",
|
||||
"N8N_SENTRY_DSN",
|
||||
"N8N_VERSION",
|
||||
"ENVIRONMENT",
|
||||
"DEPLOYMENT_NAME"
|
||||
],
|
||||
"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_SENTRY_DSN",
|
||||
"N8N_VERSION",
|
||||
"ENVIRONMENT",
|
||||
"DEPLOYMENT_NAME"
|
||||
],
|
||||
"env-overrides": {
|
||||
"PYTHONPATH": "/opt/runners/task-runner-python"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user