Dockerfile需锁定Python小版本如python:3.11.7-slim-bookworm;先COPY requirements.txt再pip install以保缓存;CMD须用exec形式确保PID 1为主进程;Web服务必须绑定0.0.0.0且正确暴露端口;密钥等敏感信息禁用ENV硬编码。

Python Web应用的Dockerfile必须指定明确的Python版本和基础镜像
用 python:latest 或 python:slim 不写小版本号,上线后可能突然构建失败或行为异常——因为镜像底层Python微版本升级了,比如 python:3.11-slim 某天变成 3.11.9,而你的 pydantic 依赖只兼容 3.11.7。
实操建议:
- 始终锁定小版本:用
python:3.11.7-slim-bookworm(推荐 Debian Bookworm,比 Alpine 更少遇到 glibc/SSL 兼容问题) - 避免
python:3-alpine,除非你清楚自己在处理 musl libc、缺少二进制 wheel、以及编译psycopg2或numpy的麻烦 - 如果项目用 Poetry,别在 Dockerfile 里反复
poetry install;先本地poetry export -f requirements.txt > requirements.txt,再 COPY 进容器用pip install -r requirements.txt—— 构建更快、层更稳定
WORKDIR 和 COPY 顺序搞反会导致 pip install 缓存失效
Docker 构建缓存很敏感。把 COPY . . 放在 RUN pip install 前面,哪怕只改了一个空格,整个依赖安装步骤就全重来,每次都要下载几百 MB 包。
正确顺序是:
- 先
COPY requirements.txt .(或pyproject.toml+poetry.lock) - 再
RUN pip install -r requirements.txt(或poetry install --no-dev) - 最后
COPY . .
这样改代码不影响依赖层缓存。注意:requirements.txt 文件本身必须存在且内容稳定,否则缓存照样失效。
启动命令不加 exec 导致信号转发失败,Ctrl+C 或 k8s kill 都杀不死进程
写成 CMD python app.py 或 CMD ["sh", "-c", "python app.py"],容器里实际跑的是 shell 进程,Python 是它的子进程。SIGTERM 来了,shell 不会自动转发给子进程,Web 服务无法优雅退出。
安全 Python 代码沙箱:在隔离的沙箱中执行任意 Python 代码,预装 requests、NumPy、pandas 库。返回 stdout、stderr。
必须用 exec 形式:
- 推荐:
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "app:app"](直接起主进程) - 如果非要用 Python 启动,写成:
CMD ["python", "app.py"],别套 shell - 绝对不要:
CMD python app.py(这是 shell form,隐含 /bin/sh -c)
验证方法:进容器 ps aux,看 PID 1 是否是你期望的进程(如 gunicorn),不是 /bin/sh。
没暴露端口或没绑定 0.0.0.0,容器跑起来却访问不了
EXPOSE 8000 只是文档说明,不等于真的开放端口;Flask 默认绑定 127.0.0.1:5000,在容器里就只能本机访问,外部连不上。
关键点:
-
EXPOSE要写,但更重要的是运行时加-p 8000:8000;K8s 则靠 Service 配置 - Web 框架必须显式绑定
0.0.0.0:8000:Flask 用app.run(host="0.0.0.0", port=8000),FastAPI 用uvicorn.run(..., host="0.0.0.0", port=8000) - 检查日志有没有类似
Running on http://127.0.0.1:8000—— 这就是坑,得改成0.0.0.0
本地测试时,用 curl -v http://localhost:8000 成功不代表容器内没问题;要进容器 curl http://0.0.0.0:8000 和从宿主机 curl 都通才算。
最常被跳过的其实是环境变量注入方式:用 ENV 写死密钥很危险,应该用 docker run -e DATABASE_URL=... 或挂载 .env 文件,但记得在代码里用 dotenv.load_dotenv() 主动加载,别指望 Docker 自动读取。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










