Dockerfile is simpler than you think

Tram Ho


Docker must be no stranger to our dev brothers. The idea of ​​Docker is to create containers that contain independent environments to launch and develop the application, in simple terms, it contains everything that the application can run. And to create those containers, we need a Docker image. Creating Docker container from Docker image is similar to installing win from ghost file, extracting ghost file has everything you need. So how to create a Docker image? ye, that’s Dockerfile writing and this is what I want to mention in this article ?

Dockerfile is the heart of Docker. It defines what the image details include so that Docker can determine how to build the image. Dockerfile is actually a text file called Dockerfile, without extensions. It contains the necessary commands in order to build an image (the commands will be executed from the top down). To better understand Dockerfile, we will go to the next section, the basic components of Dockerfile

The basic components of Dockerfile

In the official document on the Docker homepage, the Dockerfile will include the following commands:

FROM – specify base image. The base image will usually be taken from Docker Hub – the place to store and share images from which you can get and customize.

RUN – used to execute any command during image build, usually it is used to build packages in image

CMD – used to execute any command during container run. CMD will not execute anything during the build image process and each Dockerfile contains only one CMD command

LABEL – used to provide metadata for images, a good place to store author information, notes …

EXPOSE – set the port to access the container after it has been launched

ENV – set environment variables to use for building statements

ADD and COPY – copy files and folders to containers

ENTRYPOINT – provides some default commands with parameters when executing containers

VOLUME – create a folder to access and store data, linked folders from the host machine and container

USER – specifies the username or UID used during image creation for RUN , CMD and ENTRYPOINT commands

WORKDIR – Set up a working directory in the container for the commands COPY , ADD , RUN , CMD , and ENTRYPOINT

ARG – Defines variables for use in build-time.

ONBUILD – create a trigger for the image to execute when it is used as the base image for building another image

STOPSIGNAL – specify the system symbol used to stop containers.

HEALTHCHECK – provides a method for Docker to check if the container is functioning properly.

SHELL – used to change the default shell commands

Regarding the definition and usage of each command, you can see here ( English version ). I will not write a definition for each command because someone already has it. Besides, it will make the article too long and really because I feel it is not really necessary.

The components that need the most attention and are most used are: FROM , WORKDIR , RUN , COPY (as well as ADD ), EXPOSE , ENTRYPOINT and HEALTHCHECK . Why not pay attention to VOLUME ? Mounting the directory is also important. The reason is because we can completely install it in the docker compose. I often do that to agree on the folder setting. The discrete sering in each Dockerfile, when it is needed to find or have errors, opening each file is also a problem.

With these commands, we need to pay attention to a very important detail that is the command to create a layer and which command does not. Wait, what is a layer? I don’t see any paragraphs talking about this. yeah here it is, I will mention right after this what the layer is. For some of you who know, I’d like to remind you that the process of building a container from an image will be based on a series of layers. These layers are, of course, made up of Dockerfile commands. The Dockerfile itself will define Docker for those layers and the order in which they will be created. And the thing to note here is that Docker has a layer caching mechanism so that there is no need to redo the layer if it does not change from the previous build. This is very important and one of the first basics when performing Docker optimization. The commands that will create layers during the build process are: RUN , COPY and ADD . You may not be able to see how this layer was created when docker builds. For example, with a Dockerfile create a web app using nodejs

When making the build it will look like this

Where are the layers located in this heap? Then at the end of each step you will see a line like this ---> 530c750a346e that is the layer created at that step with a random ID. So every step creates a layer, it’s not RUN , COPY and ADD . Then I will explain. We issue a history command to see all the layers created.

In the IMAGE column, you can see that it lists all the ID layers created at each step but pay attention to the SIZE section. Have you seen the difference yet. The command to create layers is size> 0 and in principle when building an image, if there is a change from the previous layer, a new layer will be created and with commands of size> 0 it changes the current layer so it is possible. Of course it will create a new layer.

How to write Dockerfile

After getting to know the Dockerfile components, the next thing is how to write Dockerfile from those components. Referring to the above example, we can configure the structure of a Dockerfile which will consist of the following main parts:

  • FROM: define base image. The first command of any Dockerfile.
  • Set workdir: specify the working directory to copy source and install applications, for example. This is essential for separating applications from each other
  • Install the application: After you have the source code, it must be run build and start application, right
  • Customizing the configuration: This is the final step to finalize what you will publicize with the container created from the image defined with Dockerfile. Which port is, which command to run. This is where you will use commands like EXPOSE , CMD or ENTRYPOINT . And one thing to note is that don’t forget HEALTHCHECK for some important containers.

Note when writing Dockerfile, you should also set .dockerignore to remove unnecessary files from the build process. This helps you not to rebuild the image when there are minor changes such as updating

Add an example to write in the structure above for you to use

In the above example, I have used multi-stage build to optimize the build image process. You can refer to this article for more ways to tweak Dockerfile or refer to best practices from the docker homepage.

How to use Dockerfile

Dockerfile is used to build images but nothing more. To build the image we execute the following command:

Usually we execute this command right in the folder containing Dockerfile so about PATH or URL , I usually do not recommend using it. In my opinion for the docker build, we should only care about the -t (or --tag ) option to assign names and tags to the image. Eg:

docker build -t demoapp:latest

The above command will build the image with the name demoapp and the tag is latest . Note format is name:tag offline. After building the image, we perform the docker run to start the container from that image. Easy right? Doc for docker build and docker run

You can also use Dockerfile in the docker compose, where to gather individual Dockerfiles so that they run together. Such as:

The Dockerfile will be executed when running the docker-compose build or docker-compose up with the --build option (make the image build before starting the container). I plan to write one more post about the docker compose after doing more research, but now the program is still buzzing so I don’t dare to fear writing. ?


Dockerfile is a key component, the heart of docker so hopefully through this article, you have a better view of Dockerfile and more confidence when you start working with it. If you have any questions or comments, please leave a comment. If you find it interesting, I will synthesize and put it into serial questions about my docker. Many thanks for taking the time to read this article. Cheers.

Well below I would like to take a note of some good articles about Dockerfile that I have referenced when writing this article. It is worth reading.

Part 2 – Dockerfile in serial Docker: Unknown to the author of Hoan Ky: link

Docker image in production – a 1GB or 100MB story by Minh Momen: link


Share the news now

Source : Viblo