Jinja2中如何通过服务名称而非下标访问YML文件的services属性
解决方案
方法1:直接使用Jinja2过滤器(无需改动原有YML结构)
直接用Jinja2内置的selectattr过滤器按服务名匹配,不需要调整你现有的变量结构,通用语法为:
{{ (services | selectattr('service', 'equalto', '目标服务名') | first).属性名 }}
比如你要获取front服务的image和version,写法就是:
{{ (services | selectattr('service', 'equalto', 'front') | first).image }} {{ (services | selectattr('service', 'equalto', 'front') | first).version }}
修改后的docker-compose.yml.j2完整模板如下(同时修正了你原模板中back服务缩进错误、镜像名多余空格的问题):
version: "3.3" services: front: image: url/{{ (services | selectattr('service', 'equalto', 'front') | first).image }}:{{ (services | selectattr('service', 'equalto', 'front') | first).version }} ports: - "81:81" extra_hosts: - "backend:172.32.3.46" environment: profile: preproduction back: image: url/{{ (services | selectattr('service', 'equalto', 'back') | first).image }}:{{ (services | selectattr('service', 'equalto', 'back') | first).version }} ports: - "82:82" extra_hosts: - "backend:172.32.3.46" environment: profile: preproduction
方法2:提前转换为服务名字典(调用更简洁)
如果需要多次调用不同服务的属性,可以在模板开头先把服务列表转成以服务名为key的字典,后续调用更简单。
首先在模板顶部添加定义:
{% set service_map = {item.service: item for item in services} %}
之后就可以直接通过服务名调用属性,写法如下:
{{ service_map.front.image }} {{ service_map.front.version }} {{ service_map.back.image }} {{ service_map.back.version }}
对应的完整模板示例:
{% set service_map = {item.service: item for item in services} %} version: "3.3" services: front: image: url/{{ service_map.front.image }}:{{ service_map.front.version }} ports: - "81:81" extra_hosts: - "backend:172.32.3.46" environment: profile: preproduction back: image: url/{{ service_map.back.image }}:{{ service_map.back.version }} ports: - "82:82" extra_hosts: - "backend:172.32.3.46" environment: profile: preproduction
注意事项
- 请保证你的YML文件中每个服务的
service字段值唯一,否则筛选和字典转换会取到第一个匹配的项,出现预期外的结果 - 原模板中
url/ {{services[1].image}} : {{services[1].version}}里的多余空格需要删除,否则生成的镜像名称会带空格,导致docker-compose运行报错
内容的提问来源于stack exchange,提问作者Alejandro Sánchez
相关产品推荐
相关产品推荐

