Dify 本地部署实战:Plugin Daemon 401/500 错误深度排查与解决

摘要:本文以"问题驱动"的方式,详细记录 Dify(开源 LLM 应用开发平台)本地 Docker 部署过程中遇到的 Plugin Daemon 401 认证错误和 API 500 内部错误的完整排查过程。从现象观察、日志分析、源码追踪到最终修复,形成一套系统化的问题诊断方法论。


一、背景介绍

1.1 Dify 平台简介

Dify 是一个开源的 LLM(Large Language Model)应用开发平台,支持快速构建 AI 应用、工作流和知识库。它提供了可视化的界面,让用户无需编写代码即可创建智能应用。

核心功能

  • 🤖 AI 应用开发:创建聊天助手、Agent、工作流等应用
  • 📚 知识库管理:支持文档上传、向量化检索
  • 🔌 插件系统:通过 Plugin Daemon 扩展能力
  • 🔗 API 集成:提供完整的 REST API 接口

1.2 部署架构

Dify 采用微服务架构,包含以下核心组件:

服务 端口 说明
Web 前端 3000 React 应用,用户交互界面
API 服务 5001 Flask 后端,业务逻辑处理
Plugin Daemon 5002 插件管理服务,扩展能力
PostgreSQL 5432 关系型数据库
Redis 6379 缓存服务
Weaviate 8080 向量数据库
Sandbox 8194 代码执行沙箱

二、环境准备与基础部署

2.1 系统要求

  • 操作系统:Windows 10/11、macOS、Linux
  • Docker:Docker Desktop 20.10+
  • 内存:建议 8GB 以上
  • 磁盘:建议 20GB 以上可用空间

2.2 安装 Docker Desktop

  1. 访问 Docker 官网 下载
  2. 安装并启动 Docker Desktop
  3. 验证安装:
docker --version
docker compose version

2.3 创建项目目录

# 创建项目目录
mkdir difytest
cd difytest

2.4 编写 docker-compose.yml

创建 docker-compose.yml 文件(完整版见文末附录 A)。

2.5 启动服务

# 启动所有服务(后台运行)
docker compose up -d

# 查看容器状态
docker compose ps

预期输出

NAME            IMAGE                          STATUS
dify-api        langgenius/dify-api:latest     Up
dify-web        langgenius/dify-web:latest     Up
dify-db         postgres:15-alpine             Up
dify-redis      redis:7-alpine                 Up
dify-weaviate   semitechnologies/weaviate:1.25 Up
dify-plugin     langgenius/dify-plugin-daemon  Up
dify-sandbox    langgenius/dify-sandbox:0.2.12 Up

2.6 数据库迁移与初始化

执行数据库迁移
# 进入 API 容器执行迁移
docker exec dify-api flask db upgrade
初始化管理员账户

访问浏览器:

http://localhost:3000/install

三、问题发现:401/500 错误连环出现

3.1 错误现象

完成基础部署后,访问 http://localhost:3000 时出现两个关联错误:

错误 1:弹出框显示 401 Unauthorized

![401错误截图]

Client error '401 Unauthorized' for url 
'http://plugin_daemon:5002/plugin/3a70a6ad-ece7-42fd-9307-f3a6896f6a97/management/install/tasks'

关键信息

  • 错误类型:401 Unauthorized(未授权)
  • 目标地址:http://plugin_daemon:5002(Plugin Daemon 服务)
  • 请求路径:/plugin/.../management/install/tasks(插件管理任务)
错误 2:浏览器控制台显示 500 Internal Server Error

![500错误截图]

GET http://localhost:5001/console/api/workspaces/current/model-providers 500 (Internal Server Error)
GET http://localhost:5001/console/api/workspaces/current/models/model-types/text-generation 500

关键信息

  • 错误类型:500 Internal Server Error(服务器内部错误)
  • 目标地址:http://localhost:5001(API 服务)
  • 请求路径:/console/api/workspaces/current/model-providers(模型供应商列表)

3.2 初步分析

根据端口号判断:

  • 5001 端口:API 容器(Flask 后端)
  • 5002 端口:Plugin Daemon 容器(插件管理服务)

推断:500 错误是表象,401 错误才是根源。API 在调用 Plugin Daemon 时认证失败,导致无法获取模型数据,进而向前端返回 500 错误。


四、根本问题分析

4.1 错误链路还原

通过分析错误信息和端口对应关系,可以还原完整的错误链路:

┌─────────────────┐
│ 浏览器前端 :3000 │
└────────┬────────┘
         │ ① 请求模型供应商列表
         ▼
┌─────────────────┐
│  API 容器 :5001  │
└────────┬────────┘
         │ ② 尝试调用 Plugin Daemon 获取模型数据
         ▼
┌──────────────────────┐
│ Plugin Daemon :5002  │
└────────┬─────────────┘
         │ ③ 认证失败(401 Unauthorized)
         ▼
┌─────────────────┐
│  API 容器 :5001  │
└────────┬────────┘
         │ ④ 捕获异常,返回 500 Internal Server Error
         ▼
┌─────────────────┐
│ 浏览器前端 :3000 │
└─────────────────┘
         │ ⑤ 显示 500 错误

结论:401 是根本原因,500 是连锁反应。

4.2 日志验证

查看 API 容器日志
docker logs dify-api --tail 100

关键日志

ERROR: Client error '401 Unauthorized' for url 
'http://plugin_daemon:5002/plugin/3a70a6ad-ece7-42fd-9307-f3a6896f6a97/management/models'

✅ 确认 API 调用 Plugin Daemon 时返回 401

查看 Plugin Daemon 容器日志
docker logs dify-plugin --tail 50

关键日志

WARN ... status=401 latency_ms=0 client_ip=172.19.0.7
WARN ... status=401 latency_ms=0 client_ip=172.19.0.7
WARN ... status=401 latency_ms=0 client_ip=172.19.0.7

✅ 确认 Plugin Daemon 持续收到未授权的请求

4.3 认证机制解析

Dify 的 API 和 Plugin Daemon 之间采用双向认证机制:

认证方向 发送方环境变量 接收方环境变量 HTTP Header 说明
API → Plugin Daemon PLUGIN_DAEMON_KEY SERVER_KEY X-Api-Key API 向 Plugin Daemon 发起请求时的认证密钥
Plugin Daemon → API DIFY_INNER_API_KEY INNER_API_KEY_FOR_PLUGIN X-Api-Key Plugin Daemon 向 API 发起请求时的认证密钥

认证流程

  1. API 向 Plugin Daemon 发送请求时,在 HTTP Header 中添加 X-Api-Key: <PLUGIN_DAEMON_KEY的值>
  2. Plugin Daemon 收到请求后,用 SERVER_KEY 验证 X-Api-Key 是否匹配
  3. 如果匹配,则允许访问;否则返回 401 Unauthorized

4.4 环境变量检查

检查 API 容器环境变量
docker exec dify-api env | findstr "PLUGIN"

实际输出

PLUGIN_DAEMON_URL=http://plugin_daemon:5002
INNER_API_KEY_FOR_PLUGIN=123456
PLUGIN_REMOTE_INSTALLING_ENABLED=false

⚠️ 发现问题:缺少 PLUGIN_DAEMON_KEY 环境变量!

检查 Plugin Daemon 容器环境变量
docker exec dify-plugin env | findstr "KEY"

实际输出

SERVER_KEY=123456
DIFY_INNER_API_KEY=123456

✅ Plugin Daemon 配置正确,期望的密钥是 123456

4.5 源码追踪

为了确认 API 如何使用 PLUGIN_DAEMON_KEY,我们从容器中复制源码进行分析:

# 复制 base.py 到本地
docker cp dify-api:/app/api/core/plugin/impl/base.py d:/aiwork/difytest/temp_base.py

查看 /app/api/core/plugin/impl/base.py 第108行:

def _prepare_request_headers(
    self,
    tenant_id: str,
    method: str = "GET",
    path: str = "",
) -> dict[str, str]:
    prepared_headers: dict[str, str] = {
        "Content-Type": "application/json",
        "X-Tenant-Id": tenant_id,
    }
    if method in ["POST", "PUT", "PATCH"]:
        prepared_headers["X-Request-Id"] = str(uuid4())
    prepared_headers["X-Api-Key"] = dify_config.PLUGIN_DAEMON_KEY  # ← 第108行
    return prepared_headers

结论:API 确实使用 dify_config.PLUGIN_DAEMON_KEY 作为认证密钥。

继续查看配置文件定义:

# 复制 configs 目录到本地
docker cp dify-api:/app/api/configs d:/aiwork/difytest/configs_dir

查看 configs/feature/__init__.py 第231-234行:

PLUGIN_DAEMON_KEY: str = Field(
    description="Plugin API key",
    default="plugin-api-key",  # ← 默认值
)

根本原因确认

  • API 容器未设置 PLUGIN_DAEMON_KEY 环境变量
  • 因此使用默认值 "plugin-api-key"
  • Plugin Daemon 期望的密钥是 SERVER_KEY=123456
  • 密钥不匹配导致 401 认证失败

五、解决思路设计

5.1 方案设计

基于根本原因分析,我们设计了以下解决方案:

方案 A:修改 docker-compose.yml + 重新创建容器(推荐)

步骤

  1. docker-compose.yml 中为 API 容器添加 PLUGIN_DAEMON_KEY=123456
  2. 停止所有容器:docker compose down
  3. 重新创建所有容器:docker compose up -d
  4. 验证环境变量是否生效
  5. 验证 Plugin Daemon 日志无 401 错误

优点

  • ✅ 符合 Docker 最佳实践
  • ✅ 配置可追溯、可复现
  • ✅ 便于后续维护和团队协作

缺点

  • ⚠️ 需要重启所有容器(约 1-2 分钟)
方案 B:直接修改容器内配置文件(临时方案)

步骤

  1. 进入 API 容器:docker exec -it dify-api bash
  2. 修改 Python 配置文件,将默认值改为 123456
  3. 重启 API 容器:docker restart dify-api

优点

  • ✅ 快速验证,无需等待容器重建

缺点

  • ❌ 不符合容器化最佳实践
  • ❌ 容器重建后修改会丢失
  • ❌ 难以追踪和复现
方案 C:禁用 Plugin Daemon(规避方案)

步骤

  1. 设置 PLUGIN_DAEMON_ENABLED=false
  2. 重启 API 容器

优点

  • ✅ 立竿见影,彻底避免认证问题

缺点

  • ❌ 失去插件扩展能力
  • ❌ 部分功能不可用

5.2 方案选择

最终选择:方案 A

理由:

  1. 符合生产环境的配置管理规范
  2. 保留 Plugin Daemon 的完整功能
  3. 配置变更可追溯、可回滚

六、解决过程实施

6.1 修改 docker-compose.yml

在 API 服务的环境变量中显式添加 PLUGIN_DAEMON_KEY

# docker-compose.yml 第33-38行
services:
  api:
    environment:
      # Plugin Daemon 配置(测试环境 - 使用简单数字密钥)
      - PLUGIN_DAEMON_ENABLED=true
      - PLUGIN_DAEMON_URL=http://plugin_daemon:5002
      - PLUGIN_DAEMON_KEY=123456              ← 添加此行
      - INNER_API_KEY_FOR_PLUGIN=123456
      - PLUGIN_REMOTE_INSTALLING_ENABLED=false

6.2 重新创建容器(关键步骤)

⚠️ 重要提示:修改环境变量后,必须使用 docker compose down + docker compose up -d 重新创建容器,docker restart 不会重新加载环境变量!

原因:Docker 容器的环境变量在容器创建时注入,docker restart 只是重启进程,不会重新读取 docker-compose.yml 中的配置。

# 停止所有容器并删除网络
docker compose down

# 重新创建所有容器
docker compose up -d

输出示例

[+] Running 7/7
 ✔ Container dify-db         Started
 ✔ Container dify-redis      Started
 ✔ Container dify-weaviate   Started
 ✔ Container dify-plugin     Started
 ✔ Container dify-sandbox    Started
 ✔ Container dify-api        Started
 ✔ Container dify-web        Started

6.3 验证环境变量生效

等待 15 秒让服务完全启动后,验证环境变量:

# 检查 API 容器环境变量
docker exec dify-api env | findstr "PLUGIN_DAEMON_KEY"

预期输出

PLUGIN_DAEMON_KEY=123456

✅ 如果看到输出,说明环境变量已成功注入。

6.4 验证 Plugin Daemon 日志

docker logs dify-plugin --tail 50

预期:不再有大量 WARN ... status=401 ... 日志

实际输出

INFO  Server started on port 5002
INFO  Ready to accept connections

✅ 确认 Plugin Daemon 正常启动,无认证错误。

6.5 验证 API 健康状态

curl http://localhost:5001/console/api/ping

预期输出

{"result":"pong"}

✅ API 服务正常运行。

6.6 全面验证密钥配置

API 容器密钥配置
docker exec dify-api env | findstr "KEY\|PASSWORD\|SECRET"

输出

SECRET_KEY=dify-secret-key-change-in-production
WEAVIATE_API_KEY=WVF5YThaHlkYwhGUSmCRgsX3tD5ngdN8pkih
INNER_API_KEY_FOR_PLUGIN=123456
PLUGIN_DAEMON_KEY=123456              ← 已生效
DB_PASSWORD=dify-db-password
Plugin Daemon 容器密钥配置
docker exec dify-plugin env | findstr "KEY"

输出

SERVER_KEY=123456                     ← 已生效
DIFY_INNER_API_KEY=123456             ← 已生效
密钥对齐验证
认证方向 发送方密钥 接收方密钥 状态
API → Plugin Daemon PLUGIN_DAEMON_KEY=123456 SERVER_KEY=123456 ✅ 匹配
Plugin Daemon → API DIFY_INNER_API_KEY=123456 INNER_API_KEY_FOR_PLUGIN=123456 ✅ 匹配

✅ 双向认证密钥完全对齐。

6.7 浏览器验证

打开浏览器访问:

http://localhost:3000

验证项

  • ✅ 页面正常加载,无 500 错误
  • ✅ 无 “401 Unauthorized” 弹出框
  • ✅ 可以创建应用
  • ✅ 可以配置模型供应商

F12 打开开发者工具:

  • Console 标签:无红色错误信息
  • Network 标签:所有请求状态码为 200 或 304

✅ 问题完全解决!


七、配置参数详解

7.1 Plugin Daemon 双向认证密钥配置

参数名 容器 默认值 当前值 说明
PLUGIN_DAEMON_KEY API plugin-api-key 123456 API 向 Plugin Daemon 认证的密钥
INNER_API_KEY_FOR_PLUGIN API inner-api-key 123456 API 验证 Plugin Daemon 请求的密钥
SERVER_KEY Plugin Daemon - 123456 Plugin Daemon 验证 API 请求的密钥
DIFY_INNER_API_KEY Plugin Daemon - 123456 Plugin Daemon 向 API 认证的密钥

测试环境统一配置

# API 容器
- PLUGIN_DAEMON_KEY=123456
- INNER_API_KEY_FOR_PLUGIN=123456

# Plugin Daemon 容器
- SERVER_KEY=123456
- DIFY_INNER_API_KEY=123456

生产环境建议

  • 使用强随机字符串(至少 32 位)
  • 四个密钥可以不同,增强安全性
  • 通过环境变量或密钥管理服务注入,不要硬编码

7.2 其他重要配置

API 服务配置
- MODE=api                           # 运行模式
- SECRET_KEY=dify-secret-key-change-in-production  # Flask 会话密钥(生产环境必须修改)
- LOG_LEVEL=INFO                     # 日志级别(DEBUG/INFO/WARNING/ERROR)
- VECTOR_STORE=weaviate              # 向量数据库类型
- STORAGE_TYPE=local                 # 存储类型(local/s3/azure-blob/oci-storage)
数据库配置
- DB_HOST=db
- DB_PORT=5432
- DB_USERNAME=postgres
- DB_PASSWORD=dify-db-password       # 生产环境必须修改
- DB_DATABASE=dify
CORS 配置
- CORS_ALLOW_ORIGINS=http://localhost:3000
- WEB_API_CORS_ALLOW_ORIGINS=http://localhost:3000

八、常见问题排查

8.1 数据库表缺失

现象:访问页面时出现 500 错误,日志显示:

relation "dify_setups" does not exist

解决

# 执行数据库迁移
docker exec dify-api flask db upgrade

# 重启 API 容器
docker restart dify-api

8.2 环境变量不生效

现象:修改了 docker-compose.yml,但容器内环境变量未更新

原因docker restart 不会重新加载环境变量

解决

# 必须重新创建容器
docker compose down
docker compose up -d

8.3 容器启动失败

排查步骤

# 1. 查看容器状态
docker compose ps

# 2. 查看容器日志
docker logs dify-api --tail 100
docker logs dify-plugin --tail 100

# 3. 检查端口占用
netstat -ano | findstr "5001"
netstat -ano | findstr "5002"

# 4. 检查 Docker 网络
docker network ls
docker network inspect difytest_dify-network

8.4 认证错误排查命令

# 检查 API 容器环境变量
docker exec dify-api env | findstr "PLUGIN"

# 检查 Plugin Daemon 环境变量
docker exec dify-plugin env | findstr "KEY"

# 查看 Plugin Daemon 认证日志
docker logs dify-plugin --tail 50 | findstr "401\|status="

# 查看 API 错误日志
docker logs dify-api --tail 100 | findstr "ERROR\|500"

九、总结与经验教训

9.1 问题解决回顾

本次排查过程遵循了系统化的问题诊断方法论:

  1. 现象观察:识别 401 和 500 两个关联错误
  2. 日志分析:通过 docker logs 定位认证失败的源头
  3. 源码追踪:从容器复制源码,理解认证机制的实现细节
  4. 根因定位:发现 PLUGIN_DAEMON_KEY 环境变量缺失
  5. 方案设计:对比三种方案,选择符合最佳实践的解决方案
  6. 实施验证:修改配置、重建容器、逐项验证

9.2 关键技术要点

  • 🔑 Plugin Daemon 认证是双向的:需要配置四个环境变量,确保发送方和接收方的密钥匹配
  • ⚠️ 环境变量注入时机:Docker 容器创建时注入环境变量,docker restart 无效,必须重新创建容器
  • 🔍 500 错误通常是连锁反应:需要向下追溯,找到底层服务的原始错误(本例中是 401)
  • 📊 日志是排查问题的关键:熟练使用 docker logsdocker exec 等命令
  • 🧪 源码分析能力:当配置和日志不足以定位问题时,需要深入源码理解实现机制

9.3 经验教训

  1. 配置管理规范化:所有密钥都应通过 docker-compose.yml 或环境变量文件管理,避免硬编码
  2. 测试环境与生产环境隔离:测试环境可以使用简单密钥(如 123456),生产环境必须使用强随机字符串
  3. 文档化排障过程:记录每次问题的现象、分析过程和解决方案,形成团队知识库
  4. 监控与告警:生产环境应配置日志监控和告警,及时发现认证失败等异常情况

9.4 后续优化建议

  1. 密钥轮换机制:定期更换认证密钥,提高安全性
  2. 自动化测试:编写自动化脚本,验证所有服务的健康状态和认证配置
  3. 配置模板化:为不同环境(开发/测试/生产)提供不同的 docker-compose 模板
  4. 监控面板:搭建 Grafana + Prometheus 监控面板,实时查看服务状态

十、附录

10.1 完整 docker-compose.yml

version: '3.8'

services:
  # API 服务
  api:
    image: langgenius/dify-api:latest
    container_name: dify-api
    restart: always
    user: root
    environment:
      - MODE=api
      - LOG_LEVEL=INFO
      - SECRET_KEY=dify-secret-key-change-in-production
      - DB_USERNAME=postgres
      - DB_PASSWORD=dify-db-password
      - DB_HOST=db
      - DB_PORT=5432
      - DB_DATABASE=dify
      - REDIS_HOST=redis
      - REDIS_PORT=6379
      - REDIS_DB=0
      - STORAGE_TYPE=local
      - STORAGE_LOCAL_PATH=/app/storage
      - VECTOR_STORE=weaviate
      - WEAVIATE_ENDPOINT=http://weaviate:8080
      - WEAVIATE_API_KEY=WVF5YThaHlkYwhGUSmCRgsX3tD5ngdN8pkih
      - CONSOLE_API_URL=http://localhost:5001
      - CONSOLE_WEB_URL=http://localhost:3000
      - APP_API_URL=http://localhost:5001
      - APP_WEB_URL=http://localhost:3000
      - CORS_ALLOW_ORIGINS=http://localhost:3000
      - WEB_API_CORS_ALLOW_ORIGINS=http://localhost:3000
      # Plugin Daemon 配置
      - PLUGIN_DAEMON_ENABLED=true
      - PLUGIN_DAEMON_URL=http://plugin_daemon:5002
      - PLUGIN_DAEMON_KEY=123456
      - INNER_API_KEY_FOR_PLUGIN=123456
      - PLUGIN_REMOTE_INSTALLING_ENABLED=false
    ports:
      - "5001:5001"
    volumes:
      - dify_storage:/app/storage
    depends_on:
      - db
      - redis
      - weaviate
      - plugin_daemon
    networks:
      - dify-network

  # Web 前端
  web:
    image: langgenius/dify-web:latest
    container_name: dify-web
    restart: always
    environment:
      - CONSOLE_API_URL=http://localhost:5001
      - APP_API_URL=http://localhost:5001
    ports:
      - "3000:3000"
    depends_on:
      - api
    networks:
      - dify-network

  # PostgreSQL 数据库
  db:
    image: postgres:15-alpine
    container_name: dify-db
    restart: always
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=dify-db-password
      - POSTGRES_DB=dify
    volumes:
      - dify_db_data:/var/lib/postgresql/data
    ports:
      - "5432:5432"
    networks:
      - dify-network

  # Redis 缓存
  redis:
    image: redis:7-alpine
    container_name: dify-redis
    restart: always
    volumes:
      - dify_redis_data:/data
    ports:
      - "6379:6379"
    networks:
      - dify-network

  # Weaviate 向量数据库
  weaviate:
    image: semitechnologies/weaviate:1.25.0
    container_name: dify-weaviate
    restart: always
    environment:
      - QUERY_DEFAULTS_LIMIT=25
      - AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED=false
      - PERSISTENCE_DATA_PATH=/var/lib/weaviate
      - DEFAULT_VECTORIZER_MODULE=text2vec-openai
      - ENABLE_MODULES=text2vec-openai
      - CLUSTER_HOSTNAME=node1
    volumes:
      - dify_weaviate_data:/var/lib/weaviate
    ports:
      - "8080:8080"
    networks:
      - dify-network

  # Plugin Daemon
  plugin_daemon:
    image: langgenius/dify-plugin-daemon:0.6.0-local
    container_name: dify-plugin
    restart: always
    environment:
      - DB_HOST=db
      - DB_PORT=5432
      - DB_USERNAME=postgres
      - DB_PASSWORD=dify-db-password
      - DB_DATABASE=dify
      - REDIS_HOST=redis
      - REDIS_PORT=6379
      - REDIS_PASSWORD=
      - SERVER_PORT=5002
      - SERVER_KEY=123456
      - DIFY_INNER_API_URL=http://api:5001
      - DIFY_INNER_API_KEY=123456
      - PLUGIN_REMOTE_INSTALLING_HOST=0.0.0.0
      - PLUGIN_REMOTE_INSTALLING_PORT=5003
      - PLUGIN_WORKING_PATH=/app/storage/cwd
      - PLUGIN_STORAGE_TYPE=local
      - PLUGIN_STORAGE_LOCAL_ROOT=/app/storage
    ports:
      - "5002:5002"
      - "5003:5003"
    depends_on:
      - db
      - redis
    networks:
      - dify-network

  # Sandbox 代码执行沙箱
  sandbox:
    image: langgenius/dify-sandbox:0.2.12
    container_name: dify-sandbox
    restart: always
    environment:
      - API_KEY=dify-sandbox
      - GIN_MODE=release
    ports:
      - "8194:8194"
    networks:
      - dify-network

volumes:
  dify_storage:
  dify_db_data:
  dify_redis_data:
  dify_weaviate_data:

networks:
  dify-network:
    driver: bridge

10.2 常用命令速查

# 启动所有服务
docker compose up -d

# 停止所有服务
docker compose down

# 查看容器状态
docker compose ps

# 查看容器日志
docker logs dify-api --tail 100
docker logs dify-plugin --tail 50

# 进入容器
docker exec -it dify-api bash

# 检查环境变量
docker exec dify-api env | findstr "PLUGIN"
docker exec dify-plugin env | findstr "KEY"

# 执行数据库迁移
docker exec dify-api flask db upgrade

# 健康检查
curl http://localhost:5001/console/api/ping

参考资料

  • Dify 官方文档:https://docs.dify.ai/
  • Dify GitHub:https://github.com/langgenius/dify
  • Docker 官方文档:https://docs.docker.com/
  • Alembic 文档:https://alembic.sqlalchemy.org/

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐