Open profnandaa opened 1 month ago
/cc. @thaJeztah
I think Windows images should define the environment variables in the image config and not rely on the registry. Only variables in the config can be used for variable expansion in Dockerfile, they should take precedence over registry at runtime and ENV
should remain metadata-only command.
What we could do is add some validation routines that would detect if RUN
added a new global environment variable that was not set in image config or allow some functionality to "copy-up" value from registry to config, either at the end of the build or in RUN
. Allowing this does disable lots of buildkit's lazy semantics though because even to just get a config and DefinitionOp
(needed to link builds together for example) the whole build would need to run.
There is also a discussion in #3158 if some of the special cases only apply to PATH
. Reading those responses makes me think if maybe hcsshim
needs a special handling of PATH
instead. E.g. something that would combine the subpaths from the image config with the ones inside the registry before running the container.
@tonistiigi -- thanks for taking a look!
I think Windows images should define the environment variables in the image config and not rely on the registry. Only variables in the config can be used for variable expansion in Dockerfile, they should take precedence over registry at runtime and
ENV
should remain metadata-only command.
We actually considered taking this request to the platform team, but if this is done, it will break the current/classic docker build
experience for RUN setx
. I had highlighted that in https://github.com/moby/buildkit/pull/5446
What we could do is add some validation routines that would detect if
RUN
added a new global environment variable that was not set in image config or allow some functionality to "copy-up" value from registry to config, either at the end of the build or inRUN
. Allowing this does disable lots of buildkit's lazy semantics though because even to just get a config andDefinitionOp
(needed to link builds together for example) the whole build would need to run.
I see, I don't know if this will be right price to pay...
There is also a discussion in #3158 if some of the special cases only apply to
PATH
. Reading those responses makes me think if maybehcsshim
needs a special handling ofPATH
instead. E.g. something that would combine the subpaths from the image config with the ones inside the registry before running the container.
Makes sense to handle $PATH a little different that the rest. I think taking the hcsshim
route sounds like our best bet. I'll be taking up this discussion to the platform team and later bubble up to HCS folks for this consideration.
In the meantime, do you think we could land https://github.com/moby/buildkit/pull/5446 as a stop-gap measure for now?
I believe that registry should not be ignored. If user installs a software that adds itself to PATH, it should Just Work in a container, without any extra steps.
Related to #3158 #4895 #4901
Background
Environment variables are sourced in two different ways on Windows containers:
setx
command. A rough equivalent ofexport
on Unix systems.config.Env
field, which containers entries in the format of VARNAME=VARVALUE; these values act as defaults and are merged with any specified when creating a container. Using dockerfile frontend, this is set usingENV
.For a
mcr.microsoft.com/windows/nanoserver:ltsc2022
for example, and all the other official Windows base images, theconfig.Env
field isnull
. Therefore all the environment variables come from the registry.setx
vs.ENV
on buildkit and classic docker builderWhen there is a name collision between what is set in the config and what is set in the registry with
setx
for example, the one in config takes precedence. For example:Buildkit:
Classic
docker build
:Compare with this one:
Buildkit:
Classic
docker build
:At this point, there is no backward compatibility with classic
docker build
.Windows Installers
Installers on Windows also set environment variables (in the registry). A good example close home, is the Go installer. See example below:
Classic
docker build
:For such case, you want to make sure to set the same environment variables declaratively in the dockerfile, for a consistent build experience across classic
docker build
and buildkit.A case for building windows images from Linux
Buildkit can build windows images from Linux (cross-platform builds), however, with some limitations like you can't execute
RUN
statements. However, others likeCOPY
,ENV
,WORKDIR
are supported. This is sort of an "offline build", since actual Windows containers are not spined up.Actually, this is how Buildkit has been used for building Windows images by the early adopters, before WCOW support came about. See
microsoft/Windows-Containers#493
for example.Here is a simple example dockerfile that will build currently on both Window and Linux:
Building from Linux with
buildx
:Conclusion
A proper conclusion is yet to be made after the discussion. However, my preliminary suggestion is that we prioritize maintaining a uniform experience between building Windows images on Windows vs. building them on Linux. Therefore, I suggest the declarative way of setting environment variables using
ENV
, since they are treated similarly across board.This means leaving everything as-is with a minimal change to fix #4901 (to open PR next, #5446 ) and a clear documentation on how to handle environment variables and advisory to prefer
ENV
oversetx
.