Hi,
I tried to build and run this containerfile to test ARG and ENV instructions.
I built the image providing the --build-arg flag for VERSION and BIN_DIR and then ran the container (see image below).
I expected to find the Environment variable of the running container valued this way:
VERSION = 1.16.8 and BIN_DIR = /usr/local/bin/
while, as you can see below VERSION = 5 and BIN_DIR=/www (but these are the values specified in the --build-arg flag). What's wrong in my tests?
Thanks
Hi @AlessandraS
Try build with only one of your --build-arg and you will see a difference. In your case, when you define both --build-args, ENV variables will get thier values from ARG values ( --build-arg ), but not default in ENV instruction.
Good luck
@AlessandraS When you use --build-arg during the build, it actually overrides any default values you set in your ENV ...${VAR:-default} expression. That s exactly how Docker’s build arguments are supposed to work, so this behavior is expected. The default only kicks in when no --build-arg is given or when the ARG is undefined.
@Travis do you want to weigh in here ?
I would say @Chetan_Tiwary_ did an excellent job explaining. Essentially what you are doing with this line
ENV VERSION=${VERSION:-1.16.8} \ BIN_DIR=${BIN_DIR:-/usr/local/bin/}
is setting environment variables. In this instance, you have defaults set of 1.16.8 and /usr/local/bin. However, as part of the build process, you specified build arguments which would override the default values on the environment line and that is exactly what you saw.
Another interesting thing you could do, in addition to what @ARoumiantsev suggested (changing build arguments and only providing one value or providing no values) is to use a "-e" in the podman run command to provide runtime environment variables into the container. Use something that is neither in your Containerfile nor the podman build with arguments and see how that changes things.
The real thing here that might not be clear ...
ARG - provides a user the ability to use build-time arguments as variables for a container allowing custom containers to be built with a single Containerfile just by changing variables.
ENV - provides a user the ability to provide runtime arguments as environment variables customizing the running container but not the container image.
Using both together allows a Container image to be customized at build time, at run time, or a combination of the two so you have the best of both worlds.
Hi @AlessandraS
Try build with only one of your --build-arg and you will see a difference. In your case, when you define both --build-args, ENV variables will get thier values from ARG values ( --build-arg ), but not default in ENV instruction.
Good luck
@AlessandraS When you use --build-arg during the build, it actually overrides any default values you set in your ENV ...${VAR:-default} expression. That s exactly how Docker’s build arguments are supposed to work, so this behavior is expected. The default only kicks in when no --build-arg is given or when the ARG is undefined.
@Travis do you want to weigh in here ?
I would say @Chetan_Tiwary_ did an excellent job explaining. Essentially what you are doing with this line
ENV VERSION=${VERSION:-1.16.8} \ BIN_DIR=${BIN_DIR:-/usr/local/bin/}
is setting environment variables. In this instance, you have defaults set of 1.16.8 and /usr/local/bin. However, as part of the build process, you specified build arguments which would override the default values on the environment line and that is exactly what you saw.
Another interesting thing you could do, in addition to what @ARoumiantsev suggested (changing build arguments and only providing one value or providing no values) is to use a "-e" in the podman run command to provide runtime environment variables into the container. Use something that is neither in your Containerfile nor the podman build with arguments and see how that changes things.
The real thing here that might not be clear ...
ARG - provides a user the ability to use build-time arguments as variables for a container allowing custom containers to be built with a single Containerfile just by changing variables.
ENV - provides a user the ability to provide runtime arguments as environment variables customizing the running container but not the container image.
Using both together allows a Container image to be customized at build time, at run time, or a combination of the two so you have the best of both worlds.
@Chetan_Tiwary_ Did you mean "The default only kicks in when no --build-arg is given and the ARG is undefined" ?
I know you asked @Chetan_Tiwary_ , but I feel I can confidently answer that that is indeed what was meant.
Variables always need defined. So, if you are building a container image and there are ARG variables that aren't defined, it would typically fail because there would be a section that would try to access an undefined variable. The default setting for the "ENV" for building of the image would kick in, and set the values so that the build could continue.
You cannot proceed with building or running a container if there are undefined variables. The book and content the way it is worded might not be quite as clear, but to put things another way ... values must be set and known before you can continue.
I hate to bring this up as an example, but I'm going to anyways ... the MySQL and database containers get built from Container images. Often, users must specify the Database name, User passwords, and other things before the container can run. However, it is possible that if these were pre-built and predefined you could startup a very insecure container because a default known password would be used.
Thanks @Travis @Chetan_Tiwary_ @ARoumiantsev for all your explanations
Red Hat
Learning Community
A collaborative learning environment, enabling open source skill development.