n8n Runner 内置浏览器配置指南
在 n8n 中做网页自动化、截图或采集时,常需在 Task Runner 镜像内安装 Chromium 及 Python 库(如 DrissionPage)。本文说明如何扩展 Runner 的 Dockerfile、重建镜像并验证 Code 节点示例。
步骤一:修改 Dockerfile
将 /opt/n8n/Dockerfile 替换为与当前 Runner 版本一致的示例(版本号请与主流程对齐):
dockerfile
# 与 n8n / runners 主版本一致,示例 2.9.2
ARG RUNNERS_VERSION=2.9.2
# Stage 1:在 Alpine 中准备 Chromium 与字体等
FROM alpine:3.23 AS chromium-builder
RUN apk add --no-cache \
chromium \
nss \
freetype \
harfbuzz \
ca-certificates \
ttf-freefont
# Stage 2:合并进官方 runners 镜像
FROM n8nio/runners:2.9.2
USER root
COPY --from=chromium-builder /usr/lib/ /usr/lib/
COPY --from=chromium-builder /usr/share/fonts/ /usr/share/fonts/
COPY --from=chromium-builder /usr/bin/chromium-browser /usr/bin/chromium-browser
RUN ln -sf /usr/lib/chromium/chromium /usr/bin/chromium 2>/dev/null || true
RUN cd /opt/runners/task-runner-python && \
uv pip install --python .venv/bin/python --no-cache \
bilibili-api-python \
DrissionPage
USER runner步骤二:构建并重启
bash
cd /opt/n8n
docker build --no-cache -t n8nio/runners:custom .
docker compose up -d代码示例
DrissionPage:打开页面并取标题
python
from DrissionPage import Chromium, ChromiumOptions
co = ChromiumOptions().set_browser_path('/usr/bin/chromium-browser')
co.headless()
co.set_argument('--no-sandbox')
co.set_argument('--disable-setuid-sandbox')
co.set_argument('--disable-dev-shm-usage')
browser = Chromium(addr_or_opts=co)
page = browser.new_tab()
page.get('https://example.com')
title = page.title
html = page.html
browser.quit()
return [{'json': {'title': title}}]DrissionPage:截图并作为 binary 输出
python
import base64
from DrissionPage import Chromium, ChromiumOptions
co = ChromiumOptions().set_browser_path('/usr/bin/chromium-browser')
co.headless()
co.set_argument('--no-sandbox')
co.set_argument('--disable-setuid-sandbox')
co.set_argument('--disable-dev-shm-usage')
browser = Chromium(addr_or_opts=co)
page = browser.new_tab()
page.get('https://example.com')
screenshot = page.get_screenshot(as_bytes=True)
browser.quit()
return [{
'json': {'url': 'https://example.com'},
'binary': {
'screenshot': {
'data': base64.b64encode(screenshot).decode('utf-8'),
'mimeType': 'image/png',
'fileName': 'screenshot.png'
}
}
}]