news 2026/7/30 11:12:20

Docker Compose 实战:多服务编排、depends_on 与健康检查的正确姿势

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Docker Compose 实战:多服务编排、depends_on 与健康检查的正确姿势

Docker Compose 实战:多服务编排、depends_on 与健康检查的正确姿势

一个稍微像样的后端项目,本地跑起来往往不止一个容器:一个 web 服务、一个 Postgres、一个 Redis。用docker run一个个手敲命令,端口、网络、环境变量全靠记忆,换台机器重来一遍——这活儿谁干谁烦。Docker Compose 就是把这套「多容器怎么起、怎么连、按什么顺序起」写进一个 YAML 文件,一条docker compose up全部拉起来。

这篇不讲 Compose 是什么这种废话,直接从一个能跑的三服务项目出发,重点讲两个最容易踩坑的地方:服务依赖顺序健康检查

一个最小可用的三服务编排

假设项目结构是一个 Node/Python web 服务 + Postgres + Redis。docker-compose.yml这样写:

services:web:build:.# 用当前目录的 Dockerfile 构建ports:-"8080:8080"# 宿主机:容器environment:DATABASE_URL:postgres://app:secret@db:5432/appdbREDIS_URL:redis://cache:6379depends_on:-db-cachedb:image:postgres:16environment:POSTGRES_USER:appPOSTGRES_PASSWORD:secretPOSTGRES_DB:appdbvolumes:-pgdata:/var/lib/postgresql/data# 数据持久化,别每次 down 就丢库cache:image:redis:7volumes:pgdata:# 具名卷,交给 Docker 管理

docker compose up -d后台拉起三个容器。这里有个新手最容易忽略的关键点:web 服务连数据库的地址是db:5432,不是localhost:5432

因为 Compose 会自动建一个网络,把所有服务放进去,服务名(dbcache)就是 DNS 主机名,容器之间用服务名互访。写成localhost会连到容器自己身上,必然连不上——这是排查「本地能跑,Compose 里连不上数据库」的第一嫌疑。

depends_on 的真相:它只保证「启动顺序」,不保证「就绪」

上面用了depends_on: [db, cache],很多人以为这表示「等数据库准备好接受连接了,再启动 web」。错。depends_on只保证容器启动的先后顺序——db 容器先start,web 容器后start。但 Postgres 容器「进程起来了」和「数据库能接受连接了」之间还有几秒初始化时间。

结果就是经典翻车现场:web 容器一启动就去连db:5432,而 Postgres 还在初始化,连接被拒,web 直接崩溃退出。

web-1 | Error: connect ECONNREFUSED db:5432 web-1 exited with code 1

要真正「等数据库就绪」,得给 db 加健康检查,再让 web 用depends_oncondition: service_healthy语法等它健康。

用 healthcheck + condition 等服务真正就绪

改进版:

services:web:build:.ports:-"8080:8080"environment:DATABASE_URL:postgres://app:secret@db:5432/appdbREDIS_URL:redis://cache:6379depends_on:db:condition:service_healthy# 等 db 健康检查通过再启动cache:condition:service_healthydb:image:postgres:16environment:POSTGRES_USER:appPOSTGRES_PASSWORD:secretPOSTGRES_DB:appdbvolumes:-pgdata:/var/lib/postgresql/datahealthcheck:# pg_isready 是 postgres 自带的探活命令,能连上才算健康test:["CMD-SHELL","pg_isready -U app -d appdb"]interval:5s# 每 5s 探一次timeout:3s# 单次探测 3s 超时retries:5# 连续 5 次失败才判定 unhealthystart_period:10s# 前 10s 是启动宽限期,失败不计入 retriescache:image:redis:7healthcheck:test:["CMD","redis-cli","ping"]# 返回 PONG 即健康interval:5stimeout:3sretries:5volumes:pgdata:

现在的启动流程变成:

  1. db、cache 容器启动,Compose 开始跑它们的 healthcheck;
  2. pg_isready/redis-cli ping通过后,db、cache 状态变为healthy;
  3. 此时web 才启动,连数据库时对面已经就绪,不会再 ECONNREFUSED。

几个 healthcheck 参数别配错:

  • start_period是关键。数据库启动本身要几秒,这段时间探测失败是正常的。设了start_period: 10s,前 10 秒的失败不算进retries,避免容器还在正常启动就被误判 unhealthy 而重启。
  • interval × retries大致是「最坏多久判定挂掉」。上面是5s × 5 = 25s,按服务实际启动速度调。
  • testCMD是直接执行数组里的命令;用CMD-SHELL是丢给/bin/sh -c跑,需要用到管道、变量、&&时用后者。

应用自己的健康检查:光连上不够,要能干活

数据库pg_isready只说明「能连」,不代表「表建好了、迁移跑完了」。对你自己的 web 服务,健康检查应该打一个真正反映「能对外服务」的接口:

web:build:.ports:-"8080:8080"healthcheck:# 假设应用暴露了 /healthz,内部会检查 DB 连接池等test:["CMD","curl","-f","http://localhost:8080/healthz"]interval:10stimeout:3sretries:3start_period:15s

curl -f在 HTTP 状态码非 2xx 时返回非零退出码,正好被 healthcheck 判为失败。这样docker compose ps能直接看出 web 是不是真的活着,而不是「进程在但接口 500」。

注意:test里的命令必须是容器镜像里真实存在的。基于alpine的精简镜像可能没有curl,那就用wget -q -O- http://...或在 Dockerfile 里装上 curl,否则健康检查永远失败。

常用运维命令速查

写完编排,日常就这几条命令:

# 构建并后台启动全部服务dockercompose up-d--build# 看每个服务状态(能看到 healthy / unhealthy)dockercomposeps# 跟踪某个服务的日志dockercompose logs-fweb# 进容器排查dockercomposeexecdb psql-Uapp-dappdb# 只重启一个服务(改了代码重新构建)dockercompose up-d--buildweb# 停止并删除容器、网络(具名卷默认保留,数据还在)dockercompose down# 连数据卷一起删(慎用,会清库)dockercompose down-v

downdown -v的区别是新手最爱踩的坑:down保留具名卷(pgdata),数据库数据还在;down -v会把卷也删掉,库就清空了。想重置环境从零来过才用-v,平时别手滑。

小结

  • Compose 自动建网络,服务名就是主机名,容器间互访用db:5432而不是localhost
  • depends_on只管启动顺序,不管就绪;要等服务真正可用,必须配healthcheck+depends_on: condition: service_healthy
  • healthcheck 的start_period给足启动宽限期,避免正常启动被误判重启;数据库用pg_isready、Redis 用redis-cli ping、web 打自己的/healthz
  • healthcheck 的test命令必须在镜像里真实存在(精简镜像可能没curl)。
  • down保数据,down -v删卷清库,别搞混。

记忆点:depends_on保证「谁先起」,healthcheck才保证「起好了没」——两个一起用,才是真正的按序拉起。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/30 11:11:28

别踩坑!6大乐器优缺点一次性说清楚

各位“投资人”(家长)们,请先别急着打开购物软件搜索“乐器价格”。选乐器,本质上是在给孩子选一位陪伴他少年时代的“灵魂伴侣”。性格不合,强扭的瓜不甜,几万块的设备和几年的时间,可能都打了…

作者头像 李华
网站建设 2026/7/30 11:08:16

WechatDecrypt:三步轻松解密微信聊天记录,重获数据自主权

WechatDecrypt:三步轻松解密微信聊天记录,重获数据自主权 【免费下载链接】WechatDecrypt 微信消息解密工具 项目地址: https://gitcode.com/gh_mirrors/we/WechatDecrypt 你是否曾因微信聊天记录无法访问而感到困扰?当更换手机、备份…

作者头像 李华
网站建设 2026/7/30 11:08:02

S参数实部虚部解读:从复数本质到HFSS仿真与阻抗匹配实战

1. 项目概述:从“玄学”到“工程语言”的S参数刚接触射频微波或者高速电路设计的新人,看到仿真报告或测试数据里那一堆S11、S21的曲线和复数表格,十有八九会懵。这玩意儿到底是个啥?为什么它这么重要?图纸上那个叫“S参…

作者头像 李华
网站建设 2026/7/30 11:07:51

Qt Model/View架构解析与自定义模型实现

1. 理解Model/View架构的核心思想在Qt框架中,Model/View(模型/视图)架构是一种将数据存储与数据展示分离的设计模式。这种架构的核心价值在于解耦数据管理和用户界面,使得开发者可以更灵活地处理复杂的数据展示需求。我第一次接触…

作者头像 李华
网站建设 2026/7/30 11:07:08

如何快速配置Windows系统级音频均衡器:Equalizer APO终极指南

如何快速配置Windows系统级音频均衡器:Equalizer APO终极指南 【免费下载链接】equalizerapo Equalizer APO mirror 项目地址: https://gitcode.com/gh_mirrors/eq/equalizerapo 想要为Windows系统打造专业级的音频体验吗?Equalizer APO是一款基于…

作者头像 李华
网站建设 2026/7/30 11:07:03

全球 AI 大事件|2026 年 7 月 30 日

统计窗口:2026 年 7 月 29 日 09:00 至 2026 年 7 月 30 日 09:00(Asia/Shanghai)。 今天的 AI 新闻主线很清晰:一边是大模型能力继续进入科研、编程、企业 Agent 和安全运营场景;另一边,云厂商和互联网巨头…

作者头像 李华