docker compose 通过 docker-compose.yml 定义多容器应用,用 depends_on 控制启动顺序(仅保证容器启动先后,不等待服务就绪),用 volumes 挂载本地代码实现热更新;需配合健康检查、重试逻辑及正确路径映射才能确保 python 开发环境稳定运行。

直接说结论:用 docker-compose.yml 定义服务、用 depends_on 控制启动顺序、用 volumes 挂载代码实现热更新——这三步做完,Python 多容器开发环境就跑起来了,不需要手动拉镜像、配网络或记一堆 docker run 参数。
docker-compose.yml 里 service 怎么写才不踩坑
每个 service 实际对应一个容器,但 Python 开发中容易忽略两点:一是没显式指定 restart 策略导致容器崩溃后静默退出;二是把 command 写死在 Dockerfile 里,结果 docker-compose.yml 中的覆盖失效。
-
web服务建议用build: .+command显式启动(比如python app.py),而不是依赖Dockerfile的CMD,方便调试时换命令 -
db或redis这类官方镜像,直接用image:拉取,别自己build,除非你真要改基础配置 -
environment下的变量名必须和应用代码里读取的一致,比如 Flask 读REDIS_URL,那这里就得写REDIS_URL: redis://redis:6379/0,不能只写host: redis - 别漏掉
restart: unless-stopped,否则容器一崩你就得手动docker-compose up -d重拉
depends_on 只控制启动顺序,不等服务就绪
depends_on 是 Docker Compose 最常被误解的字段。它只保证容器创建和启动的先后,**不检查目标服务是否真正 ready**。比如 db 容器刚起来,MySQL 还在初始化,web 就连过去,必然报 ConnectionRefusedError。
- 真实项目里必须加健康检查:
healthcheck配合condition: service_healthy - 示例:给
db加上healthcheck,再让web的depends_on指向它,并设condition - Python 应用内部也建议加重试逻辑,比如用
tenacity包重试数据库连接,别指望编排层兜底
Python 代码热更新怎么配才生效
本地改 app.py,容器里没反应?大概率是 volumes 挂载路径写错了,或者没避开 COPY . . 的构建缓存。
- 开发模式下,
volumes必须挂载到容器内实际运行代码的路径,比如WORKDIR /app,那就得写./src:/app,不是./src:/app/src -
Dockerfile里别COPY . .到工作目录,否则构建时就把当前代码打进镜像了,挂载卷会被覆盖 - Flask 自动重载需要传
--reload,所以command得写成["flask", "run", "--host=0.0.0.0:5000", "--reload"],且确保FLASK_DEBUG=1 - 注意
.dockerignore,如果里面写了__pycache__或*.pyc,挂载后修改可能被忽略(某些旧版 Docker 有此行为)
端口冲突和网络不通怎么快速定位
访问 localhost:5000 打不开,或者容器里 curl redis:6379 失败,优先查三件事:
- 确认
ports是宿主机映射("5000:5000"),不是容器内暴露(EXPOSE只是文档作用) - 所有服务默认在同一个 Compose 网络里,容器间通信用服务名当 host,比如
redis、db,别写localhost或127.0.0.1 - 用
docker-compose exec web sh进容器,再ping redis和telnet redis 6379,能通说明网络和端口没问题,问题在应用层 - 日志最直白:
docker-compose logs -f web看启动报错,docker-compose logs db看数据库是否初始化完成
最易被忽略的是健康检查和 Python 应用自身的连接重试——depends_on 不是银弹,它只管容器启停,不管服务状态。很多“部署成功但连不上”的问题,根源都在这儿。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











