Docker 构建流程与多阶段镜像
Docker 构建过程与多阶段镜像
相关源文件
本章引用的主要源码文件:
.github/labeler.yml.github/workflows/api-tests.yml.github/workflows/autofix.yml.github/workflows/build-push.yml.github/workflows/db-migration-test.yml.github/workflows/docker-build.yml.github/workflows/main-ci.yml.github/workflows/pyrefly-diff-comment.yml.github/workflows/pyrefly-diff.yml.github/workflows/style.yml.github/workflows/tool-test-sdks.yaml.github/workflows/translate-i18n-claude.yml.github/workflows/trigger-i18n-sync.yml.github/workflows/vdb-tests-full.yml.github/workflows/vdb-tests.yml.github/workflows/web-tests.ymlapi/Dockerfiledepot.jsonweb/.env.exampleweb/Dockerfileweb/app/layout.tsxweb/config/index.tsweb/docker/entrypoint.shweb/types/feature.ts
目的与范围
本文档描述了 Dify 平台中 API 和 Web 服务的 Docker 镜像构建过程。内容涵盖多阶段 Dockerfile 架构、构建优化策略、依赖安装以及镜像创建流程。有关运行时容器配置和 MODE 环境变量的信息,请参见环境配置与运行时模式。有关部署编排的详细信息,请参见服务拓扑与 Docker Compose 堆栈。
多阶段构建架构
API 和 Web 服务均采用多阶段 Docker 构建,以在保持构建时依赖与运行时依赖清晰分离的同时,最小化最终镜像体积。
API 多阶段构建流程
API 镜像构建遵循 api/Dockerfile 中定义的三个不同阶段。
阶段 1:基础镜像 - 使用 Python 3.12-slim 和 uv 包管理器建立基础环境 api/Dockerfile:2-10。全局安装 uv(版本 0.8.9)以实现快速依赖解析 api/Dockerfile:7-9。
阶段 2:依赖包 - 专门用于依赖编译。安装构建所需工具如 g++ 和数学库(libmpfr-dev、libmpc-dev),这些库是 gmpy2 等包所必需的 api/Dockerfile:17-22。命令 uv sync --frozen --no-dev 将生产依赖安装到 /app/api/.venv 的虚拟环境中,包括 providers/ 下的工作区成员 api/Dockerfile:25-28。
阶段 3:生产环境 - 最终运行时镜像。仅从 packages 阶段复制编译好的 Python 虚拟环境 api/Dockerfile:95-97。关键组件包括:
- Node.js 22:安装以支持 API 内的代码执行需求
api/Dockerfile:55-81。 - 系统工具:
fonts-noto-cjk用于 PDF 工具,media-types用于 MIME 类型猜测,libmagic1用于文件类型检测api/Dockerfile:86-91。 - NLTK 数据:预下载到
/usr/local/share/nltk_dataapi/Dockerfile:101-103。 - 非 root 用户:
dify用户(UID 1001)用于安全加固api/Dockerfile:54-60。
来源: api/Dockerfile:1-123
Web 多阶段构建流程
Web 镜像构建使用 node:22-alpine 基础镜像,并采用四阶段流程以优化 Next.js 独立输出。
来源: web/Dockerfile:1-89
依赖管理与层优化
UV 包管理器(API)
API Dockerfile 使用 uv 实现高性能依赖解析 api/Dockerfile:7-9。构建过程利用 uv.lock 和 --frozen 标志,通过信任已检入的锁定文件来确保可重现的环境 api/Dockerfile:25-28。
PNPM 和 Corepack(Web)
Web 服务使用 pnpm 进行包管理,通过 corepack 启用 web/Dockerfile:12-13。它安装工作区依赖,包括 packages/ 目录中的依赖 web/Dockerfile:28-34。
层缓存策略
构建过程旨在最大化 Docker 层缓存。依赖清单文件(API 的 pyproject.toml、uv.lock;Web 的 package.json、pnpm-lock.yaml)在完整应用程序源代码之前被复制 api/Dockerfile:25-26、web/Dockerfile:24-27。这确保了耗时的依赖安装层仅在锁定文件发生变化时才失效。
来源: api/Dockerfile:7-28、web/Dockerfile:12-34
运行时优化:预热缓存
NLTK 数据预下载
API 镜像在构建期间下载 NLTK 数据集,以避免文档处理时的运行时延迟和连接问题:
RUN mkdir -p /usr/local/share/nltk_data \
&& NLTK_DATA=/usr/local/share/nltk_data python -c "import nltk; nltk.download('punkt'); nltk.download('averaged_perceptron_tagger'); nltk.download('stopwords')"
来源: api/Dockerfile:101-103
Tiktoken 编码缓存
API 镜像为 gpt2 模型预热 tiktoken 缓存,以消除 Token 计数任务中的首次使用延迟 api/Dockerfile:105-108。
安全加固:非 root 用户执行
API 和 Web 镜像均设计为以非 root 用户 dify(UID 1001)运行,以遵循最小权限原则。
| 特性 | API 实现 api/Dockerfile:54-60 | Web 实现 web/Dockerfile:68-72 |
|---|---|---|
| 用户创建 | groupadd -r -g 1001 dify && useradd -r -u 1001 -g 1001 | addgroup -S -g 1001 dify && adduser -S -u 1001 -G dify |
| 所有权 | chown -R dify:dify /app | chown -R dify:dify /app |
| Shell | /bin/bash | /bin/ash |
| 执行 | USER dify | USER dify |
来源: api/Dockerfile:54-121、web/Dockerfile:68-87
环境变量映射
构建过程注入默认环境变量,这些变量定义了应用程序的生产行为。
| 变量 | API 默认值 api/Dockerfile:33-39 | Web 默认值 web/Dockerfile:51-60 |
|---|---|---|
EDITION | SELF_HOSTED | SELF_HOSTED |
DEPLOY_ENV | PRODUCTION | PRODUCTION |
CONSOLE_API_URL | http://127.0.0.1:5001 | http://127.0.0.1:5001 |
APP_WEB_URL | http://127.0.0.1:3000 | 不适用 |
NODE_ENV | 不适用 | production |
这些默认值通常会在运行时通过 .env 文件或 Docker Compose 配置被覆盖 web/.env.example:1-10。
来源: api/Dockerfile:33-39、web/Dockerfile:51-60、web/.env.example:1-10
服务入口点
两个服务均使用入口点脚本来管理启动逻辑和环境变量注入。
API 入口点(/entrypoint.sh)
API 镜像入口点 api/Dockerfile:123 根据 MODE 环境变量(例如 api、worker、beat)促进不同服务的执行。它负责在启动 Python 应用程序之前初始化环境。
Web 入口点(./entrypoint.sh)
Web 镜像入口点 web/Dockerfile:89 处理 Next.js 独立服务器的启动。它还执行运行时环境变量注入,用于需要提供给客户端的变量,例如 TEXT_GENERATION_TIMEOUT_MS web/.env.example:42-43。
来源: api/Dockerfile:114-123、web/Dockerfile:82-89、web/.env.example:42-43