Docker swarm 尝试解析我的 compose 文件中 ENV 变量的值(因为它有一个 go 模板)并给我一个错误

Docker swarm tries to parse the value of ENV variable in my compose file (because it has a go template in it) and gives me an error

错误

我尝试启动一个 logspout 容器并通过 docker-compose 文件设置日志格式(一个 ENV 变量)。不太难,如果我用 docker-compose up 启动它,一切正常。但是当我尝试使用 docker swarm initdocker stack deploy -c docker-compose.yml mystack 启动它时,我得到一个错误:

来自守护程序的错误响应:rpc 错误:code = InvalidArgument desc = 扩展环境失败:扩展环境 "RAW_FORMAT={ \"container\" : \"{{ .Container.Name }} \", \"labels\": {{ toJSON .Container.Config.Labels }}, \"timestamp\": \"{{ .Time.Format \"2006-01-02T15:04:05Z07 :00\" }}\", \"source\" : \"{{ .Source }}\", \"message\": {{ toJSON .Data }} }": 模板: expansion:1: 函数"toJSON"未定义

我的理解

我想我只有 swarm 有错误,而不是 docker-compose,因为我想传递给 logspout 的 ENV 变量是:

RAW_FORMAT: '{ "container" : "{{ .Container.Name }}", "labels": {{ toJSON .Container.Config.Labels }}, "timestamp": "{{ .Time.Format "2006-01-02T15:04:05Z07:00" }}", "source" : "{{ .Source }} ", "message": {{ toJSON .Data }} }'

此 ENV 变量包含一个 go 模板。但是有了集群模式,你可以create services using go-templates。因此,似乎 swarm 尝试(但失败了)解析我只想传递给 logspout 容器的 ENV 变量的值。

我的问题

  1. 这是告诉 swarm 不要解析我的 RAW_FORMAT 变量中的 go-template 的方法吗?

  2. 如果不是,是否有其他方法可以将此变量设置为正确的值?

更多...

如果您想重现这个问题,这里有一个最小的 docker-compose 文件:

version: "3.3"
services:
logspout:
  image: gliderlabs/logspout:latest
  volumes:
    - /etc/hostname:/etc/host_hostname:ro
    - /var/run/docker.sock:/var/run/docker.sock
  environment:
    RAW_FORMAT: '{ "container" : "{{ .Container.Name }}", "labels": {{ toJSON .Container.Config.Labels }}, "timestamp": "{{ .Time.Format "2006-01-02T15:04:05Z07:00" }}", "source" : "{{ .Source }}", "message": {{ toJSON .Data }} }'

如果你在windows,你必须先执行$Env:COMPOSE_CONVERT_WINDOWS_PATHS=1

在 go 模板中,可以使用 {{"{{"}} 转义 {{,因此您的 yml 文件应如下所示:

version: "3.3"
services:
  logspout:
    image: gliderlabs/logspout:latest
    volumes:
      - /etc/hostname:/etc/host_hostname:ro
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      RAW_FORMAT: '{ "container" : "{{"{{"}} .Container.Name }}", "labels": {{"{{"}} toJSON .Container.Config.Labels }}, "timestamp": "{{"{{"}} .Time.Format "2006-01-02T15:04:05Z07:00" }}", "source" : "{{"{{"}} .Source }}", "message": {{"{{"}} toJSON .Data }} }'

你可以通过 {{` 字符串 `}}

  environment:
    RAW_FORMAT: '{{`{ "container" : "{{ .Container.Name }}`}}", "labels": {{ toJSON .Container.Config.Labels }}, "timestamp": "{{ .Time.Format "2006-01-02T15:04:05Z07:00" }}", "source" : "{{ .Source }}", "message": {{ toJSON .Data }} }`}}'

另一个例子

LDAP_SEARCH_FILTER={{`(sAMAccountName={{username}})`}}