找回密码
 立即注册

QQ登录

只需一步,快速开始

peUfSYR.png
查看: 47|回复: 0

Day 16 Docker Compose高级用法(补发)

[复制链接]

876

主题

13

回帖

2808

积分

管理员

积分
2808
发表于 2026-3-29 16:17:12 | 显示全部楼层 |阅读模式
用了这么久 Docker Compose,你是不是还停留在
  1. docker compose up -d
复制代码
就完事了?

坦白说,大多数人对 Compose 的使用只触及了冰山一角。真正让它发挥威力的,是那些藏在文档深处、很少被提及的进阶用法。今天这篇,我把自己踩坑多年攒下来的实战经验一次性讲透。

下载了一个开源代码,想跟着项目更新

这是我认为 Compose 最被低估的能力——override 机制

很多人遇到过这种场景:用的是开源项目提供的
  1. docker-compose.yml
复制代码
,但你想加点自己的配置,比如多挂载一个目录、改个端口。直接改原文件?下次更新就被覆盖了。

Docker Compose 天生支持多文件合并。它会自动读取同目录下的
  1. docker-compose.override.yml
复制代码
,把里面的配置叠加到主文件上。
  1. # docker-compose.yml(原始文件,不要动它)
  2. services:
  3.   web:
  4.     image: nginx:latest
  5.     ports:
  6.       - "80:80"
复制代码
  1. # docker-compose.override.yml(你的自定义配置)
  2. services:
  3.   web:
  4.     ports:
  5.       - "8443:443"
  6.     volumes:
  7.       - ./custom.conf:/etc/nginx/conf.d/custom.conf
  8.     environment:
  9.       - DEBUG=true
复制代码

执行
  1. docker compose up
复制代码
时,两个文件会自动合并。端口变成了 80 和 8443 两个映射,volume 和环境变量也追加上去了。

如果你想更灵活,可以用
  1. -f
复制代码
参数手动指定多个文件:
  1. docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
复制代码

合并规则也不复杂:单值字段后者覆盖前者,列表字段追加合并
  1. image
复制代码
是单值,后面的文件会覆盖前面的;
  1. ports
复制代码
  1. volumes
复制代码
是列表,会叠加在一起。

这招在区分开发和生产环境时特别好用。基础配置放主文件,开发环境的 debug 参数放 override,生产环境的资源限制放 prod 文件。各管各的,互不干扰。

profiles:按需启动,告别注释大法

你的 Compose 文件里有没有这种情况——调试工具、监控组件平时不需要,用的时候才启动?

以前的做法是注释掉再取消注释,丑得很。
  1. profiles
复制代码
完美解决了这个问题。
  1. services:
  2.   app:
  3.     image: myapp:latest
  4.     ports:
  5.       - "8080:8080"
  6.   debug-tools:
  7.     image: busybox
  8.     profiles:
  9.       - debug
  10.     command: sleep infinity
  11.   prometheus:
  12.     image: prom/prometheus
  13.     profiles:
  14.       - monitoring
  15.     ports:
  16.       - "9090:9090"
复制代码

没有
  1. profiles
复制代码
标签的服务(比如 app)每次都会启动。带了标签的,只有显式激活才会跑:
  1. # 只启动 app
  2. docker compose up -d
  3. # 启动 app + debug 工具
  4. docker compose --profile debug up -d
  5. # 全都要
  6. docker compose --profile debug --profile monitoring up -d
复制代码

干净利落,不用来回改文件。

depends_on 的正确打开方式

很多人知道
  1. depends_on
复制代码
能控制启动顺序,但只写一个服务名就完事了。问题是,容器启动了不代表服务就绪。数据库容器跑起来了,但 MySQL 还在初始化,应用就去连接——直接报错。

Compose 支持健康检查条件:
  1. services:
  2.   db:
  3.     image: mysql:8.0
  4.     environment:
  5.       MYSQL_ROOT_PASSWORD: secret
  6.     healthcheck:
  7.       test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
  8.       interval: 5s
  9.       timeout: 3s
  10.       retries: 10
  11.       start_period: 30s
  12.   app:
  13.     image: myapp:latest
  14.     depends_on:
  15.       db:
  16.         condition: service_healthy
  17.         restart: true
复制代码
  1. condition: service_healthy
复制代码
意味着 app 会等到 db 的健康检查通过才启动。
  1. restart: true
复制代码
是个容易被忽略的参数——当 db 重启后,app 也会跟着重启。在数据库升级场景下非常实用。
  1. start_period
复制代码
也值得说一下:它给容器一个"宽限期",在这段时间内健康检查失败不算数。数据库第一次初始化可能要几十秒,没有这个参数会被误判为不健康。

资源限制:别让一个容器吃光服务器

生产环境不做资源限制就是在裸奔。一个内存泄漏就能把整台机器拖垮。
  1. services:
  2.   app:
  3.     image: myapp:latest
  4.     deploy:
  5.       resources:
  6.         limits:
  7.           cpus: "2.0"
  8.           memory: 1G
  9.         reservations:
  10.           cpus: "0.5"
  11.           memory: 256M
复制代码
  1. limits
复制代码
是硬上限,超了就 OOM Kill。
  1. reservations
复制代码
是预留资源,Docker 会保证至少给你这么多。

说白了,limits 是天花板,reservations 是地板。

extension fields:消灭重复配置

多个服务用差不多的配置,复制粘贴改来改去?用 YAML 锚点和 Compose 的扩展字段。
  1. x-common: &common-config
  2.   restart: unless-stopped
  3.   logging:
  4.     driver: json-file
  5.     options:
  6.       max-size: "10m"
  7.       max-file: "3"
  8.   networks:
  9.     - app-net
  10. services:
  11.   api:
  12.     <<: *common-config
  13.     image: api-server:latest
  14.     ports:
  15.       - "8080:8080"
  16.   worker:
  17.     <<: *common-config
  18.     image: worker:latest
  19.     environment:
  20.       - QUEUE=default
复制代码
  1. x-
复制代码
开头的顶级字段会被 Compose 忽略,专门用来存公共配置。
  1. <<: *common-config
复制代码
把公共配置展开合并进来。日志策略、重启策略、网络配置——写一次,到处用。

几个容易踩的坑

env_file 的优先级。同时用了
  1. env_file
复制代码
  1. environment
复制代码
,后者会覆盖前者中的同名变量。另外
  1. .env
复制代码
文件是给 Compose 文件本身做变量替换的,和容器内的环境变量是两回事,别搞混了。
  1. services:
  2.   app:
  3.     image: myapp:${APP_VERSION:-latest}  # 从 .env 读取
  4.     env_file:
  5.       - ./app.env          # 注入到容器内
  6.     environment:
  7.       - DB_HOST=production  # 覆盖 app.env 中的 DB_HOST
复制代码

init 参数。加一行
  1. init: true
复制代码
,容器里会跑一个 init 进程(tini)来转发信号、回收僵尸进程。不加这个,你的应用可能收不到 SIGTERM,
  1. docker compose down
复制代码
每次都要等 10 秒超时强杀。
  1. services:
  2.   app:
  3.     image: myapp:latest
  4.     init: true
复制代码

tmpfs 挂载。需要高速临时存储又不想写磁盘?比如上传文件的临时目录、应用缓存:
  1. services:
  2.   app:
  3.     image: myapp:latest
  4.     tmpfs:
  5.       - /tmp:size=100M
  6.       - /app/cache:size=200M
复制代码

基于内存,读写速度快,容器重启自动清空。

实用命令速查

最后分享几个日常高频但很多人不知道的命令:
  1. # 只重建某个服务,不影响其他容器
  2. docker compose up -d --no-deps --build api
  3. # 查看最终合并后的完整配置(排查问题用)
  4. docker compose config
  5. # 按服务查看日志,只看最近 100 行
  6. docker compose logs --tail 100 -f api
  7. # 在运行中的容器执行命令
  8. docker compose exec db mysql -u root -p
  9. # 暂停/恢复服务(不销毁容器)
  10. docker compose pause api
  11. docker compose unpause api
复制代码

其中
  1. docker compose config
复制代码
强烈建议养成习惯。用了多文件合并、变量替换、扩展字段之后,最终生效的配置到底长什么样?这个命令直接告诉你答案,省得瞎猜。

━━━━━━━━━━━━━━━━━━━━

Docker Compose 的能力远不止"编排几个容器"这么简单。Override 机制、profiles、健康检查、资源限制、扩展字段——这些功能组合起来,足以应对大多数中小规模的部署场景。

与其急着上 K8s,不如先把手头的 Compose 用明白。

觉得有用的话,点个在看转发一下,让更多人少踩坑。

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码关注微信公众号

Archiver|手机版|小黑屋|风叶林

GMT+8, 2026-5-8 21:40 , Processed in 0.189761 second(s), 19 queries .

Powered by 风叶林

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表