如何拆分Docker Compose文件到多个YAML?解决合并报错问题
问题描述
我有一个包含大量相互依赖服务的损坏的docker-compose.yaml文件,其中volumes、secrets和networks标签占用了大量行数,打算将这些内容导出到多个文件中。
我的尝试配置如下:
volumes.yaml
x-volumes: &volumes driver: local driver_opts: type: bind o: bind device: /data/${{str}} vol1: <<: *volumes str: bla1 vol2: <<: *volumes str: bla2
networks.yaml
nginx: DLNA: driver: macvlan driver_opts: parent: eth0 ipam: config: - subnet: 192.168.178.0/24 gateway: 192.168.178.1 ip_range: 192.168.178.250/32 vpn_apps: driver: bridge driver_opts: com.docker.network.bridge.name: "docker-apps" com.docker.network.bridge.enable_ip_masquerade: "true" com.docker.network.bridge.enable_icc: "true" com.docker.network.driver.mtu: "1500" ipam: driver: default config: - subnet: 172.21.0.0/16 gateway: 172.21.0.1
secrets.yaml
sec1: file: /opt/secrets/sec1 sec2: file: /opt/secrets/sec2
main.yaml
version: "3.8" volumes: <<: ./volumes.yaml networks: <<: ./networks.yaml secrets: <<: ./secrets.yaml services: portainer: image: *images.portainer container_name: portainer restart: always volumes: - vol1: /some/path - vol2: /some/path2 networks: - nginx secrets: - sec1 - sec2
运行时遇到错误:yaml: map merge requires map or sequence of maps as the value,请问如何正确将网络、卷和密钥外部化到不同文件中?
解决方案
你遇到的错误是因为YAML的<<:合并语法仅支持合并当前文件内的映射或映射序列,无法直接引用外部文件路径。以下是两种可行的配置外部化方法:
方法1:Docker Compose多文件组合(推荐)
Docker Compose原生支持通过-f参数加载多个配置文件,文件内容会自动合并为完整配置,兼容性好且无需额外设置。
步骤1:调整各文件结构
每个外部文件只保留对应顶层配置块:
- volumes.yaml
volumes: vol1: driver: local driver_opts: type: bind o: bind device: /data/bla1 vol2: driver: local driver_opts: type: bind o: bind device: /data/bla2
- networks.yaml
networks: nginx: {} DLNA: driver: macvlan driver_opts: parent: eth0 ipam: config: - subnet: 192.168.178.0/24 gateway: 192.168.178.1 ip_range: 192.168.178.250/32 vpn_apps: driver: bridge driver_opts: com.docker.network.bridge.name: "docker-apps" com.docker.network.bridge.enable_ip_masquerade: "true" com.docker.network.bridge.enable_icc: "true" com.docker.network.driver.mtu: "1500" ipam: driver: default config: - subnet: 172.21.0.0/16 gateway: 172.21.0.1
- secrets.yaml
secrets: sec1: file: /opt/secrets/sec1 sec2: file: /opt/secrets/sec2
- main.yaml(保留版本与服务配置)
version: "3.8" services: portainer: image: portainer/portainer-ce:latest container_name: portainer restart: always volumes: - vol1: /some/path - vol2: /some/path2 networks: - nginx secrets: - sec1 - sec2
步骤2:加载所有文件运行
执行以下命令启动服务:
docker-compose -f main.yaml -f volumes.yaml -f networks.yaml -f secrets.yaml up -d
方法2:使用YAML !include指令(需实验性功能)
Docker Compose提供实验性的!include指令可直接引用外部文件内容,但需要启用实验性功能。
步骤1:调整文件结构
各外部文件仅保留对应模块的内容(无需顶层键):
- volumes.yaml
vol1: driver: local driver_opts: type: bind o: bind device: /data/bla1 vol2: driver: local driver_opts: type: bind o: bind device: /data/bla2
networks.yaml、secrets.yaml同理,仅保留网络/密钥的映射内容。
步骤2:修改main.yaml引用外部文件
version: "3.8" volumes: !include ./volumes.yaml networks: !include ./networks.yaml secrets: !include ./secrets.yaml services: portainer: image: portainer/portainer-ce:latest container_name: portainer restart: always volumes: - vol1: /some/path - vol2: /some/path2 networks: - nginx secrets: - sec1 - sec2
步骤3:启用实验性功能运行
COMPOSE_EXPERIMENTAL="true" docker-compose up -d
注意事项
- YAML锚点
&与合并<<:仅在同一文件内有效,跨文件无法引用。若需复用配置片段,可将共享锚点放在单独的common.yaml中,再通过多文件加载方式引入。 - 方法1为Docker Compose标准用法,兼容性更好,优先推荐。
- 原配置中的
*images.portainer锚点需确保定义在某个加载的文件内,例如在common.yaml中添加x-images: &images.portainer portainer/portainer-ce:latest,再将common.yaml加入加载参数。
内容的提问来源于stack exchange,提问作者studentaccount13
相关产品推荐
相关产品推荐

