Skip to content
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

Official expected behavior about default ENV variables set in images and listed in docker-compose manifest #11962

Closed
remiville opened this issue Jul 3, 2024 · 6 comments · Fixed by compose-spec/compose-go#654
Labels

Comments

@remiville
Copy link

Description

I found an important difference in docker-compose behavior regarding default variables set in images, since v2.24.7.

Knowing that we have an image containing a variable "VAR" with a default value "default", the Dockerfile specifies:
ENV VAR "default"

If the environment section of the docker-compose manifest specifies a variable "VAR" (without value):

  • Before v2.24.7: the variable is unset from the container (the "default" value is lost)
  • Since v2.24.7: the variable with its default value is kept in the container

Regardless of the version, if the environment section of the docker-compose manifest specifies "VAR=" (with the equal sign and no value), the variable is set as empty in the container.

This difference in behavior is important because:

  • If you deploy your images with docker-compose or another orchestrator you want your default variables being defined in images (not in .env or docker-compose manifest).
  • If you want to override one of these variables just by setting it in .env or in the execution context (export VAR=...) you need to specify it in the environment section of the docker-compose manifest, if not the variable will not be passed to the container.

For me the behavior since v2.24.7 is the good one, but it doesn't appear in changelog, I don't even not know which issue or commit changed this, it's maybe just a side effect.

Can you confirm this behavior introduced by v2.24.7 is the expected one and can you add it to the official documentation ?
If a unit test could ensure this behavior will not be lost it would be great.

@ndeloof
Copy link
Contributor

ndeloof commented Jul 4, 2024

That's indeed a bug.

@remiville
Copy link
Author

Hi @ndeloof,

Just to be clear you moved this issue from feature to bug, but the new behavior introduced by v2.24.7 is good for me.
I mostly just like to be sure if it is intentional and if it will be kept in the future.

@ndeloof
Copy link
Contributor

ndeloof commented Jul 4, 2024

This behavior is inconsistent with docker run, so I consider this to be a bug that has to be fixed

@remiville
Copy link
Author

remiville commented Jul 5, 2024

Is there a chance to consider it as an unintentional improvement ? 😆

What do you mean exactly about the inconsistency with docker run ?
Effectively docker run -i -e TEST test_img sh -c 'echo $TEST'
returns nothing (here test_img is built using this Dockerfile:

FROM alpine
ENV TEST "default"

)
It seems logical, because explicitly setting -e TEST has no use, except for removing the "default" value.

But in a docker-compose manifest, this is different because if it contains:

    environment:
      - TEST

The utility of doing that is not necessarily to unset the TEST variable, but just passing its value to the container if the TEST variable is set in .env, any other env_file or in the execution context.

Even since v2.24.7 if you want to unset the variable you can do this explicitly with:

    environment:
      - TEST=

I'm little disappointed if the new behavior is removed, because it makes the definition of default values inside images more complicated (for example to define default values in images, to be used both by docker-compose and k8s).

If the new behavior is considered as a regression and reverted, would it be possible to have a new mark ? for example:

    environment:
      - TEST?

and/or:

    environment:
      - TEST?=${SOME_VAR}

To be able to define a variable to be passed to the container, but not unset it if not defined (and/or if ${SOME_VAR} is empty) ?

@ShadowLNC
Copy link

ShadowLNC commented Jul 5, 2024

I think this is the same as #11740 (or similar issue with unsetting variables and precedence order)

@ndeloof
Copy link
Contributor

ndeloof commented Jul 5, 2024

docker run -e TEST is not designed to unset TEST variable, but to propagate value from user's environment. If TEST is defined by user, container will get the same value, otherwise variable is removed from container's environment.
As most compose attributes, environment is just a 1:1 mapping with docker run .. command line flags, so the need to be consistent.

would it be possible to have a new mark

could be an option, but would be better the same behavior is available with the docker CLI for consistency.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants