Docker Images

Share the page with

Anatomy of a Dockerfile

A typical Docker image running the node application looks like the following.

FROM alpine:3.18
USER root
ENV EASIFEM_BUILD_DIR /easifem/build
ENV EASIFEM_SOURCE_DIR /easifem/src
ENV EASIFEM_INSTALL_DIR /easifem/install
ENV EASIFEM_TEST_DIR /easifem/tests

RUN apk update && apk add --no-cache gfortran musl-dev

COPY ./tests/* $EASIFEM_TEST_DIR/

WORKDIR $EASIFEM_TEST_DIR

RUN gfortran -o main.out main.F90 && ./main.out

ARG email="vickysharma0812@gmail.com"
LABEL "maintainer"=$email

Let understand the above file line by line.

FROM alpine:3.18

This line indicates the base image for our image. In this case it is Alpine linux version3.18. You can read about this project here.

Alpine Linux is a Linux distribution built around musl libc and BusyBox. The image is only 5 MB in size and has access to a package repository that is much more complete than other BusyBox based images. This makes Alpine Linux a great image base for utilities and even production applications. Read more about Alpine Linux here and you can see how their mantra fits in right at home with Docker images.

ARG email="vickysharma0812@gmail.com"

This line defines an argument (a variable) in the Dockerfile. This variable can be specified by the user while running the container.

LABEL "maintainer"=$email

This line defines a label for the image that we are building.

Applying labels to images and containers allows us to add metadata via key/value pairs that can later be used to search for and identify Docker images and containers.

USER root

By default, Docker runs all processes as root within the container, the above line describes the USER.

Even though containers provide some isolation from the underlying operating system, they still run on the host kernel. Due to potential security risks, production containers should almost always be run in the context of an unprivileged user.

ENV EASIFEM_BUILD_DIR /easifem/build
ENV EASIFEM_SOURCE_DIR /easifem/src
ENV EASIFEM_INSTALL_DIR /easifem/install
ENV EASIFEM_TEST_DIR /easifem/tests

The above lines define the shell environment variables.

RUN apk update && apk add --no-cache gfortran musl-dev

The above lines run the commands. Here, it is worth remembering that every instruction creates a new Docker image layer, so it often makes sense to combine a few logically grouped commands onto a single line.

COPY ./tests/* $EASIFEM_TEST_DIR/

This command moves the file from the tests directory of host to /easifem/tests/ directory of the image.

WORKDIR $EASIFEM_TEST_DIR

With the WORKDIR instruction, we can change the working directory in the image for the remaining build instructions.

The order of commands in a Dockerfile can have a very significant impact on ongoing build times. You should try to order commands so that things that change between every single build are closer to the bottom. This means that adding your code and similar steps should be held off until the end. When you rebuild an image, every single layer after the first introduced change will need to be rebuilt.

Building an image

Before we build the image, we need to add .dockerignore file to the same location as Dockerfile. Add following entries to it.

.git
*.out
*.o
build
*/build/*

To build the image run the following command:

docker image build -t  vickysharma0812/fortran-hello-world-alpine:latest

Using docker image build is functionally the same as using docker build.

To improve the speed of builds, Docker will use a local cache when it thinks it is safe. This can sometimes lead to unexpected issues because it doesn’t always notice that something changed in a lower layer. You can disable the cache for a build by using the --no-cache argument to the docker image build command.

Each step identified in the following output maps directly to a line in the Dockerfile, and each step creates a new image layer based on the previous step. The first build that you run will take a few minutes because you have to download the base node image. Subsequent builds should be much faster unless a new version of our base image tag has been released.

Running Image

We run the above image by using following command.

docker container run --rm -d vickysharma0812/fortran-hello-world-alpine:latest

Setting environment variables

While running the container, we can set the environment variables by using --env or -e flag.

docker container run --rm -d \
--env EASIFEM_SOURCE_DIR=/easifem/source/ \
vickysharma0812/fortran-hello-world-alpine:latest

Storing images on Dockerhub

Create account at Docker hub.

First we need to change the tag of the image that we have build. We need to add the host name docker.io.

docker image tag vickysharma0812/fortran-hello-world-alpine:latest \
    docker.io/vickysharma0812/fortran-hello-world-alpine:latest

Here vickysharma0812 is my account name on hub.docker.com.

Now we push this image to docker cloud.

docker image push vickysharma0812/fortran-hello-world-alpine:latest

After that anyone who has access to internet can pull out image and run the containers.

docker image pull vickysharma0812/fortran-hello-world-alpine:latest

Getting info on build images

We can dive into the build images by using dive and using following command.

dive vickysharma0812/fortran-hello-world-alpine:latest
┃ ● Layers ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 
Cmp   Size  Command                                                                                 
    7.7 MB  FROM de8b86e33ae69ac                                                                    
    172 MB  RUN |1 email=vickysharma0812@gmail.com /bin/sh -c apk update && apk add --no-cache gfor 
      71 B  COPY ./tests/* /easifem/tests/ # buildkit                                               
       0 B  WORKDIR /easifem/tests                                                                  
     73 kB  RUN |1 email=vickysharma0812@gmail.com /bin/sh -c gfortran -o main.out main.F90 && ./ma 
                                                                                        
Image name: vickysharma0812/fortran-hello-world-alpine:latest                                       
Total Image size: 179 MB                                                                           
Potential wasted space: 1.5 MB                                                                     
Image efficiency score: 99 %                                                                       
                                                                                                    
Count   Total Space  Path                                                                           
    2        1.3 MB  /lib/ld-musl-aarch64.so.1                                                      
    2         94 kB  /lib/apk/db/installed                                                          
    2         68 kB  /usr/bin/strings                                                               
    2         22 kB  /lib/apk/db/scripts.tar                                                        
    2         152 B  /lib/apk/db/triggers

As you can see, most of the space in our image is taken by gfortran and gcc compilers.

Share the page with