Spaces:
Sleeping
Sleeping
File size: 6,380 Bytes
e4fbb50 967a040 e4fbb50 da1bcc5 e4fbb50 f0cbeae e4fbb50 b4dd3ad 75fb63c 5a27c8e b4dd3ad f0cbeae b4dd3ad 0069402 fd06513 2d97948 1b6ef52 2d97948 3f73fdd 2d97948 bc03a8f fd06513 75fb63c b4dd3ad e4fbb50 ad5bc33 0069402 75fb63c e4fbb50 75fb63c 2d97948 3f73fdd 7a4fde2 aa0785d 72eeb27 aa0785d 72eeb27 75fb63c 62f4408 75fb63c e4fbb50 b4dd3ad 59802b0 e4fbb50 b4dd3ad e4fbb50 2d97948 e4fbb50 1b6ef52 e4fbb50 967a040 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 | # 使用 PostgreSQL 作为基础镜像
FROM nikolaik/python-nodejs:python3.12-nodejs22
# 添加维护者信息
LABEL maintainer="ai来事 <https://www.youtube.com/@all.ai.>"
ARG CACHEBUST=2
# 设置构建参数,提供默认值
ARG WEBHOOK_URL=https://你的hf账户名-空间名.hf.space/
ARG POSTGRESDB_PORT=5432
# 设置基本环境变量
ENV WEBHOOK_URL=${WEBHOOK_URL} \
N8N_HOST=0.0.0.0 \
N8N_PORT=7860 \
N8N_PROTOCOL=https \
GENERIC_TIMEZONE=Asia/Shanghai \
N8N_METRICS=true \
QUEUE_HEALTH_CHECK_ACTIVE=true \
N8N_PAYLOAD_SIZE_MAX=256 \
N8N_LOG_LEVEL=info \
EXECUTIONS_DATA_MAX_AGE=168 \
EXECUTIONS_DATA_PRUNE=true \
N8N_EXECUTE_IN_PROCESS=false \
DB_TYPE=postgresdb \
DB_POSTGRESDB_PORT=${POSTGRESDB_PORT} \
VIRTUAL_ENV=/home/pn/venv \
PATH="/home/pn/venv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$PATH" \
# 添加 Redis 配置
QUEUE_BULL_REDIS_HOST=localhost \
QUEUE_BULL_REDIS_PORT=6379 \
QUEUE_BULL_REDIS_DB=0 \
N8N_QUEUE_BULL_REDIS_PREFIX=n8n:queue \
EXECUTIONS_MODE=regular \
# 添加 Qdrant 配置
QDRANT_HOST=http://localhost \
QDRANT_PORT=6333 \
QDRANT_VERSION=1.12.4 \
# 添加超时配置
WAIT_TIMEOUT=30 \
DB_POSTGRESDB_SSL_REJECT_UNAUTHORIZED=false \
N8N_DISABLE_TASK_BROKER=false \
N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=false \
# Skip webhook deregistration on shutdown for cleaner restarts
N8N_SKIP_WEBHOOK_DEREGISTRATION_SHUTDOWN=true \
# Disable worker offloading since we're using regular mode
OFFLOAD_MANUAL_EXECUTIONS_TO_WORKERS=false \
# ── Fix: force node-gyp to always use system Python, never the venv ──
# This is the key line that makes native addon compilation future-proof.
# No matter what Python version or venv state exists, node-gyp will
# always use the system Python which has setuptools installed via apt.
NODE_GYP_FORCE_PYTHON=/usr/bin/python3
# 安装系统依赖
RUN apt-get update && apt-get install -y --no-install-recommends \
curl \
unzip \
gnupg \
build-essential \
sudo \
vim \
git \
procps \
lsof \
net-tools \
ca-certificates \
openssl \
tzdata \
htop \
jq \
netcat-openbsd \
redis-server \
# ── Fix: install setuptools and python3-dev system-wide ──────────────
# python3-setuptools: restores 'distutils' for Python 3.12+ which
# removed it from stdlib. Required by node-gyp for native addons.
# python3-dev: provides Python C headers needed for any native builds.
# Being apt-managed means it auto-updates with OS and stays compatible
# with whatever Python version the base image ships in the future.
python3-setuptools \
python3-dev \
&& ln -fs /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
&& dpkg-reconfigure --frontend noninteractive tzdata \
\
# ── Qdrant ────────────────────────────────────────────────────────────
&& cd /tmp \
&& curl -L https://github.com/qdrant/qdrant/releases/download/v${QDRANT_VERSION}/qdrant-x86_64-unknown-linux-gnu.tar.gz -o qdrant.tar.gz \
&& tar xvf qdrant.tar.gz \
&& mv qdrant /usr/local/bin/ \
&& rm qdrant.tar.gz \
&& mkdir -p /home/pn/.n8n/qdrant/storage \
&& mkdir -p /home/pn/.n8n/qdrant/config \
&& mkdir -p /home/pn/.n8n/qdrant/snapshots \
&& chown -R pn:pn /home/pn/.n8n/qdrant \
&& chmod -R 755 /home/pn/.n8n/qdrant \
\
# ── Node / n8n ─────────────────────────────────────────────────────────
# IMPORTANT: npm install runs BEFORE venv creation.
# If venv existed first, node-gyp could pick up venv's Python
# (which has no distutils) even with NODE_GYP_FORCE_PYTHON set.
# Correct order: npm → venv (never the other way around).
#
# node-gyp is pre-installed globally so it's ready for any native
# addon that n8n@latest or future versions might include.
&& npm install -g node-gyp \
&& npm install -g --force n8n@latest pnpm \
&& npm cache clean --force \
\
# ── Python venv ────────────────────────────────────────────────────────
# Created AFTER npm so the venv Python is never in scope during
# node-gyp builds. setuptools is also installed inside the venv
# so pip itself and any venv-based tools stay future-proof too.
&& python3 -m venv ${VIRTUAL_ENV} \
&& ${VIRTUAL_ENV}/bin/pip install --no-cache-dir --upgrade \
pip \
setuptools \
requests \
yt-dlp \
youtube-transcript-api \
\
# ── Cleanup ────────────────────────────────────────────────────────────
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
# 创建环境变量文件
RUN --mount=type=secret,id=POSTGRES_USER,mode=0444,required=true \
--mount=type=secret,id=POSTGRES_PASSWORD,mode=0444,required=true \
--mount=type=secret,id=POSTGRES_DB,mode=0444,required=true \
--mount=type=secret,id=POSTGRESDB_HOST,mode=0444,required=true \
echo "export DB_POSTGRESDB_HOST=$(cat /run/secrets/POSTGRESDB_HOST)" >> /home/pn/.env && \
echo "export DB_POSTGRESDB_USER=$(cat /run/secrets/POSTGRES_USER)" >> /home/pn/.env && \
echo "export DB_POSTGRESDB_PASSWORD=$(cat /run/secrets/POSTGRES_PASSWORD)" >> /home/pn/.env && \
echo "export DB_POSTGRESDB_DATABASE=$(cat /run/secrets/POSTGRES_DB)" >> /home/pn/.env && \
chown pn:pn /home/pn/.env
# 创建工作目录
WORKDIR /home/pn/n8n
# 复制启动脚本并创建数据目录
COPY --chown=pn:pn run.sh ./run.sh
COPY --chown=pn:pn config/n8n_env.sh ./config/n8n_env.sh
RUN chmod +x ./run.sh \
&& mkdir -p /home/pn/.n8n \
&& chown -R pn:pn /home/pn/.n8n \
&& chown -R pn:pn /home/pn/n8n
# 暴露端口
EXPOSE 7860
# 切换到非 root 用户
USER pn
# 设置数据卷
VOLUME ["/home/pn/.n8n"]
# 启动命令
CMD ["./run.sh"] |