Ansible:如何使用动态键名称设置 Docker 容器标签?

Rei*_*pes 7 jinja2 ansible docker ansible-template traefik

我尝试使用 traefik 标签启动 docker 容器。要为容器创建 traefik 路由器,您必须放置一些像这样的标签。

app_names:
  - tower01
  - tower02

docker_labels:
    awx_web:
      traefik.enable: "true"
      traefik.http.routers.{{ app_name }}.entrypoints: "http"
      traefik.http.routers.{{ app_name }}.rule: "Host(`{{ app_server_fqdn }}`)"
      traefik.http.routers.{{ app_name }}.middlewares: "https-redirect@file"
      traefik.http.routers.{{ app_name }}-sec.entrypoints: "https"
      traefik.http.routers.{{ app_name }}-sec.rule: "Host(`{{ app_server_fqdn }}`)"
      traefik.http.routers.{{ app_name }}-sec.tls: "true"
      traefik.http.routers.{{ app_name }}-sec.tls.options: "myTLSOptions@file"
      traefik.http.routers.{{ app_name }}-sec.tls.certresolver: "le"
      traefik.http.routers.{{ app_name }}-sec.middlewares: "default-headers@file"
      traefik.http.services.{{ app_name }}.loadbalancer.server.port: "8052"
      com.centurylinklabs.watchtower.enable: "{{ autoupdate_container[loop_item] }}"
Run Code Online (Sandbox Code Playgroud)

并使用与此类似的任务:

app_names:
  - tower01
  - tower02

docker_labels:
    awx_web:
      traefik.enable: "true"
      traefik.http.routers.{{ app_name }}.entrypoints: "http"
      traefik.http.routers.{{ app_name }}.rule: "Host(`{{ app_server_fqdn }}`)"
      traefik.http.routers.{{ app_name }}.middlewares: "https-redirect@file"
      traefik.http.routers.{{ app_name }}-sec.entrypoints: "https"
      traefik.http.routers.{{ app_name }}-sec.rule: "Host(`{{ app_server_fqdn }}`)"
      traefik.http.routers.{{ app_name }}-sec.tls: "true"
      traefik.http.routers.{{ app_name }}-sec.tls.options: "myTLSOptions@file"
      traefik.http.routers.{{ app_name }}-sec.tls.certresolver: "le"
      traefik.http.routers.{{ app_name }}-sec.middlewares: "default-headers@file"
      traefik.http.services.{{ app_name }}.loadbalancer.server.port: "8052"
      com.centurylinklabs.watchtower.enable: "{{ autoupdate_container[loop_item] }}"
Run Code Online (Sandbox Code Playgroud)

当然,标签应该是:

traefik.http.routers.tower01.entrypoints: "http"
traefik.http.routers.tower01.rule: "Host(`{{ app_server_fqdn }}`)"
traefik.http.routers.tower01.middlewares: "https-redirect@file"
traefik.http.routers.tower01-sec.entrypoints: "https"
traefik.http.routers.tower01-sec.rule: "Host(`{{ app_server_fqdn }}`)"
traefik.http.routers.tower01-sec.tls: "true"
traefik.http.routers.tower01-sec.tls.options: "myTLSOptions@file"
traefik.http.routers.tower01-sec.tls.certresolver: "le"
traefik.http.routers.tower01-sec.middlewares: "default-headers@file"
traefik.http.services.tower01.loadbalancer.server.port: "8052"
Run Code Online (Sandbox Code Playgroud)

尽管如此,Ansible 不会处理键名中的 jinja 变量。

任何想法?

小智 2

你需要使用字典。

- name: Create Traefik labels's dictionary
  set_fact:
      my_labels: "{{ my_labels | default({}) | combine ({ item.key : item.value }) }}"
  with_items:
    - { 'key': 'traefik.enable' , 'value': 'true'}
    - { 'key': 'traefik.http.routers.{{ app_name }}.entrypoints' , 'value': 'http'}
    - { 'key': 'traefik.http.routers.{{ app_name }}.rule' , 'value': 'Host(`{{ app_server_fqdn }}`)'}
    - { 'key': 'traefik.http.routers.{{ app_name }}.middlewares' , 'value': 'https-redirect@file'}
    - ...
Run Code Online (Sandbox Code Playgroud)

并在 docker_container 中使用新字典:

- name: "{{ app_name }} | create awx web container"
  docker_container:
    name:           "{{ app_name }}-web"
    hostname:       "awxweb"
    user:           "root"
    image:          "ansible/awx_web:{{ docker_image[loop_item] | default('latest') }}"
    env:            "{{ docker_env[loop_item] | default(omit) }}"
    networks:       [ name: "{{ app_name }}" ]
    purge_networks: true
    volumes:        "{{ docker_volumes[loop_item] | default(omit) }}"
    restart_policy: "unless-stopped"
    labels:         "{{ my_labels }}"
    state:          "{{ state | default('started') }}"
Run Code Online (Sandbox Code Playgroud)

通过循环,您可以创建不同的字典:https ://www.middlewareinventory.com/blog/ansible-dict/