|
| 1 | +ARG PYTHON_IMAGE=python:3.13-slim |
| 2 | + |
| 3 | +# ============================================================================== |
| 4 | +# STAGE 1: JavaScript runner (@n8n/task-runner) artifact from CI |
| 5 | +# ============================================================================== |
| 6 | +FROM alpine:3.22.1 AS app-artifact-processor |
| 7 | +COPY ./dist/task-runner-javascript /app/task-runner-javascript |
| 8 | + |
| 9 | +# ============================================================================== |
| 10 | +# STAGE 2: Python runner build (@n8n/task-runner-python) with uv |
| 11 | +# Produces a relocatable venv tied to PYTHON_IMAGE |
| 12 | +# ============================================================================== |
| 13 | +FROM ${PYTHON_IMAGE} AS python-runner-builder |
| 14 | +ARG TARGETPLATFORM |
| 15 | +ARG UV_VERSION=0.8.14 |
| 16 | + |
| 17 | +RUN apt-get update && apt-get install -y --no-install-recommends \ |
| 18 | + curl ca-certificates build-essential pkg-config git \ |
| 19 | + && rm -rf /var/lib/apt/lists/* |
| 20 | + |
| 21 | +RUN set -e; \ |
| 22 | + case "$TARGETPLATFORM" in \ |
| 23 | + "linux/amd64") UV_ARCH="x86_64-unknown-linux-gnu" ;; \ |
| 24 | + "linux/arm64") UV_ARCH="aarch64-unknown-linux-gnu" ;; \ |
| 25 | + *) echo "Unsupported platform: $TARGETPLATFORM" >&2; exit 1 ;; \ |
| 26 | + esac; \ |
| 27 | + mkdir -p /tmp/uv && cd /tmp/uv; \ |
| 28 | + curl -fsSLO "https://github.com/astral-sh/uv/releases/download/${UV_VERSION}/uv-${UV_ARCH}.tar.gz"; \ |
| 29 | + curl -fsSLO "https://github.com/astral-sh/uv/releases/download/${UV_VERSION}/uv-${UV_ARCH}.tar.gz.sha256"; \ |
| 30 | + sha256sum -c "uv-${UV_ARCH}.tar.gz.sha256"; \ |
| 31 | + tar -xzf "uv-${UV_ARCH}.tar.gz"; \ |
| 32 | + install -m 0755 "uv-${UV_ARCH}/uv" /usr/local/bin/uv; \ |
| 33 | + cd / && rm -rf /tmp/uv |
| 34 | + |
| 35 | +WORKDIR /app/task-runner-python |
| 36 | + |
| 37 | +COPY packages/@n8n/task-runner-python/pyproject.toml \ |
| 38 | + packages/@n8n/task-runner-python/uv.lock** \ |
| 39 | + packages/@n8n/task-runner-python/.python-version** \ |
| 40 | + ./ |
| 41 | + |
| 42 | +RUN uv venv |
| 43 | +RUN uv sync \ |
| 44 | + --frozen \ |
| 45 | + --no-editable \ |
| 46 | + --no-install-project \ |
| 47 | + --all-extras |
| 48 | + |
| 49 | +COPY packages/@n8n/task-runner-python/ ./ |
| 50 | +RUN uv sync \ |
| 51 | + --frozen \ |
| 52 | + --no-editable |
| 53 | + |
| 54 | +# ============================================================================== |
| 55 | +# STAGE 3: Task Runner Launcher download |
| 56 | +# ============================================================================== |
| 57 | +FROM alpine:3.22.1 AS launcher-downloader |
| 58 | +ARG TARGETPLATFORM |
| 59 | +ARG LAUNCHER_VERSION=1.3.0 |
| 60 | + |
| 61 | +RUN set -e; \ |
| 62 | + case "$TARGETPLATFORM" in \ |
| 63 | + "linux/amd64") ARCH_NAME="amd64" ;; \ |
| 64 | + "linux/arm64") ARCH_NAME="arm64" ;; \ |
| 65 | + *) echo "Unsupported platform: $TARGETPLATFORM" && exit 1 ;; \ |
| 66 | + esac; \ |
| 67 | + mkdir /launcher-temp && cd /launcher-temp; \ |
| 68 | + wget -q "https://github.com/n8n-io/task-runner-launcher/releases/download/${LAUNCHER_VERSION}/task-runner-launcher-${LAUNCHER_VERSION}-linux-${ARCH_NAME}.tar.gz"; \ |
| 69 | + 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"; \ |
| 70 | + 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; \ |
| 71 | + sha256sum -c checksum.sha256; \ |
| 72 | + mkdir -p /launcher-bin; \ |
| 73 | + tar xzf task-runner-launcher-${LAUNCHER_VERSION}-linux-${ARCH_NAME}.tar.gz -C /launcher-bin; \ |
| 74 | + cd / && rm -rf /launcher-temp |
| 75 | + |
| 76 | +# ============================================================================== |
| 77 | +# STAGE 4: Runtime |
| 78 | +# ============================================================================== |
| 79 | +FROM ${PYTHON_IMAGE} AS runtime |
| 80 | +ARG NODE_VERSION=22 |
| 81 | +ARG N8N_VERSION=snapshot |
| 82 | +ARG N8N_RELEASE_TYPE=dev |
| 83 | + |
| 84 | +ENV NODE_ENV=production |
| 85 | +ENV N8N_RELEASE_TYPE=${N8N_RELEASE_TYPE} |
| 86 | +ENV SHELL=/bin/sh |
| 87 | + |
| 88 | +RUN apt-get update \ |
| 89 | + && apt-get install -y --no-install-recommends curl gnupg ca-certificates tini \ |
| 90 | + && mkdir -p /etc/apt/keyrings \ |
| 91 | + && curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key \ |
| 92 | + | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg \ |
| 93 | + && echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_${NODE_VERSION}.x nodistro main" \ |
| 94 | + > /etc/apt/sources.list.d/nodesource.list \ |
| 95 | + && apt-get update \ |
| 96 | + && apt-get install -y --no-install-recommends nodejs \ |
| 97 | + && apt-get remove curl -y \ |
| 98 | + && apt-get clean \ |
| 99 | + && rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/*.deb |
| 100 | + |
| 101 | +RUN useradd -m -u 1000 runner |
| 102 | +WORKDIR /home/runner |
| 103 | + |
| 104 | +COPY --from=app-artifact-processor /app/task-runner-javascript /opt/runners/task-runner-javascript |
| 105 | +COPY --from=python-runner-builder /app/task-runner-python /opt/runners/task-runner-python |
| 106 | +COPY --from=launcher-downloader /launcher-bin/* /usr/local/bin/ |
| 107 | + |
| 108 | +COPY docker/images/runners/n8n-task-runners.json /etc/n8n-task-runners.json |
| 109 | + |
| 110 | +RUN chown -R runner:runner /opt/runners /home/runner |
| 111 | +USER runner |
| 112 | + |
| 113 | +EXPOSE 5680/tcp |
| 114 | +ENTRYPOINT ["tini", "--", "/usr/local/bin/task-runner-launcher"] |
| 115 | +CMD ["javascript", "python"] |
| 116 | + |
| 117 | +LABEL org.opencontainers.image.title="n8n task runners" \ |
| 118 | + org.opencontainers.image.description="Sidecar image providing n8n task runners for JavaScript and Python code execution" \ |
| 119 | + org.opencontainers.image.source="https://github.com/n8n-io/n8n" \ |
| 120 | + org.opencontainers.image.url="https://n8n.io" \ |
| 121 | + org.opencontainers.image.version="${N8N_VERSION}" |
0 commit comments