compose: Inconsistent env var parsing from docker-compose.yml
If I declare my env vars in bash, I get the following:
10:07 $ export TESTVAR=test
10:08 $ echo $TESTVAR
test
10:08 $ export TESTVAR="test"
10:08 $ echo $TESTVAR
test
However, if I create the following files: Dockerfile:
FROM ubuntu:latest
COPY ./test.sh /test/test.sh
WORKDIR /test
ENTRYPOINT [ "/test/test.sh" ]
test.sh:
#!/bin/bash
echo "--------------TEST RUN---------------"
echo $TESTVAR
case $TESTVAR in
test)
echo "no quotes"
;;
esac
echo "------------END TEST RUN-------------"
docker-compose.yml
testthing:
dockerfile: Dockerfile
build: .
environment:
- TESTVAR="test"
I get the following output:
10:07 $ docker-compose up
Recreating compose_testthing_1
Attaching to compose_testthing_1
testthing_1 | --------------TEST RUN---------------
testthing_1 | "test"
testthing_1 | ------------END TEST RUN-------------
compose_testthing_1 exited with code 0
Changing the environment variable to TESTVAR=test
produces:
10:07 $ docker-compose up
Creating compose_testthing_1
Attaching to compose_testthing_1
testthing_1 | --------------TEST RUN---------------
testthing_1 | test
testthing_1 | no quotes
testthing_1 | ------------END TEST RUN-------------
compose_testthing_1 exited with code 0
For the record, docker itself appears to handle the quotes correctly (test:latest
is the same Dockerfile above being run directly):
10:11 $ docker run -it --rm -e TESTVAR="test" test:latest
--------------TEST RUN---------------
test
no quotes
------------END TEST RUN-------------
Also, compose behaves correctly when using the map syntax, i.e. TESTVAR: "test"
and TESTVAR: test
behave the same way, and consistently with bash (no quotes
is printed).
About this issue
- Original URL
- State: closed
- Created 8 years ago
- Reactions: 36
- Comments: 27
Commits related to this issue
- Allow options with quotes and spaces to be passed in See https://github.com/docker/compose/issues/2854 for related issue. — committed to ernsheong/keycloak-postgres-nginx by ernsheong 7 years ago
- fix(docker-compose): fix yml to use mapping instead of list further reading: https://github.com/docker/compose/issues/2854 https://docs.docker.com/compose/compose-file/#args — committed to dcos/dcos-ui by juliangieseke 7 years ago
- Remove quotes around .env files This fixes docker-compose issues with inconsistent .env parsing. See: https://github.com/docker/compose/issues/2854 However, this will likely break variables such as p... — committed to SonarSoftwareInc/customer_portal by geneccx 5 years ago
- added --dotenv-docker / -k option * docker / docker-compose .env files do not play well with quoted values (unlike any other dotenv implementation it seems) * see https://github.com/docker/compose/... — committed to envwarden/envwarden by deleted user 5 years ago
- use unquoted env variables in docker-compose. Seems to be due to https://github.com/docker/compose/issues/2854 — committed to AleksTeresh/lcl-classifier by deleted user 3 years ago
PR added - please show it some love if you want this fixed!
This has caused me grief as well…
@dnephin I agree with your break down, the problem is that the resulting behaviour is as if compose is setting
export TESTVAR="\"test\""
. It’s confusing and unexpected, which is compounded by the fact things just silently don’t work as expected (because values don’t match up).If this really is the intended behaviour, it should be documented.
I’m probably beating a dead horse here, but this has really caused some major confusion in my scenario as well. I’ve created an example to demonstrate all the possible ways you can screw up environment variables in
docker-compose
. I’m using it as a reference to get the correct behavior as it is unpredictable in my opinion.Here’s my
docker-compose.yml
(the command just prints out the values of the env vars):and my
.env
file:Let’s start the betting to see which tests come out with no quotes at all in the values themselves 🎲 🎲
Results:
Test 1 and 8 are controls, so they don’t count. That leaves only test 2 and 6 from the array syntax, and 9 and 11 from the map syntax:
Particularly troubling was test 5, which ended up with a quoted word inside a quoted sentence, effectively breaking out of the quotes, ala SQL injection.
My biggest complaint is that
docker-compose
does not allow you to quote values in.env
files. This flies in the face of all thedotEnv
implementations that I’ve seen, across multiple languages, and breaks compatibility with my applications, since they can no longer share information with Docker via.env
files reliably. For now I’m just going to keep trimming quotes from env vars, but I really think this should be addressed.This is also unintuitive behavior in env_file. Suppose you want to set
PIP_TRUSTED_HOSTS
with more than one host. In docker-compose’s env_file syntax, you would have to writeIn shell, this would be taken as export
PIP_TRUSTED_HOSTS=pip1
for the commandpip2
. Since the shell is already so finicky with its quotes-handling, I beg you not to diverge too much from it in env_file.dotenv is a specific format used by more than just docker-compose. The dotenv format allows quoted values. The expected behavior of dotenv files is bash-like.
So in my opinion, docker-compose should make one of two possible changes: A) Properly handle dotenv files with quoted values just as
source .env
works in bash B) Use a different format that is intentionally distinct from .env, e.g. yaml, toml, ini, or similar.The current behavior seems totally incorrect and surprising, considering what people expect. I don’t think the expectations are unreasonable either, since the
env_file
is used to set environment variables in a running container.it appears i’m having problems due to docker-compose keeping quotes as part of the value when using the
env_file
. considering (as noted previously) most/all other env file implementation do allow quoting of the values, will this be fixed/changed at any point?per the comments in the thread i can understand (even if i don’t agree with) the rationale for not “altering the expected behavior of yaml” , however since we have both
environment
andenv_file
, maybe haveenv_file
allow quoting of the values? this would both keep the spirit of the yaml handling and give others an avenue for more proper dotenv handling, though i can see some additional documentation being needed for the difference between them.this issue has been hanging open for a few years, so if this isn’t going to happen, maybe it should get an official response and be closed.
@cerw When 1.26 releases, it will have support. The feature was already merged in.
If you would support changing the behavior to clean quotes from values in
.env
, I’m happy to submit a PR.I’m not a native Python speaker, but this should do the trick:
right here: https://github.com/docker/compose/blob/7ae632a9ee7530fcf81e212baa3e588f477ea862/compose/config/environment.py#L21
A possible temporary solution is to run this which removes the quotes
sed -r 's/^([^=]+=)\"(.*)\"$/\1\2/g' .env > .env.docker
and just load .env.docker in env file for docker compose till this lands.Too bad the fix didn’t make it into the cli. Same issue using
--env-file
withdocker run
.Any updates on this?
Hello everyone.
I’m really sorry to hear that you are having problems/doubts with
env_file
parsing. About the topic, my concern is that the issue was opened in 2016 and since then, the entire mechanism ofenv_file
parsing was delegated to python-dotenv and now the behavior is more “standardized”.Also it is very hard for us to know if all of you refer to the same issue.
Given that, I invite you to update
docker-compose
to the latest version and retry it. If the problem persists, please open a new bug with the clearest case of reproduction that you can and we will be happy to triage and fix it when it’s a real bug.Thank you all for the feedback!
.env
files simply may need quotes due to special characters in some of the settings, and they work just fine in just about any environment. Given thatdocker-compose
supports external.env
files, they should be parsed accordingly - as external files, with their own schema. Sodocker-componse
should be interested in the key/value pairs on those files, and be aware the values may or may not be in quotes, rather than blindly reading them, assuming the files adhere to it’s own preferred schema.Obviously, that’s a biased view, but it feels cleaner then asking for
docker-compose
specific.env
files, which just would end up in a mess.So, whats the proper way if I wanna env file which I can
set -a;source env;set +a
work in bash still work in deploy? any idea?just mount the file inside the container and run
source
directly?I think this is working as expected.
In the docker example above, bash is interpreting the quotes for you, so the application never gets
"test"
, it getstests
.In the compose example using map, yaml is interpreting the quotes for you, so Compose never sees the quotes.
In the list of strings example:
TESTVAR="test"
is interpreted by yaml as the literal string'TESTVAR="test"'
.I don’t think compose should alter the expected behaviour of yaml, and remove quotes from the string.