冷蟊初退 孤灯野澜 志起鸡鸣 墓不悲秋 技术交流 软件开发 商业合作 加Q:411239339

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

浏览:8次阅读
没有评论

共计 2310 个字符,预计需要花费 6 分钟才能阅读完成。

用了这么久 Docker Compose,你是不是还停留在 docker compose up -d 就完事了?

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

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

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

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

Docker Compose 天生支持多文件合并。它会自动读取同目录下的 docker-compose.override.yml,把里面的配置叠加到主文件上。

# docker-compose.yml(原始文件,不要动它)services:
  web:
    image: nginx:latest
    ports:
      - "80:80"
# docker-compose.override.yml(你的自定义配置)services:
  web:
    ports:
      - "8443:443"
    volumes:
      - ./custom.conf:/etc/nginx/conf.d/custom.conf
    environment:
      - DEBUG=true

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

如果你想更灵活,可以用 -f 参数手动指定多个文件:

docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d

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

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

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

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

以前的做法是注释掉再取消注释,丑得很。profiles 完美解决了这个问题。

services:
  app:
    image: myapp:latest
    ports:
      - "8080:8080"

  debug-tools:
    image: busybox
    profiles:
      - debug
    command: sleep infinity

  prometheus:
    image: prom/prometheus
    profiles:
      - monitoring
    ports:
      - "9090:9090"

没有 profiles 标签的服务(比如 app)每次都会启动。带了标签的,只有显式激活才会跑:

# 只启动 app
docker compose up -d

# 启动 app + debug 工具
docker compose --profile debug up -d

# 全都要
docker compose --profile debug --profile monitoring up -d

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

depends_on 的正确打开方式

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

Compose 支持健康检查条件:

services:
  db:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: secret
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 5s
      timeout: 3s
      retries: 10
      start_period: 30s

  app:
    image: myapp:latest
    depends_on:
      db:
        condition: service_healthy
        restart: true

condition: service_healthy 意味着 app 会等到 db 的健康检查通过才启动。restart: true 是个容易被忽略的参数——当 db 重启后,app 也会跟着重启。在数据库升级场景下非常实用。

start_period 也值得说一下:它给容器一个 " 宽限期 ",在这段时间内健康检查失败不算数。数据库第一次初始化可能要几十秒,没有这个参数会被误判为不健康。

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

生产环境不做资源限制就是在裸奔。一个内存泄漏就能把整台机器拖垮。

services:
  app:
    image: myapp:latest
    deploy:
      resources:
        limits:
          cpus: "2.0"
          memory: 1G
        reservations:
          cpus: "0.5"
          memory: 256M

limits 是硬上限,超了就 OOM Kill。reservations 是预留资源,Docker 会保证至少给你这么多。

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

extension fields:消灭重复配置

多个服务用差不多的配置,复制粘贴改来改去?用 YAML 锚点和 Compose 的扩展字段。

x-common: &common-config
  restart: unless-stopped
  logging:
    driver: json-file
    options:
      max-size: "10m"
      max-file: "3"
  networks:
    - app-net

services:
  api:
    <<: *common-config
    image: api-server:latest
    ports:
      - "8080:8080"

  worker:
    <<: *common-config
    image: worker:latest
    environment:
      - QUEUE=default

x- 开头的顶级字段会被 Compose 忽略,专门用来存公共配置。<<: *common-config 把公共配置展开合并进来。日志策略、重启策略、网络配置——写一次,到处用。

几个容易踩的坑

env_file 的优先级 。同时用了 env_fileenvironment,后者会覆盖前者中的同名变量。另外 .env 文件是给 Compose 文件本身做变量替换的,和容器内的环境变量是两回事,别搞混了。

services:
  app:
    image: myapp:${APP_VERSION:-latest}  # 从 .env 读取
    env_file:
      - ./app.env          # 注入到容器内
    environment:
      - DB_HOST=production  # 覆盖 app.env 中的 DB_HOST

init 参数 。加一行 init: true,容器里会跑一个 init 进程(tini)来转发信号、回收僵尸进程。不加这个,你的应用可能收不到 SIGTERM,docker compose down 每次都要等 10 秒超时强杀。

services:
  app:
    image: myapp:latest
    init: true

tmpfs 挂载 。需要高速临时存储又不想写磁盘?比如上传文件的临时目录、应用缓存:

services:
  app:
    image: myapp:latest
    tmpfs:
      - /tmp:size=100M
      - /app/cache:size=200M

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

实用命令速查

最后分享几个日常高频但很多人不知道的命令:

# 只重建某个服务,不影响其他容器
docker compose up -d --no-deps --build api

# 查看最终合并后的完整配置(排查问题用)docker compose config

# 按服务查看日志,只看最近 100 行
docker compose logs --tail 100 -f api

# 在运行中的容器执行命令
docker compose exec db mysql -u root -p

# 暂停 / 恢复服务(不销毁容器)docker compose pause api
docker compose unpause api

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


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

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

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

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

正文完
创作不易,扫码加点动力
post-qrcode
 0
果较瘦
版权声明:本站原创文章,由 果较瘦 于2026-03-29发表,共计2310字。
转载说明:除特殊说明外本站文章皆由果较瘦原创发布,转载请注明出处。