把“我这里能跑”变成可复现:用 Docker 运行一个 Python API
很多小服务在本机能跑,换一台电脑或交给 CI 就开始报错:Python 版本不同、系统依赖缺失,或者启动命令没有写清。Docker 不能替代测试,但可以把运行环境和启动方式变成项目里可审查的文件,让团队少花时间猜环境。
本文用 FastAPI 写一个最小健康检查接口,演示开发环境容器化的几个关键点:明确构建上下文、合理安排镜像层、区分开发挂载与生产镜像,并避免把本地杂项和密钥带进构建过程。
项目结构
python-api/
├── main.py
├── requirements.txt
├── Dockerfile
├── compose.yaml
└── .dockerignore
写一个最小接口
在应用入口处定义健康检查路由:
from fastapi import FastAPI
app = FastAPI()
@app.get("/health")
def health():
return {"status": "ok"}
「requirements.txt」可以先写:
fastapi
uvicorn[standard]
为了让多人和 CI 得到一致结果,正式项目应提交经过验证的依赖锁定版本;不要长期依赖每次构建都解析到的最新版本。
用 Dockerfile 构建镜像
FROM python:3.12-slim
WORKDIR /app
ENV PYTHONDONTWRITEBYTECODE=1 PYTHONUNBUFFERED=1
COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 8000
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
先复制依赖清单并安装,再复制业务代码。这样只改 Python 文件时,构建工具通常能复用前面的依赖层,减少重复安装。EXPOSE 说明容器服务使用的端口,但不会单独把端口发布到宿主机;对外映射要在运行参数或 Compose 配置里写清。
缩小构建上下文
Docker 会把指定目录作为构建上下文,Dockerfile 的 COPY 只能读取上下文里的文件。项目根目录放一个「.dockerignore」:
.venv/
__pycache__/
*.py[cod]
.git/
.env
忽略虚拟环境和 Git 历史能减少无用文件;忽略「.env」可以避免本地配置被意外放进构建上下文。密钥也不应写入 Dockerfile 或镜像层,应通过合适的运行时配置注入。
用 Compose 启动开发环境
services:
api:
build: .
ports:
- "8000:8000"
volumes:
- .:/app
command: uvicorn main:app --host 0.0.0.0 --port 8000 --reload
运行「docker compose up --build」后,可以在本机 8000 端口检查健康检查路由,或用 curl 查看返回的 JSON。Compose 的 ports 将宿主机端口映射到容器端口;volumes 中的目录挂载则让代码修改能立即反映到开发容器里。–reload 只适合开发,生产运行时应移除热重载和源码挂载,并按部署环境固定依赖及镜像版本。
遇到问题时先看三处
第一,应用必须监听 0.0.0.0。若只监听容器内部的 127.0.0.1,宿主机端口映射通常无法访问它。第二,依赖有变化时要重新构建镜像;普通代码改动在上面的目录挂载下无需重建。第三,用「docker compose logs -f api」查看服务日志,比反复猜测端口问题更快。
容器适合保存进程环境,不适合作为唯一的数据存储位置。数据库和需要长期保留的文件应规划具名卷或外部存储,并区分开发与生产配置。把这些边界写进 Compose 文件,往往比增加更多启动脚本更容易交接。
延伸阅读
可查阅 Docker 官方文档中的《构建上下文与 .dockerignore》《Compose 服务配置》和《Compose 卷》章节。
- 点赞
- 收藏
- 关注作者
评论(0)