问题
The error
I try to launch a logspout container and set the log format (an ENV variable) via a docker-compose file. Not too difficult, and if I launch it with docker-compose up
, everything works fine. But when I try to launch it with docker swarm init
and docker stack deploy -c docker-compose.yml mystack
, I get an error:
Error response from daemon: rpc error: code = InvalidArgument desc = expanding env failed: expanding 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 }} }": template: expansion:1: function "toJSON" not defined
What I understand
I think I have the error only with swarm and not docker-compose, because the ENV variable I want to pass to logspout is:
RAW_FORMAT: '{ "container" : "{{ .Container.Name }}", "labels": {{ toJSON .Container.Config.Labels }}, "timestamp": "{{ .Time.Format "2006-01-02T15:04:05Z07:00" }}", "source" : "{{ .Source }}", "message": {{ toJSON .Data }} }'
This ENV variable contains a go template. But with swarm mode, you can create services using go-templates. So it seems that swarm tries (and fails) to parse the value of the ENV variable that I just want to pass to the logspout container.
My question
Is it a way to tell swarm not to parse the go-template in my RAW_FORMAT variable?
If not, is there an other way to set this variable to the correct value?
More...
If you want to reproduce this problem, here is a minimal docker-compose file:
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 }} }'
If you are on windows, you have to execute $Env:COMPOSE_CONVERT_WINDOWS_PATHS=1
first.
回答1:
In go templates, escaping {{
can be done with {{"{{"}}
, so your yml file should look like this:
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 }} }'
回答2:
You can warp by {{`
string `}}
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 }} }`}}'
Another example
LDAP_SEARCH_FILTER={{`(sAMAccountName={{username}})`}}
来源:https://stackoverflow.com/questions/52855230/docker-swarm-tries-to-parse-the-value-of-env-variable-in-my-compose-file-becaus