Docker - ARGS and ENV
If you have come here, I hope you know what docker is, and are simply trying to understand the what, why, when, and where of ARGS and ENV.
Before we start
There exist three lifecycle stages we will concern ourselves with here relating to docker.
- Docker image authoring, which is when creating a Dockerfile, or .dockerfile.
- Docker image building, which is when using a Dockerfile, or .dockerfile to build an image.
- Docker container creation, which is when using a docker image to create a container.
You may not have to interact with docker past one or more of these stages. Particularly in large organisations. I Still think it is valuable to get all of this into your head, but be pragmatic and know best, what you need to know.
There are also two stages that Build arguments and Environment variables share
- Definition of ARGS or ENV within a Dockerfile.
- Supply of values for ARGS when image building
- Supply of values for ENV for container creation
Build Arguments (ARGS)
- Build arguments are used to be able to use the same Dockerfile definition when image authoring, to produce multiple docker images when image building.
- There are a variety of reasons to use build arguments, from changing base docker images without editing a Dockerfile definition or engaging in multiple image authoring, reducing the lines of code owned. I have found build arguments best for small, one-line or parametrizable configuration choices. The common thread is that the instructions for image building can be trivially parametrized, when image authoring.
- Build arguments are defined as part of a Dockerfile when image authoring, to provide named placeholders for values, often with a default value so that they can be omitted when image building. The values can be overridden, and may be supplied or cause error if there is no default defined, prior to image building. Build arguments should not be used for secrets, as shipping secrets within images is publicly exposing them.
- I would suggest all docker image building, should only take place in a continuous integration environment. The build arguments will be specified during image authoring, by those who are responsible for specific technologies. As for why I advocate for only building in continuous integration environments; I have worked at places where this did not happen, but I have never worked at a place where image building outside of a continuous integration environment at some stage had not gone on to cause problems later.
Environment variables (ENV)
Environment variables are pieces of configuration that are defined prior to launching a process. They existed long before Docker was conceived or delivered, and exist across Windows, OSx, Linux, BSD and every UNIX I have encountered.
- For Docker, environment variables can be defined when image authoring, and may have defaults, which may be canary values. Values can be supplied at container creation, which override the values defined at image authoring time. Defining environment variables, even if not used, can provide context and configuration information, about the wider system-state to a program, in a way that is flexible to change, standardised, and can be specified per-execution.
- The headline is flexibility, comprehension, security and speed. Where the environment declaration happens, conveys different meanings. Specifying within a Dockerfile when image authoring, can convey defaults, which may be canary values, or simply documentation of the environmental configuration and format supported by an image or container. Specifying when running via docker-compose, Kubernetes or command-line is saying that you would like to configure the container creation in a specific way providing flexibility for images you have. You may have 4 databases you can reach and use the same code to reach both of them. This means that instead of 4 specific images making 4 containers, you can ship one, lowering bandwidth needed and time to deploy, while providing flexibility for rapid change. Because the images will not have security credentials they can be shared without concern that they represent additional risk and changing secrets does not require re-deployment.
- In contrast to build arguments, environment variables can and should be used for both secrets and configuration at container creation, and configuration only during image authoring for specifying defaults and canary values.
- For docker image authoring you can declare Environment variables within a Dockerfile. Other configuration formats do exist, such as the docker-compose.yml, Kubernetes yaml files, and many more, but these are for container creation prior to runtime, and will be roughly synonymous to executing the docker run command, when supplying environment variable values.
I Hope this has helped you.