LiteLLM Docker 部署实战:从 docker-compose 快速上手到非 Root 加固镜像构建
本篇技术指南围绕 LiteLLM 仓库的 Docker 部署文档 展开,完整讲解如何用 Docker Compose 在本地一键拉起 LiteLLM Proxy、PostgreSQL 与 Prometheus 三件套,配置 LITELLM_MASTER_KEY 主密钥,以及如何使用加固版(hardened)Compose 文件验证非 Root、只读根文件系统、出口流量受控的部署形态。读完本文,你将能够独立完成 LiteLLM 镜像的构建、运行、验证、下线,并理解 docker/Dockerfile.non_root 多阶段构建与 Prisma 离线迁移的底层机制。
一、前置条件与整体拓扑
文档明确要求的环境依赖只有两项:
- Docker
- Docker Compose
LiteLLM 的默认部署由仓库根目录的 docker-compose.yml 定义,该文件配置使用 Dockerfile.non_root 构建出一个安全、非 Root 的容器运行环境。整个 Compose 栈包含三个服务:
| 服务 | 镜像 / 构建来源 | 端口 | 关键配置 |
|---|---|---|---|
litellm |
本地构建(target: runtime),镜像名 docker.litellm.ai/berriai/litellm:main-stable |
4000:4000 |
DATABASE_URL 指向 db 服务,STORE_MODEL_IN_DB: "True",健康检查 |
db |
postgres:16 |
5432:5432 |
库名 litellm,用户 llmproxy,命名卷 postgres_data 持久化数据 |
prometheus |
prom/prometheus |
9090:9090 |
挂载 prometheus.yml,TSDB 保留 15 天 |
几个值得注意的配置细节(均可在 docker-compose.yml 中核实):
- 健康检查:
litellm服务每 30 秒用 Python 标准库请求http://localhost:4000/health/liveliness,超时 10 秒、失败重试 3 次,并给了 40 秒的启动宽限期(start_period: 40s),这与 Proxy 启动时要执行 Prisma 迁移的耗时相匹配。 - 可选配置文件注入:Compose 文件中保留了被注释的
volumes: ./config.yaml:/app/config.yaml与command: --config=/app/config.yaml两行,取消注释即可让 Proxy 以指定 YAML 配置启动。 - 只读副本(可选):注释中的
DATABASE_URL_READ_REPLICA可将只读查询(find_*、count、group_by、query_raw/_first)路由到独立的 reader 端点(例如 Aurora reader),单库部署保持不设置即可。 STORE_MODEL_IN_DB: "True":允许通过管理 UI 直接往 Proxy 里添加模型。
二、设置 Master Key(LITELLM_MASTER_KEY)
应用要求设置 LITELLM_MASTER_KEY 用于签名和校验令牌,必须在运行应用之前以环境变量形式提供。文档给出的操作步骤是:
- 在项目根目录创建
.env文件; - 写入一行配置:
LITELLM_MASTER_KEY=your-secret-key
- 将
your-secret-key替换为一个强随机生成的密钥。
这个变量为什么如此关键?从源码实现看,Proxy 启动时会在 proxy_server.py 中执行 master_key = get_secret_str("LITELLM_MASTER_KEY") 读取该值;同时它也支持通过配置文件 general_settings.master_key 提供(见 proxy_server.py)。若两者都未设置,源码中会明确警告:
"LITELLM_MASTER_KEY is not set! All requests will be treated as INTERNAL_USER with no admin access. Set LITELLM_MASTER_KEY for production use."
也就是说,缺失主密钥时所有请求都只能以无管理员权限的内部用户身份处理,/key 管理等后台接口将不可用——这正是后文“故障排查”章节中 Master key is not initialized 报错的根源。Compose 文件通过 env_file: - .env 把 .env 内容注入 litellm 容器,因此 .env 必须位于项目根目录(与执行 docker compose 的位置一致)。
三、构建并运行容器
.env 就绪后,执行:
docker compose up -d --build
文档说明该命令会完成三件事:
- 使用
Dockerfile.non_root构建镜像; - 以分离模式(
-d)启动litellm、litellm_db、prometheus三个服务; --build标志确保 Dockerfile 或应用代码有变化时镜像会被重新构建。
从源码结构看,这里的镜像构建相当“重”,Dockerfile.non_root 是一个多阶段构建:
ui-builder阶段(L16-L28):在--platform=$BUILDPLATFORM上编译 Next.js 管理 UI 的静态导出(ui/litellm-dashboard),保证多架构构建下只在构建平台原生编译一次,而不是在每个目标架构下跑 QEMU。builder阶段(L30-L120):基于按摘要(digest)钉死的 Chainguardwolfi-base基础镜像,安装 Python 3.13 与 Rust 工具链,用uv sync --frozen按pyproject.toml/uv.lock安装proxy、proxy-runtime、extra_proxy、semantic-router、saml、bedrock-realtime等依赖组;随后把编译好的 UI 复制到只读路径/var/lib/litellm/ui并打上.litellm_ui_ready标记(L88-L91),再执行prisma generate把 Prisma CLI 与引擎“烘焙”到固定路径/opt/prisma。runtime阶段(L122-L199):只拷入.venv、docker/脚本、schema.prisma、迁移脚本litellm/proxy/prisma_migration.py、enterprise/与litellm-proxy-extras/,不携带构建期源码。运行时以USER 65534(nobody)运行,EXPOSE 4000/tcp,入口为 prod_entrypoint.sh,默认CMD ["--port", "4000"]。
其中与“离线可迁移”相关的关键环境变量(Dockerfile.non_root):
PRISMA_BINARY_CACHE_DIR=/opt/prisma/binaries
PRISMA_CLI_PATH=/opt/prisma/binaries/node_modules/.bin/prisma
PRISMA_CLI_QUERY_ENGINE_TYPE=binary
PRISMA_OFFLINE_MODE=true
源码注释解释了动机:PRISMA_CLI_QUERY_ENGINE_TYPE=binary 让 Prisma CLI 直接使用烘焙好的二进制查询引擎,使得对全新数据库执行 prisma migrate deploy 时无需 npm、无需网络;否则 CLI 会回退到下载,在离线或非可写 uid 场景下失败。
而容器实际启动时,入口链路是 prod_entrypoint.sh(可选经 ddtrace-run 包装后)执行 litellm "$@",litellm Proxy 启动流程内部会先调用 entrypoint.sh 所代表的迁移逻辑——优先用 .venv/bin/python,否则回退 uv run,最后回退 python3 运行 prisma_migration.py 完成数据库迁移,之后才拉起服务。这也解释了为什么健康检查要给 40 秒启动宽限。
四、验证应用运行状态
查看容器状态:
docker compose ps
查看 litellm 容器日志:
docker compose logs -f litellm
配合 docker-compose.yml 中定义的健康检查,你还可以直接在宿主机验证存活探针端点(与容器内 CMD-SHELL 检查同源):
python3 -c "import urllib.request; urllib.request.urlopen('http://localhost:4000/health/liveliness')"
当 litellm 服务对 db 依赖就绪、迁移成功完成后,docker compose ps 中 health 列会由 starting 转为 healthy(depends_on: db 只保证 Postgres 先启动,不保证其可用,数据库侧另有 pg_isready 健康检查兜底)。
五、停止应用
docker compose down
该命令停止并移除 litellm、db、prometheus 容器;postgres_data 与 prometheus_data 两个命名卷不受影响,Postgres 数据在容器重启后依然保留(见 docker-compose.yml 中的卷定义)。
六、加固 / 离线测试(Hardened & Offline Testing)
仓库提供了 docker-compose.hardened.yml,用于在“非 Root、只读根文件系统、受限出口”约束下验证变更是否安全。文档要求的验证方式是同时加载两个 Compose 文件并强制无缓存构建:
docker compose -f docker-compose.yml -f docker-compose.hardened.yml build --no-cache
docker compose -f docker-compose.yml -f docker-compose.hardened.yml up -d
文档总结了这套加固栈的约束内容,逐项对照 docker-compose.hardened.yml 源码可以确认:
- 构建来源:从 docker/Dockerfile.non_root 构建,Prisma 引擎与 Node 工具链已烘焙进镜像(
PROXY_EXTRAS_SOURCE: "local"表示从仓库本地源安装litellm-proxy-extras而非已发布包)。 - 非 Root + 只读根文件系统:
user: "101:101"、read_only: true、cap_drop: [ALL]、security_opt: no-new-privileges:true(L13-L20),仅有的两个可写 tmpfs 挂载为:/app/cache(128m,noexec,nosuid,nodev)——支撑 Prisma/NPM 缓存,对应PRISMA_BINARY_CACHE_DIR、NPM_CONFIG_CACHE、XDG_CACHE_HOME;/app/migrations(64m)——Prisma 迁移工作区,对应LITELLM_MIGRATION_DIR。
- 只读路径上预构建的管理 UI:
/var/lib/litellm/ui(预整理后的 Next.js UI,带.litellm_ui_ready标记);/var/lib/litellm/assets(UI Logo 与静态资源)。
- 出口流量受控:所有出站流量经本地 Squid 代理(
HTTP_PROXY/HTTPS_PROXY指向http://squid:3128,NO_PROXY: "localhost,127.0.0.1,db")且 Squid 拒绝出口,因此 Prisma 迁移只能使用已缓存的 CLI 与引擎——这与Dockerfile.non_root中PRISMA_OFFLINE_MODE=true的设计互为印证。
此外,文档要求用以下命令验证离线 Prisma 行为:
docker run --rm --network none --entrypoint prisma ghcr.io/berriai/litellm:main-stable --version
该命令在 --network none(完全无网络)下应成功打印引擎版本,从而证明 Prisma 二进制在离线环境下可用。镜像内非 Root 行为还有对应的 nonroot.yaml 测试清单,断言入口点为 docker/prod_entrypoint.sh、运行用户为 65534、工作目录为 /app,并校验 Prisma 包路径的存在性与属主。
七、相关镜像构建方式补充
docker/ 目录还提供了几条可选构建路径,可按需参考:
- 默认开发镜像:仓库根 Dockerfile 与
Dockerfile.non_root结构一致(同样多阶段、digest 钉死基础镜像),作为常规构建入口。 docker/Dockerfile.database:在运行时额外执行 build_admin_ui.sh(L80)。该脚本仅在检测到enterprise/enterprise_ui/enterprise_colors.json存在时才构建企业定制 UI(通过 nvm 安装.nvmrc指定 Node 版本后执行./build_ui.sh),普通开源构建会直接跳过。- 从 PyPI 包构建:docker/build_from_pip/Readme.md 说明,若公司对镜像构建有严格安全要求(不允许从源码树安装依赖),可参考 Dockerfile.build_from_pip 从
litellmpip 包构建 Proxy。
八、故障排查
原文档给出的两个高频问题,结合源码可进一步定位:
build_admin_ui.sh: not foundDocker 构建上下文(build context)设置不正确时会出现此错误。请确认docker compose命令是在项目根目录执行的——docker-compose.yml中build.context: .指向根目录,而 build_admin_ui.sh 的路径是相对于根目录的docker/子目录,构建上下文一旦偏移,COPY与脚本调用都会失配。Master key is not initialized表示LITELLM_MASTER_KEY环境变量未生效。确认已按第二节操作,在项目根目录创建了含LITELLM_MASTER_KEY的.env文件,且 Compose 的env_file: - .env能正确加载它;修改后需要重新docker compose up -d(或--build)使新环境进入容器。
排查时可直接观察迁移与启动日志:
docker compose logs -f litellm
正常启动序列应为:Prisma 迁移脚本执行成功(见 entrypoint.sh 打印的 Migration script ran successfully!)→ LiteLLM Proxy 在 4000 端口就绪 → 健康检查转绿。
小结
本文完整覆盖了 docker/README.md 的实操脉络——设置 LITELLM_MASTER_KEY、docker compose up -d --build 三服务一键部署、ps/logs 验证、down 下线,以及 hardened 栈下的非 Root、只读 rootfs、Squid 拒绝出口的离线验证——并深入 docker/Dockerfile.non_root、docker-compose.yml、docker-compose.hardened.yml 与 proxy_server.py 等源码,解释了非 Root 用户(UID 65534/101)、tmpfs 可写挂载划分、UI 只读预构建标记与 Prisma 引擎烘焙(/opt/prisma + PRISMA_CLI_QUERY_ENGINE_TYPE=binary)之间的配合关系。这套组合保证了 LiteLLM Proxy 既能以最低成本在本地快速跑起来,也能在安全合规(离线、只读、最小权限)的生产环境中验证通过。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00