Files
BiliNote/Dockerfile.complete
huangjianwu f1b091b846 chore(deploy): docker 镜像源/restart 策略 + .env 修正 + 文档
- 所有 Dockerfile 加 BASE_REGISTRY build-arg,国内拉不到 docker.io
  时可换 daocloud 等镜像源;compose 透传该 arg
- docker-compose: restart 从 on-failure:3 改 unless-stopped(避免短暂
  崩溃后永久打死);gpu compose 补齐 healthcheck/restart/mem_limit
- Dockerfile.complete: supervisord 用 %(ENV_*)s 透传环境变量给 backend
  子进程(之前只白名单 2 个,docker run -e 配的变量后端看不到)
- .env.example: 修正 VITE_API_BASE_URL 端口(8000→8483)、
  WHISPER_MODEL_SIZE medium→tiny(首次启动不被大模型下载卡住)、
  补 Docker 部署说明注释
- README: 新增 Docker 部署常见问题 FAQ(镜像源/restart/数据持久化等)
- CLAUDE.md: 勘误(移除不存在的 messaging/i18n/worker_registry 描述,
  修正 events 路径),补 pytest/typecheck 命令

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 19:01:55 +08:00

135 lines
6.1 KiB
Docker
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# BASE_REGISTRY 默认 docker.io国内拉不到可换镜像源
# docker build --build-arg BASE_REGISTRY=docker.m.daocloud.io -f Dockerfile.complete .
ARG BASE_REGISTRY=docker.io
# === 阶段1构建 Backend ===
FROM ${BASE_REGISTRY}/library/python:3.11-slim AS backend-builder
ARG APT_MIRROR=mirrors.tuna.tsinghua.edu.cn
ARG PIP_INDEX=https://pypi.tuna.tsinghua.edu.cn/simple
RUN set -ex && \
rm -f /etc/apt/sources.list && \
rm -rf /etc/apt/sources.list.d/* && \
echo "deb http://${APT_MIRROR}/debian bookworm main contrib non-free non-free-firmware" > /etc/apt/sources.list && \
echo "deb http://${APT_MIRROR}/debian bookworm-updates main contrib non-free non-free-firmware" >> /etc/apt/sources.list && \
echo "deb http://${APT_MIRROR}/debian-security bookworm-security main contrib non-free non-free-firmware" >> /etc/apt/sources.list && \
apt-get update && \
apt-get install -y --no-install-recommends ffmpeg && \
rm -rf /var/lib/apt/lists/*
ENV PATH="/usr/bin:${PATH}"
ENV HF_ENDPOINT=https://hf-mirror.com
WORKDIR /tmp/backend
# 先复制 requirements.txt 利用层缓存
COPY ./backend/requirements.txt /tmp/backend/requirements.txt
RUN pip install --no-cache-dir -i ${PIP_INDEX} -r requirements.txt
COPY ./backend /tmp/backend
# === 阶段2构建 Frontend ===
# Node 18-alpine 跑不动 Tailwind v4 / Vite 6前者要求 Node 20+,后者推荐 Node 20+
# 升到 node:20-alpine。alpine 走 muslpnpm 会按 lockfile 拉 *-linux-x64-musl native binary。
ARG BASE_REGISTRY=docker.io
FROM ${BASE_REGISTRY}/library/node:20-alpine AS frontend-builder
# pnpm 版本 pin 到 9 系列:
# - lockfile (BillNote_frontend/pnpm-lock.yaml) 是 lockfileVersion '9.0',由 pnpm 9 生成
# - pnpm 11+ 要求 Node 22+,与 node:20 不兼容ERR_UNKNOWN_BUILTIN_MODULE
# - 不用 @latest 避免上游 pnpm 升级悄悄破坏 CI
RUN corepack enable && corepack prepare pnpm@9.15.0 --activate
WORKDIR /tmp/frontend
# 先复制 package.json + lockfile 利用依赖层缓存
# --frozen-lockfile 保证 CI 与本地开发依赖版本一致,杜绝 semver 漂移引入的破坏性升级
COPY ./BillNote_frontend/package.json ./BillNote_frontend/pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile
COPY ./BillNote_frontend /tmp/frontend
# 设置环境变量,告诉 vite.config.ts 这是 Docker 构建
ENV DOCKER_BUILD=1
RUN pnpm run build
# === 阶段3完整应用镜像 ===
ARG BASE_REGISTRY=docker.io
FROM ${BASE_REGISTRY}/library/python:3.11-slim
ARG APT_MIRROR=mirrors.tuna.tsinghua.edu.cn
# 安装必要的运行时依赖
RUN set -ex && \
rm -f /etc/apt/sources.list && \
rm -rf /etc/apt/sources.list.d/* && \
echo "deb http://${APT_MIRROR}/debian bookworm main contrib non-free non-free-firmware" > /etc/apt/sources.list && \
echo "deb http://${APT_MIRROR}/debian bookworm-updates main contrib non-free non-free-firmware" >> /etc/apt/sources.list && \
echo "deb http://${APT_MIRROR}/debian-security bookworm-security main contrib non-free non-free-firmware" >> /etc/apt/sources.list && \
apt-get update && \
apt-get install -y --no-install-recommends ffmpeg nginx supervisor procps && \
rm -rf /var/lib/apt/lists/*
ENV PATH="/usr/bin:${PATH}"
ENV HF_ENDPOINT=https://hf-mirror.com
ENV PYTHONUNBUFFERED=1
# 复制 Python 依赖
COPY --from=backend-builder /usr/local/lib/python3.11/site-packages /usr/local/lib/python3.11/site-packages
COPY --from=backend-builder /usr/local/bin /usr/local/bin
# 复制 backend 代码
COPY ./backend /app/backend
WORKDIR /app/backend
# 复制前端静态文件到 nginx
COPY --from=frontend-builder /tmp/frontend/dist /usr/share/nginx/html
# 配置 nginx
RUN rm -rf /etc/nginx/conf.d/default.conf
COPY ./nginx/default.conf /etc/nginx/conf.d/default.conf
# 创建 supervisor 配置
# 关键点supervisord 默认 *不* 把自己的环境变量传给子进程。
# 在 [supervisord] 块用 environment= 设兜底默认值;在 [program:backend] 用
# %(ENV_*)s 显式引用,等价于「把 host 通过 docker run -e 或 env_file 传进来的
# 变量再透传给 python main.py」。漏掉这一步就是用户「改 .env 没反应」的根因。
RUN mkdir -p /var/log/supervisor
COPY <<EOF /etc/supervisor/conf.d/supervisord.conf
[supervisord]
nodaemon=true
user=root
logfile=/var/log/supervisor/supervisord.log
pidfile=/var/run/supervisord.pid
environment=BACKEND_PORT="8483",BACKEND_HOST="0.0.0.0",TRANSCRIBER_TYPE="fast-whisper",WHISPER_MODEL_SIZE="tiny",FFMPEG_BIN_PATH="",HF_ENDPOINT="https://hf-mirror.com",STATIC="/static",OUT_DIR="./static/screenshots",DATA_DIR="data",NOTE_OUTPUT_DIR="note_results",IMAGE_BASE_URL="/static/screenshots",ENV="production",GROQ_TRANSCRIBER_MODEL="whisper-large-v3-turbo"
[program:nginx]
command=nginx -g "daemon off;"
stdout_logfile=/var/log/supervisor/nginx.log
stderr_logfile=/var/log/supervisor/nginx.log
autorestart=true
priority=10
[program:backend]
command=python main.py
directory=/app/backend
stdout_logfile=/var/log/supervisor/backend.log
stderr_logfile=/var/log/supervisor/backend.log
autorestart=true
priority=20
environment=BACKEND_PORT="%(ENV_BACKEND_PORT)s",BACKEND_HOST="%(ENV_BACKEND_HOST)s",TRANSCRIBER_TYPE="%(ENV_TRANSCRIBER_TYPE)s",WHISPER_MODEL_SIZE="%(ENV_WHISPER_MODEL_SIZE)s",FFMPEG_BIN_PATH="%(ENV_FFMPEG_BIN_PATH)s",HF_ENDPOINT="%(ENV_HF_ENDPOINT)s",STATIC="%(ENV_STATIC)s",OUT_DIR="%(ENV_OUT_DIR)s",DATA_DIR="%(ENV_DATA_DIR)s",NOTE_OUTPUT_DIR="%(ENV_NOTE_OUTPUT_DIR)s",IMAGE_BASE_URL="%(ENV_IMAGE_BASE_URL)s",ENV="%(ENV_ENV)s",GROQ_TRANSCRIBER_MODEL="%(ENV_GROQ_TRANSCRIBER_MODEL)s"
EOF
# 修改 nginx 配置以使用本地 backend
RUN sed -i 's/proxy_pass http:\/\/backend:8483/proxy_pass http:\/\/127.0.0.1:8483/g' /etc/nginx/conf.d/default.conf && \
sed -i 's/proxy_pass http:\/\/frontend:80/proxy_pass http:\/\/127.0.0.1:8080/g' /etc/nginx/conf.d/default.conf
# 启动 supervisor
# 推荐启动方式(覆盖默认 env
# docker run -d --name bilinote --env-file .env -p 8080:80 bilinote-aio
# 单个变量覆盖:
# docker run -d -e TRANSCRIBER_TYPE=groq -e WHISPER_MODEL_SIZE=base ...
EXPOSE 80
CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"]