- To launch a container, we must either download a public image or create your own.
- The docker image can be considered as a single asset that mainly represents the filesystem for the container.
- Docker images are built up from individual layers. Each layer puts a special demands on the Linux kernel
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="email@example.com" LABEL "maintainer"=$email
Let understand the above file line by line.
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.
This line defines an argument (a variable) in the Dockerfile. This variable can be specified by the user while running the container.
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.
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.
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
docker image buildis functionally the same as using
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.
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
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.
- The first step required to push the image is to ensure that you are logged in to the Docker repository you intend to use.
First we need to change the tag of the image that we have build. We need to add the host name
docker image tag vickysharma0812/fortran-hello-world-alpine:latest \ docker.io/vickysharma0812/fortran-hello-world-alpine:latest
vickysharma0812 is my account name on
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.
┃ ● Layers ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Cmp Size Command 7.7 MB FROM de8b86e33ae69ac 172 MB RUN |1 firstname.lastname@example.org /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@example.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