-
Notifications
You must be signed in to change notification settings - Fork 18.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
builder: Environment variables in CMD
are not used
#42937
Comments
This is (currently) the expected behavior, but documentation can definitely be improved, as this is somewhat "complicated", and can be confusing (also see docker/cli#3323). Docker itself (
First exampleBased on your first example: docker build -t repro-42937 -<<'EOF'
FROM alpine
ENV FOOBAR=fish
CMD echo $FOOBAR
EOF The docker image inspect --format='{{json .Config.Env}}' repro-42937
["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin","FOOBAR=fish"] But the docker image inspect --format='{{json .Config.Cmd}}' repro-42937
["/bin/sh","-c","echo $FOOBAR"] The variable will be evaluated when the command is executed, which also allows you to override the env-variable at runtime: docker run --rm repro-42937
fish
docker run --rm --env FOOBAR=turtles repro-42937
turtles Second exampleIn your second example, docker build -t repro-42937-2 -<<'EOF'
FROM alpine
ARG FOOBAR=fish
CMD echo $FOOBAR
EOF Unlike docker image inspect --format='{{json .Config.Env}}' repro-42937-2
["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"] But (like the first example), the docker image inspect --format='{{json .Config.Cmd}}' repro-42937-2
["/bin/sh","-c","echo $FOOBAR"] The variable will be evaluated when the command is executed, which also allows you to override the env-variable at runtime. As the image does not have a docker run --rm repro-42937-2
But if you specify the environment variable at runtime, it will be printed: docker run --rm --env FOOBAR=turtles repro-42937-2
turtles Third exampleYour third example is simlar to the first one, however, this time you're using the "exec" form (JSON). The "exec" form is used to execute a command without using a shell ( As explained above, environment substitution in docker build -t repro-42937-3 -<<'EOF'
FROM alpine
ENV FOOBAR=fish
CMD ["./${FOOBAR}"]
EOF Inspecting the image shows; docker image inspect --format='{{json .Config.Cmd}}' repro-42937-3
["./${FOOBAR}"] Running the image will produce an error, because (without shell), the env-var is not substituted, and docker run --rm repro-42937-3
docker: Error response from daemon: OCI runtime create failed: container_linux.go:380:
starting container process caused:
exec: "./${FOOBAR}": stat ./${FOOBAR}: no such file or directory: unknown. Changing the Dockerfile to explicitly set a shell to execute the command (I'm changing it to an docker build -t repro-42937-4 -<<'EOF'
FROM alpine
ENV FOOBAR=fish
CMD ["/bin/sh", "-c", "echo $FOOBAR"]
EOF This makes the image the same as the first example: docker image inspect --format='{{json .Config.Cmd}}' repro-42937-4
["/bin/sh","-c","echo $FOOBAR"] By default it will use the docker run --rm repro-42937-4
fish
docker run --rm --env FOOBAR=turtles repro-42937-4
turtles But what about
|
Thanks for your (much) detailed response. @thaJeztah then, this issue is dupe of docker/cli#3323? I went for the |
Personally, it'd make sense to have the following vars:
|
Thank you! This topic really needs better documentation / examples; some time should be spent on that (and we'd need a good place for it in the documentation - perhaps separate from the general Dockerfile syntax page - to allow for it to be described in-depth).
Yes, in hindsight (my personal 0.02c - I had some discussion on this with others, and there was no real consensus 😅), perhaps there should've been a separate syntax for variables "known by the builder". Something like; FROM busybox
ARG SOME_ARG=hello
ENV SOME_ENV=hello
RUN echo %{SOME_ARG} $SOME_ENV
LABEL my_label=%{SOME_ARG} Or even: FROM busybox
ARG SOME_ARG=hello
ENV SOME_ENV=hello
RUN echo %{arg:SOME_ARG} %{env:SOME_ENV}
LABEL my_label=%{arg:SOME_ARG} This would allow distinguishing them better, and clearer what substitutions are "templating" / performed by the Dockerfile parsing, and which ones are evaluated by the shell, although it would have to be looked at if that could cause additional confusion, e.g. both variants below would result in the same, but for different reasons: RUN echo %{arg:SOME_ARG} %{env:SOME_ENV}
RUN echo $SOME_ARG $SOME_ENV It would potentially avoid ambiguity in some cases though, e.g.: RUN export SOME_ARG=hello echo %{arg:SOME_ARG} At the time this was all implemented, the intent was to make these act more "natural"; env-var substitution is a concept known by most Linux users, and has a well-defined syntax; using this syntax made it organically fit into the |
https://docs.docker.com/engine/reference/builder/#environment-replacement ?
I agree and disagree:
Instead of
It'd probably be well readable and understandable for the mentioned 'Linux' audience. The con here is the major breaking change. Dockerfiles don't (they probably should, like docker-compose) have a |
This topic may be quite long, so a bit in doubt if it should be put on that page (which is already lengthy), or instead a separate page (which could be linked from there)
I'm not tied to the syntax (so it's just a rough idea); I did try to avoid using
Yes, we can't make breaking changes, so if this is to be considered, it should be backward compatible (existing ways of handling substitution should continue to work), hence a different syntax for substitutions that are handled when parsing the Dockerfile.
Note that (some years after my initial proposal #4907) Dockerfiles, when using BuildKit, now do support versioning through the # syntax=docker/dockerfile:1.3 When using the
Heh, except the docker-compose spec (https://github.com/compose-spec/) dropped versioning altogether (🙊), but that's another topic |
Steps to reproduce the issue:
In Dockerfile:
and
and
None of these work.
Describe the results you received:
Variable is empty (
CMD ./
).Describe the results you expected:
Variable is used (
CMD ./fish
).The text was updated successfully, but these errors were encountered: