Optimizing Dockerfiles: Effective Use of ARG and ENV

NewsOptimizing Dockerfiles: Effective Use of ARG and ENV

If you’ve been involved with Docker, a popular platform for developing, shipping, and running applications, you likely know the importance of a Dockerfile. Essentially, a Dockerfile serves as a recipe for creating Docker images. It outlines the necessary components, such as base images, software packages, and files, along with the instructions to assemble these elements into a Docker image. Typically, once a Dockerfile is set up, it’s rarely changed unless project requirements evolve. Most developers stick to a few commonly used Dockerfile commands like RUN, COPY, and EXPOSE. However, there are additional commands, such as ARG and ENV, which can significantly enhance the flexibility and manageability of your Docker images.

In this discussion, we will delve into the ARG and ENV instructions, examining their purposes, how they function, and when to use them effectively.

ARG: Defining Build-Time Variables

The ARG instruction in a Dockerfile is used to define variables that are accessible during the build phase but disappear once the image is created. Consider the following example:

dockerfile<br /> FROM ubuntu:latest<br /> ARG THEARG="foo"<br /> RUN echo $THEARG<br /> CMD ["env"]<br />

When you build this Dockerfile, you’ll notice the output includes the line "echo foo":

bash<br /> $ docker build --no-cache -t argtest .<br /> [+] Building 0.4s (6/6) FINISHED<br /> ...<br /> => [2/2] RUN echo foo<br /> ...<br />

However, when you run the image and inspect it using the env command, the variable THEARG does not appear:

bash<br /> $ docker run --rm argtest<br /> PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin<br /> HOSTNAME=d19f59677dcd<br /> HOME=/root<br />

This is because ARG variables are only available during the image build process.

ENV: Defining Build and Runtime Variables

In contrast to ARG, the ENV command allows you to define variables that are accessible during both the build and runtime of a Docker image:

dockerfile<br /> FROM ubuntu:latest<br /> ENV THEENV="bar"<br /> RUN echo $THEENV<br /> CMD ["env"]<br />

Building this Dockerfile produces output that includes "echo bar":

bash<br /> $ docker build -t envtest .<br /> [+] Building 0.8s (7/7) FINISHED<br /> ...<br /> => [2/2] RUN echo bar<br /> ...<br />

Running the image and checking its environment variables confirms the presence of THEENV:

bash<br /> $ docker run --rm envtest<br /> PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin<br /> HOSTNAME=f53f1d9712a9<br /> THEENV=bar<br /> HOME=/root<br />

Overriding ARG

One advanced use of ARG is to specify a placeholder value that can later be updated at build time:

dockerfile<br /> FROM ubuntu:latest<br /> ARG THEARG<br /> RUN echo $THEARG<br /> CMD ["env"]<br />

Without a specified value, the build will output a missing $THEARG value:

bash<br /> $ docker build -t argtest .<br /> ...<br /> => [2/2] RUN echo $THEARG<br /> ...<br />

To specify a value, use the –build-arg flag in the build command:

bash<br /> $ docker build --build-arg THEARG=foo -t argtest .<br /> ...<br /> => [2/2] RUN echo foo<br /> ...<br />

Similarly, Docker Compose can set ARG values using the args key:

yaml<br /> services:<br /> argtest:<br /> build:<br /> context: .<br /> args:<br /> THEARG: foo<br />

When executing docker compose up –build, the output reflects the updated value:

bash<br /> $ docker compose up --build<br /> ...<br /> => [argtest 2/2] RUN echo foo<br /> ...<br />

Overriding ENV

You can override ENV variables during runtime, which differs slightly from ARG. With ENV, you need to provide both a key and a value:

dockerfile<br /> FROM ubuntu:latest<br /> ENV THEENV="default"<br /> RUN echo $THEENV<br /> CMD ["env"]<br />

Building this Dockerfile results in an error if the value is missing:

bash<br /> $ docker build -t envtest .<br /> ...<br /> ERROR: failed to solve: ENV must have two arguments<br />

Instead, specify the value when running the container:

bash<br /> $ docker run --rm -e THEENV=bar envtest<br /> PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin<br /> HOSTNAME=638cf682d61f<br /> THEENV=bar<br /> HOME=/root<br />

The .env file, typically used with Docker Compose, can also be applied here:

bash<br /> $ cat .env<br /> THEENV=bar<br /> <br /> $ docker run --rm --env-file ./.env envtest<br /> PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin<br /> HOSTNAME=59efe1003811<br /> THEENV=bar<br /> HOME=/root<br />

In Docker Compose, use the environment key for setting ENV variables:

yaml<br /> services:<br /> envtest:<br /> build:<br /> context: .<br /> environment:<br /> THEENV: $THEENV<br />

If no value is provided, a warning is displayed:

bash<br /> $ docker compose up --build<br /> WARN[0000] The "THEENV" variable is not set. Defaulting to a blank string.<br /> ...<br />

Values can be specified in several ways:

  1. On the compose command line:

    bash<br /> $ THEENV=bar docker compose up<br /> ...<br /> => [envtest] RUN echo $THEENV<br /> ...<br />

  2. In the shell environment on the host system:

    bash<br /> $ export THEENV=bar<br /> $ docker compose up<br /> ...<br /> => [envtest] RUN echo $THEENV<br /> ...<br />

  3. In a special .env file:

    bash<br /> $ cat .env<br /> THEENV=bar<br /> <br /> $ docker compose up<br /> ...<br /> => [envtest] RUN echo $THEENV<br /> ...<br />

    For direct service runs using docker compose run, the -e flag can override the .env file:

    bash<br /> $ docker compose run -e THEENV=bar envtest<br /> ...<br /> THEENV=bar<br /> ...<br />

    The tl;dr

    In summary, use ARG if you need a variable during the Docker build process but not at runtime. Use ENV for variables needed both at build and runtime, or just at runtime. The decision between ARG and ENV can be guided by a simple flowchart.

    Both ARG and ENV can be dynamically adjusted using command-line arguments in docker run and docker compose, allowing for adaptable workflows and variable management.

    Learn More

    For further exploration of Docker and its capabilities, consider visiting the official Docker documentation at Docker Documentation. This resource provides comprehensive guides and reference materials to deepen your understanding of Docker’s powerful features.

For more Information, Refer to this article.

Neil S
Neil S
Neil is a highly qualified Technical Writer with an M.Sc(IT) degree and an impressive range of IT and Support certifications including MCSE, CCNA, ACA(Adobe Certified Associates), and PG Dip (IT). With over 10 years of hands-on experience as an IT support engineer across Windows, Mac, iOS, and Linux Server platforms, Neil possesses the expertise to create comprehensive and user-friendly documentation that simplifies complex technical concepts for a wide audience.
Watch & Subscribe Our YouTube Channel
YouTube Subscribe Button

Latest From Hawkdive

You May like these Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

This site uses Akismet to reduce spam. Learn how your comment data is processed.