3、Composition文件结构:顶层字段解析

好,咱们今天来聊聊Compose文件的结构。说白了,它就是一份「服务部署说明书」。你写清楚了,Docker就能按你的意思把整个应用跑起来。

我个人习惯把Compose文件看作一个「三层结构」:顶层声明、服务定义、以及底层资源。今天咱们就聚焦顶层——那些写在最前面的字段。

3.1 版本声明:别小看这一行

每个Compose文件的第一行,通常是版本声明。比如:

version: '3.8'

嗯,这里要注意。版本号决定了你能用哪些功能。我见过不少新手直接写version: '3',结果某些字段不生效,排查半天才发现是版本太老。

版本 关键特性 我的建议
2.x 基础功能,不支持Swarm 别用了,太老
3.x 支持Swarm、secrets、configs 推荐3.8+
3.8+ 支持GPU、扩展字段 当前首选
小技巧:如果你不确定用哪个版本,直接写 version: '3.8' 基本不会错。我目前在用的项目都统一用这个版本。

3.2 services:核心中的核心

services 是Compose文件的灵魂。你想想看,整个文件就是为了定义「要跑哪些服务」。

services:
  web:
    image: nginx:latest
    ports:
      - "80:80"
  db:
    image: postgres:13
    environment:
      POSTGRES_PASSWORD: example

每个服务就是一个容器。你可以定义它的镜像、端口、环境变量、挂载卷等等。我曾经在项目中遇到一个问题:两个服务用了同一个端口,结果启动时冲突了。排查了半天才发现是端口映射写重复了。

避坑指南:服务名不要用下划线开头,也不要包含大写字母。Docker Compose对服务名有严格的命名规范,只能用 [a-z0-9_-]

3.3 networks:让服务能互相通信

默认情况下,Compose会创建一个默认网络,所有服务都在里面。但有时候你需要隔离网络,或者指定IP段。

networks:
  frontend:
    driver: bridge
  backend:
    driver: overlay
    ipam:
      config:
        - subnet: 10.0.1.0/24

我个人习惯把前端服务和后端服务放在不同网络里。前端只能访问后端暴露的端口,后端不能直接访问前端。这样安全性会好很多。

重点:如果你不声明networks,Compose会自动创建一个名为 项目名_default 的网络。但显式声明会让你的配置更清晰。

3.4 volumes:数据持久化的命根子

容器一重启,数据就丢了?那肯定不行。volumes就是用来解决这个问题的。

volumes:
  db_data:
    driver: local
  logs:
    driver: local
    driver_opts:
      type: none
      device: /var/log/myapp
      o: bind

记得有一次,我部署了一个数据库服务,没挂载卷。结果容器崩溃重启后,所有数据都没了。嗯,从那以后我再也不敢不挂载卷了。

3.5 configs:配置管理的优雅方案

configs是Swarm模式下才有的功能。它允许你把配置文件独立出来,不用塞进镜像里。

configs:
  my_config:
    file: ./config/nginx.conf
  app_config:
    external: true

你想想看,如果每次改配置都要重新构建镜像,那得多麻烦。用configs,配置文件可以单独管理,热更新也方便。

提示:configs默认挂载到容器的 /configs/ 目录下。你可以通过 target 字段指定挂载路径。

3.6 secrets:敏感信息的安全港湾

密码、API密钥、证书……这些敏感信息不能明文写在Compose文件里。secrets就是干这个的。

secrets:
  db_password:
    file: ./secrets/db_password.txt
  api_key:
    external: true
    name: my_api_key_v1

我曾经见过有人直接把数据库密码写在环境变量里,结果代码泄露后整个数据库被拖库。用secrets,至少能保证敏感信息不会出现在日志或版本控制里。

警告:secrets在Swarm模式下才生效。如果你用的是普通Compose,可以考虑用 .env 文件替代,但安全性会差一些。

3.7 命名规范:好名字省一半调试时间

命名这事,看似简单,其实坑不少。我总结了几条经验:

  • 服务名:全小写,用连字符分隔。比如 web-apidb-master
  • 网络名:用有意义的名称,比如 frontend-netbackend-net
  • 卷名:加上用途前缀,比如 db-dataapp-logs
  • 配置名:包含版本号,比如 nginx-config-v2

说白了,命名规范就是让你三个月后回来看代码,还能一眼看懂每个资源是干嘛的。

3.8 知识结构图

下面这张图,帮你理清Compose文件顶层字段的关系:

Compose文件顶层 services networks volumes configs secrets 核心原则 版本声明决定可用功能 命名规范影响可维护性 顶层字段之间可以互相引用

这张图把顶层字段的关系梳理得很清楚。services是核心,其他字段都是为它服务的。networks、volumes、configs、secrets各自负责不同的资源类型,但它们之间可以互相引用。

总结一下:Compose文件的顶层字段,说白了就是「声明式配置」的体现。你告诉Docker「我要什么」,Docker帮你「怎么实现」。理解了这个思路,写Compose文件就会顺手很多。

公众号:蓝海资料掘金营,微信deep3321