独立Ansible角色下多应用与反向代理的Docker网络配置方案咨询
场景背景
用Traefik、Nginx或Apache这类反向代理为各类应用提供服务时,如果把反向代理和所有应用放在同一个docker-compose.yml里,网络配置会很简单:
networks: traefik-appfoo: traefik-appbar: services: traefik: # ... 反向代理配置 networks: - traefik-appfoo - traefik-appbar appfoo: # ... 应用配置 networks: - traefik-appfoo appbar: # ... 应用配置 networks: - traefik-appbar
但实际部署中,我采用的是多Ansible角色的Playbook结构,每个服务(反向代理、各应用)都有独立的docker-compose.yml:
roles/ traefik/ # 安装配置Traefik appfoo/ # 安装配置由Traefik代理的foo应用 appbar/ # 安装配置由Traefik代理的bar应用 appbaz/ # 其他应用 playbook.yml
这种情况下,需要把各个应用角色的网络名称传递给Traefik角色,Traefik的docker-compose.yml会有这样的占位:
networks: ? # 需要动态填充应用网络 ? # 需要动态填充应用网络 services: traefik: # ... 反向代理配置 networks: - ? # 需要动态填充应用网络 - ? # 需要动态填充应用网络
我不想在Traefik角色里硬编码网络配置——这种方式混乱、难维护,还会破坏角色的独立性。之前试过在每个应用角色里写Ansible片段,上传到服务器指定目录后用assemble模块拼接成完整的Traefik docker-compose.yml,虽然能保证幂等性,但角色无法完全独立,维护成本极高。
有没有更简便的处理方案?这个问题同样适用于存在后期安装依赖应用的场景。
推荐解决方案
1. 模板化Traefik的Docker Compose文件
把Traefik角色里的docker-compose.yml改成Jinja2模板(命名为docker-compose.yml.j2),通过变量动态生成网络配置:
networks: {% for net in traefik_attached_networks %} {{ net }}: external: true # 声明网络由外部创建(即应用角色的docker-compose创建) {% endfor %} services: traefik: # ... 你的Traefik基础配置 networks: {% for net in traefik_attached_networks %} - {{ net }} {% endfor %}
2. 全局维护或动态收集网络列表
方式一:手动维护全局变量
在Playbook的group_vars/all.yml里统一管理需要Traefik接入的网络:
# group_vars/all.yml traefik_attached_networks: - traefik-appfoo - traefik-appbar # 新增应用时,直接在这里添加对应的网络名称即可
方式二:动态收集(无需手动维护)
如果不想手动更新网络列表,可以让Ansible自动收集应用角色的网络信息:
- 每个应用角色在
defaults/main.yml里定义自己的专属网络名:
# roles/appfoo/defaults/main.yml app_network_name: traefik-appfoo
- 在Playbook的前置任务里收集所有应用的网络名:
# playbook.yml - hosts: your_server pre_tasks: - set_fact: traefik_attached_networks: "{{ traefik_attached_networks | default([]) + [hostvars[inventory_hostname][item + '_network_name']] }}" loop: "{{ app_roles }}" vars: app_roles: - appfoo - appbar roles: - appfoo - appbar - traefik
3. 应用角色创建专属网络
每个应用角色的docker-compose.yml里显式创建对应网络,确保名称和全局变量/收集到的名称一致:
# roles/appfoo/docker-compose.yml networks: traefik-appfoo: name: traefik-appfoo # 显式指定网络名,避免Docker自动生成随机后缀 services: appfoo: # ... 应用配置 networks: - traefik-appfoo
4. 控制角色执行顺序
确保Playbook先执行所有应用角色,再执行Traefik角色——这样应用创建的网络已经存在,Traefik可以直接接入外部网络。
内容的提问来源于stack exchange,提问作者lonix

