[feature request] support setting build-time environment variables
As developers of a CI system that uses buildah for building (https://konflux-ci.dev/), we have a need to dynamically set environment variables at build time (for the RUN instructions in a Containerfile).[^1]
We didn't find any great way to achieve that at present. The options we considered:
--build-arg- Requires the
ARGs to be defined up-front in the Containerfile (or requires modifying the Container dynamically to inject them) ARGs have a lower precedence thanENV. The Containerfile or the parent image may already be setting the variable viaENV=> we're not able to override it
- Requires the
--env- Sets the environment variable in the image config, which we want to avoid. We want to set the environment variables only at build time
- Inject a
.envshell script into the build using--volume. Dynamically modify theRUNinstructions in the Containerfile tosourcethis shell script before doing the rest of the command(s)- This is the option we currently use, despite the problems
- Modifying the RUN instructions is error-prone. We don't even support all the possible forms (e.g. exec form and heredoc form - related issue)
- Some users are uncomfortable with having their Containerfile dynamically modified
It would be awesome if we could set build-time environment variables more easily. Some options that could work:
- Buildah currently supports the
envarray from the engine table in containers.conf. Would it be reasonable to supportenvfrom the containers table as well and use these for theRUNenvironment?- Or, would it be reasonable for the
[engine.env]variables to propagate toRUNinstructions?
- Or, would it be reasonable for the
- A new
--build-envCLI option forbuildah buildthat would set environment variables forRUNinstructions but wouldn't set them on the resulting image config.
[^1]: For example, we set GOMODCACHE to a pre-populated cache directory that we mount into the build using --volume. We do a similar thing for Python builds - pointing pip to a directory instead of an index server using PIP_FIND_LINKS.
One hack which can be done is dump all the env into a file in contextdir and use
RUN --mount=type=bind,src=myfile.sh,target=myfile.sh,Z source myfile.sh <do other operation>
@chmeliik Any thoughts ?
One hack which can be done is dump all the
envinto a file incontextdirand useRUN --mount=type=bind,src=myfile.sh,target=myfile.sh,Z source myfile.sh <do other operation>@chmeliik Any thoughts ?
That's pretty much what we currently do
Inject a
.envshell script into the build using--volume. Dynamically modify theRUNinstructions ...
With the downsides mentioned in the issue description.
For more context: we don't own the Containerfiles we build. A user supplies the Containerfile, and we'd like the ability to set build-time environment variables without having to modify their Containerfile.
--env Sets the environment variable in the image config, which we want to avoid. We want to set the environment variables only at build time
Yeah, though one could also edit the generated config to remove them after today.
A new --build-env CLI option for buildah build that would set environment variables for RUN instructions but wouldn't set them on the resulting image config.
Makes sense to me, although
Some users are uncomfortable with having their Containerfile dynamically modified
Right that's the thing, today cachi2 basically breaks the ability to replicate what happens in a pipeline with podman build, and if e.g. we also supported an ARG CACHI2_WHATEVER that the container owner would take responsibility to handle, that would seem like a clean option too.
Yeah, though one could also edit the generated config to remove them after today.
We'd also need to take care not to unset environment variables that a user explicitly sets in their Containerfile, let's say
FROM registry.fedoraproject.org/fedora-minimal:41
ENV GOMODCACHE=/tmp/gomodcache
We would end up running something like buildah build --env GOMODCACHE=/cachi2/output/deps/gomod -f Containerfile. It seems that the ENV in the Containerfile takes precedence in this case, which is probably good. It breaks the cachi2 integration, but that might be fine. The Containerfile owner can fix that by moving the ENV below all the relevant RUN instructions (that might feel weird though). We would just have to make sure not to unset variables if their value is different from what we thought we were setting.
But it is a bit of unpleasant added complexity.
if e.g. we also supported an ARG CACHI2_WHATEVER that the container owner would take responsibility to handle, that would seem like a clean option too.
The existence of a --build-env option would make this unnecessary in my opinion. But if adding it is not acceptable, this could be an OK-ish fallback
the ENV in the Containerfile takes precedence
This reminds me - the potential --build-env variables would need to take precedence over --env/ENV
The Containerfile owner can fix that by moving the ENV below all the relevant RUN instructions
That said shouldn't basically every build be done via multi-stage? For everything except dnf installs that covers this problem I'd say as the ENV should only be transient to the builder phase. I think we could make cachi2/dnf work in a multi-stage flow too, but it would be supremely ugly like
FROM ubi as builder
ENV cachi2=blah # or whatever
RUN dnf download foo bar baz
FROM ubi
RUN --mount=from=builder,target=/builder dnf -y install /builder/*.rpm
That said shouldn't basically every build be done via multi-stage? For everything except dnf installs that covers this problem
I think most Python apps also wouldn't be built multi-stage (could be, but people aren't used to it).
But I don't really care how our users build their Containers, I'm looking for an easy solution that would cover the most use cases
As described, this would intentionally not leave a trace in the built image's config, meaning it could not be accounted for by the cache evaluation logic.
As described, this would intentionally not leave a trace in the built image's config, meaning it could not be accounted for by the cache evaluation logic.
Ah, so it would have to imply --no-cache (or require that the user also specify --no-cache explicitly). That would work for us
A friendly reminder that this issue had no activity for 30 days.
Would this be a reasonable feature to have, or do the caching concerns disqualify it?
A friendly reminder that this issue had no activity for 30 days.
We would still be interested in having this