07入门:Compose进阶

第 7 关 Compose 进阶
本关的产出:把第 6 关那份文件补上「顺序」和「就绪」两层,再用多文件与 profiles 管住本地、生产两套环境。
7.1 起得来,不等于能连
第 6 关那份文件,up -d 之后有个问题:web 里的程序连 db 会失败一阵。第 2 关那条坑——mysql 第一次启动要先初始化数据目录,得等十几秒——到了 compose 里原样复现。
compose 起容器有顺序,但顺序来自 depends_on,得自己写:
services: web: image: nginx depends_on: - db写了它,db 会先于 web 创建;down 的时候反过来,web 先拆。(不写 depends_on 也起得来,只是顺序不保证。)
但要注意它管的是什么:depends_on 只等 db 跑起来,不等 db 能应答。mysql 的容器起来了、进程在跑,那十几秒的初始化里 3306 上仍然没人应答——web 该连还是连不上。
所以「起来了」和「就绪了」是两回事。 要表达后者,得先定义什么叫就绪。
7.2 定义一个「就绪」的判据
在 db 上加一段 healthcheck:
db: image: mysql environment: - MYSQL_ROOT_PASSWORD=hecloud healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-uroot", "-phecloud"] interval: 5s timeout: 5s retries: 10 start_period: 30s逐项:
test:判据本身。它是一条命令,退出码为 0 就算这一轮健康。这里用mysqladmin ping——数据库能应答,它才返回 0。interval:隔多久查一轮。timeout:单轮超时就当这轮失败。retries:连续失败几次,才把状态判成「不健康」。start_period:开头的宽限期。这期间内的失败不计数——mysql 初始化慢,就是靠它不至于一上来被误判成挂了。
看状态:
docker compose psSTATUS 那一列会从 (health: starting) 变成 (healthy)。健康检查是容器身上的一层属性,docker inspect 里也看得到。
7.3 等到就绪再起下一个
有了判据,depends_on 就能等它:
web: image: nginx depends_on: db: condition: service_healthycondition 有三种:
service_started:只等跑起来——就是 7.1 那个默认行为。service_healthy:等健康检查判成 healthy 才算过了。service_completed_successfully:等它跑完退出,且退出码为 0。给那种「一次性做完就走」的初始化服务用。
改成 service_healthy,web 会一直等到 db 报 healthy 才被创建——第 2 关那个坑,到这儿才算收口。
易踩的坑:condition 写在依赖方(web)上,healthcheck 得写在被依赖方(db)上——两处别写反。对面没有 healthcheck 时,service_healthy 就没有依据可等。
7.4 一套文件,拆成多份
本地开发和生产跑的不一样:本地要挂源码、开调试端口,生产不要。把这些都塞进一个文件,靠 if 之类的思路去开关,很快就乱了。compose 的办法是按层叠文件。
两个文件,后一个叠在前一个上面:
docker compose -f compose.yaml -f compose.prod.yaml up -d按命令行顺序合并,后面的覆盖前面的。 怎么覆盖,看是哪一类条目,记不住就先跑 docker compose config 看合并后的结果:
- 单值项(
image、command):后面的直接盖掉前面的。 - 键值项(
environment、labels):按键名合并,同名的以后一个为准,新键加上去。 - 挂载(
volumes):按容器里的路径合并,同一个路径以后一个为准。 - 端口列表(
ports、expose):累加——两边都留,加了新的旧的也不消失。
易踩的坑:文件名是 compose.override.yaml 时会被自动叠上,不用写 -f——这是给本地开发留的口子。哪天发现「为什么本地多了一份配置」,通常就是它。
7.5 按需起:profiles
生产不要的东西,除了用 7.4 的文件覆盖关掉,还可以一开始就不让它起。给服务挂一个 profile 名:
services: db: image: mysql
phpmyadmin: image: phpmyadmin profiles: - debug规矩很简单:
- 没写
profiles的服务永远起——db就是。 - 写了
profiles的只在它那个 profile 激活时才起——phpmyadmin平时不出现。
激活:
docker compose --profile debug up -d要开多个就写多遍 --profile,或者逗号隔开;--profile "*" 全开。也可以直接点名:
docker compose up -d phpmyadmin被点名的服务就算 profile 没激活也会起——临时跑个调试工具时会用到。
易踩的坑:docker compose down 只停没 profile 的服务,phpmyadmin 这种得用 docker compose down phpmyadmin 或带 --profile 才停得掉。
这一关的产出:服务之间能表达「等它真的就绪」,以及一套文件管住多套环境的两种手法。下一关回到单个容器,钻进一个第 2 关就绕开的问题——容器里那个进程,是怎么被启动、被停掉的。
本关命令速查
Compose 的命令与用法,见 命令速查表 · Compose。
支持与分享
如果这篇文章对你有帮助,欢迎分享给更多人或打赏支持!





