3.Dockerfile如何构建一个Python算法镜像

Dockerfile 如何构建一个 Python 算法镜像?

码海寻道 · AI 算法工程化与系统落地实战第 3 篇

上一篇已经把算法封装成 FastAPI 服务,但它仍然依赖当前机器的 Python、系统库、模型路径和启动命令。Dockerfile 的作用,就是把这些运行条件固化成一个可以重复构建的镜像。

本文以一个 FastAPI 算法服务为例,说明 Dockerfile 怎么写、镜像怎么构建、模型文件放在哪里,以及为什么"能构建成功"还不等于"可以上线"。

一、先理解镜像和容器

text 复制代码
Dockerfile:构建镜像的说明书
镜像:应用代码、运行时和依赖的只读模板
容器:镜像启动后的运行实例

镜像应该尽量包含稳定的运行环境和应用代码;数据库、上传文件、日志和可变业务数据不应该依赖容器可写层。容器被删除后,业务数据仍然要能从 Volume、对象存储或外部数据库恢复。

二、准备项目目录

text 复制代码
algorithm-api/
├── app/
│   ├── main.py
│   ├── config.py
│   └── inference.py
├── requirements.txt
├── Dockerfile
└── .dockerignore

依赖文件示例:

text 复制代码
fastapi
uvicorn[standard]
pydantic-settings

如果模型运行时需要 onnxruntime、opencv-python-headless 或 PyTorch,应该根据 CPU/GPU 环境分别锁定依赖,不要在同一镜像中无条件安装两套大型运行时。

三、一个可用的基础 Dockerfile

dockerfile 复制代码
FROM python:3.12-slim

ENV PYTHONDONTWRITEBYTECODE=1 \
    PYTHONUNBUFFERED=1 \
    PIP_NO_CACHE_DIR=1

WORKDIR /app

COPY requirements.txt .
RUN pip install --upgrade pip \
    && pip install -r requirements.txt

COPY app ./app

EXPOSE 8000

CMD ["fastapi", "run", "app/main.py", "--port", "8000"]

这里有一个重要顺序:先复制依赖文件并安装,再复制业务代码。这样业务代码修改时可以复用依赖安装层,缩短构建时间。

FastAPI 官方文档目前建议根据实际部署环境自行构建镜像,使用 fastapi run 或适合当前部署方式的 Worker 配置,不要继续依赖已经弃用的通用 FastAPI 基础镜像。FastAPI 容器部署文档

四、为什么要写 .dockerignore?

没有 .dockerignore,构建上下文可能把以下内容一起发送给 Docker:

text 复制代码
.git/
.venv/
__pycache__/
.env
tests/data/
模型临时文件
日志和调试输出

建议:

text 复制代码
.git
.venv
__pycache__
*.pyc
.env
.pytest_cache
logs
data/tmp

.env 尤其重要,它可能包含数据库密码、模型供应商 Token 或对象存储密钥。忽略文件只能减少误打包,不能替代密钥管理;已经提交到 Git 的密钥仍需要轮换。

五、模型文件要不要打进镜像?

通常有三种方案:

方案 优点 风险
打进镜像 启动简单,版本绑定 镜像很大,更新慢
启动时下载 镜像小 启动依赖网络和凭据
挂载模型目录 更新灵活 需要管理路径、权限和版本

选择时看模型大小、更新频率和部署环境。无论采用哪种方案,都应该记录模型版本和校验和:

text 复制代码
model_name=classifier
model_version=v3
sha256=...

不要让容器启动时无条件下载一个"最新模型"。这会让同一个镜像在不同时间启动出不同结果,也会让故障恢复依赖外部网络。

六、把模型目录作为 Volume 挂载

开发环境可以这样运行:

bash 复制代码
docker run --rm \
  -p 8000:8000 \
  -v "${PWD}/models:/app/models:ro" \
  -e ALGO_MODEL_PATH=/app/models/classifier-v3.onnx \
  algorithm-api:dev

注意使用只读挂载 :ro。算法服务通常只需要读取模型,不应该有权限修改模型文件。生产环境还要限制模型目录来源,并在启动时检查文件权限和哈希。

七、用非 root 用户运行

默认 root 用户运行会扩大容器内漏洞的影响范围。可以在镜像中创建普通用户:

dockerfile 复制代码
FROM python:3.12-slim

ENV PYTHONDONTWRITEBYTECODE=1 \
    PYTHONUNBUFFERED=1

WORKDIR /app

RUN groupadd --system app \
    && useradd --system --gid app --create-home app

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY --chown=app:app app ./app

USER app
EXPOSE 8000
CMD ["fastapi", "run", "app/main.py", "--port", "8000"]

如果运行时需要写临时文件,应明确创建一个可写目录,而不是让整个根文件系统保持可写。

八、添加健康检查

健康检查应该检查服务是否真的能接收请求,而不只是进程存在:

dockerfile 复制代码
HEALTHCHECK --interval=30s --timeout=5s --start-period=30s --retries=3 \
  CMD python -c "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8000/health', timeout=3)"

应用中提供轻量接口:

python 复制代码
@app.get("/health")
def health():
    return {"status": "ok"}

如果模型尚未加载完成,建议另外提供 /ready,返回未就绪状态,而不是让健康检查把正在加载模型的容器反复重启。

九、构建、运行和排查

构建镜像:

bash 复制代码
docker build -t algorithm-api:0.1.0 .

运行:

bash 复制代码
docker run --rm -p 8000:8000 algorithm-api:0.1.0

查看日志和进入容器:

bash 复制代码
docker logs -f <container_id>
docker exec -it <container_id> sh

常见问题:

  • 容器启动即退出:检查 CMD、模块路径和启动日志;
  • 找不到模型:检查容器内路径,不要使用宿主机绝对路径;
  • 端口无法访问:确认应用监听 0.0.0.0,且端口映射正确;
  • 构建特别慢:检查 .dockerignore 和依赖缓存;
  • 镜像体积过大:拆分 CPU/GPU 依赖,删除构建缓存和无用文件。

十、生产构建还要关注什么?

正式发布前建议补充:

  • 固定基础镜像和依赖版本;
  • 生成依赖清单和漏洞扫描报告;
  • 使用 Git SHA 或不可变 Digest 标记镜像;
  • 不把 API Key 和数据库密码写进镜像;
  • 设定 CPU、内存、GPU 和临时目录限制;
  • 记录镜像、模型和配置版本;
  • 准备回滚镜像和兼容的数据库迁移方案。

镜像只是交付单位,不是完整部署方案。下一篇将介绍如何用 Docker Compose 把算法 API、数据库和缓存组合起来。

参考资料

  1. FastAPI 官方文档:FastAPI in Containers
  2. Docker 官方文档:Dockerfile reference
  3. Docker 官方文档:Build context

本文为"码海寻道"原创技术文章。基础镜像、Python 版本和推理运行时应根据目标 CPU/GPU 环境进行压测和兼容性验证。

相关推荐
宝哥聊编程4 小时前
主流 Agent 平台对比:Coze、Dify、飞书、扣子、OpenClaw 落地实操手册
前端·人工智能·飞书
sunzy_泽阳4 小时前
《Spring Ai 2.1 + LangGraph4j》系列教程(上):从零建项目到可恢复的 Java Graph
人工智能·agent
武天旭4 小时前
AI安全--AI大模型的关键技术组成
人工智能·深度学习·安全·机器学习
Dmz丶4 小时前
前端转 AI 100 天 Day 36:Prompt 工程入门——从“感觉对了就行”到方法论
python
无心水4 小时前
22、数学与经济管理(运筹学) 核心考点与学习笔记
人工智能·笔记·学习·架构师·软考·软考架构师·软考系统架构师
日日大王学编程5 小时前
AI 时代后端方向新人的未来规划与看法
人工智能·后端·python·ai·golang
小哈里5 小时前
【Agent】从Prompt工程、Context工程到 Harness工程,让 AI 能真正完成工作
人工智能·prompt·agent·ai编程·harness
Juicedata5 小时前
从 Meta 的工程实践看 EB 级 AI 存储架构
人工智能·架构
CCblandy5 小时前
缓存淘汰实测:一次全表扫描把 LRU 命中率从 46% 打到 38%,W-TinyLFU 守住 50% 却贵 11 倍
后端·python·缓存·性能优化·架构