如何在Ansible循环中配置带变量的字典实现多用户Docker容器及Traefik路由
解决Ansible循环部署带动态Traefik标签Docker容器的方案
问题核心原因
你当前的配置无法运行的核心原因是:Ansible不支持直接在YAML字典的键位置内联Jinja2模板变量,你写在labels下的动态键名不符合Ansible的语法规范。
最优实现方案
不需要用到嵌套循环或复杂的set_fact预定义逻辑,直接在docker_container任务中通过Jinja2模板动态构造完整的labels字典即可,修正后的完整任务代码如下:
- name: Run syncthing docker_container: name: "{{ item.name }}-syncthing" image: "lscr.io/linuxserver/syncthing" state: started restart_policy: "always" env: PUID: "1000" PGID: "1000" volumes: - "{{ item.data_dir }}:/data" # 其他你需要挂载的卷继续加在这里 labels: "{{ { 'traefik.enable': 'true', 'traefik.http.routers.' ~ item.name ~ '-syncthing.entrypoints': 'websecure', 'traefik.http.routers.' ~ item.name ~ '-syncthing.rule': 'Host(`' ~ item.name ~ '.' ~ fqdn_real ~ '`)', 'traefik.http.routers.' ~ item.name ~ '-syncthing.tls': 'true', 'traefik.http.routers.' ~ item.name ~ '-syncthing.tls.certresolver': 'le', 'traefik.http.routers.' ~ item.name ~ '-syncthing.service': item.name ~ '-syncthing', 'traefik.http.routers.' ~ item.name ~ '-syncthing.middlewares': item.name ~ '-syncthing-basicauth', 'traefik.http.services.' ~ item.name ~ '-syncthing.loadbalancer.server.port': '8080', 'traefik.http.middlewares.' ~ item.name ~ '-syncthing-basicauth.basicauth.users': item.auth } }}" loop: "{{ syncthing_containers_info }}"
注意事项
- 上面的代码修正了你原有配置里的一个笔误:你之前路由引用的中间件名是
{{ item.name }}-basicauth,但实际定义的中间件名是{{ item.name }}-syncthing-basicauth,两者不一致会导致Traefik报错,这里已经统一为后者,你可以根据实际需求调整。 - 代码中使用
~作为Jinja2的字符串拼接符,语法兼容性更好,所有变量都会被正确解析拼接成最终的标签键名。 - 你原有定义的
syncthing_containers_info变量不需要做任何修改,可以直接复用。
验证方法
如果你需要先确认生成的标签是否正确,可以在部署容器前新增一个debug任务打印配置:
- name: Debug generated labels debug: msg: "{{ { 'traefik.enable': 'true', 'traefik.http.routers.' ~ item.name ~ '-syncthing.entrypoints': 'websecure', 'traefik.http.routers.' ~ item.name ~ '-syncthing.rule': 'Host(`' ~ item.name ~ '.' ~ fqdn_real ~ '`)', 'traefik.http.routers.' ~ item.name ~ '-syncthing.tls': 'true', 'traefik.http.routers.' ~ item.name ~ '-syncthing.tls.certresolver': 'le', 'traefik.http.routers.' ~ item.name ~ '-syncthing.service': item.name ~ '-syncthing', 'traefik.http.routers.' ~ item.name ~ '-syncthing.middlewares': item.name ~ '-syncthing-basicauth', 'traefik.http.services.' ~ item.name ~ '-syncthing.loadbalancer.server.port': '8080', 'traefik.http.middlewares.' ~ item.name ~ '-syncthing-basicauth.basicauth.users': item.auth } }}" loop: "{{ syncthing_containers_info }}"
内容的提问来源于stack exchange,提问作者xmd
相关产品推荐
相关产品推荐

