Docker hub includes many images that are composed of different libraries. These images fulfill the requirement of the used environment. If you cannot use the existing one due to the fact that your application requires a different setup and libraries, then you need to create your custom image. Thankfully, the docker file helps us in defining a custom docker image. This file will be executed by the docker server according to the written commands to initiate the custom docker container.
Docker file will be transferred from the docker client to the docker server which applies all defined commands step by step to create a new container. The structure of a docker file should answer the following questions:
- What is the base image that satisfies the environment requirements?
- What are the additional programs or libraries that are necessary for the application that we want to run in this environment?
- How should we execute the startup command to run the container?
The above figure shows us the structure of a docker file and its execution process. In order to build this file, we call simply “docker build .” command . “.” indicates here the dockerfile path.
As seen in the dockerfile , first a base docker image is selected. This is the image that will contain the file system of the selected operating system. Before selecting this image, it is highly recommended analyzing them and compare your environment requirements and the features of the image to be selected in order to hinder the unnecessary resource usage. FROM command allows us to fetch the base image either from the docker hub or from the docker cache on the computer if it is already available. RUN command says the docker server to execute the command after the RUN command in the container. In our example, the missing libraries or the application is installed. Again, it totally depends on the requirements of our application. Now we have an image that is based on an Ubuntu operating system and the installed applications. The final command CMD is called once the container is started. In this example, the redis-server is started.
How does docker server interpret a dockerfile?
Whenever the docker build command is executed, we see lots of outputs on the terminal that actually explain what is going on under the hood. The execution of the commands in the docker file leads to the generation of new images at each line of this file. In our dockerfile that includes only three-line (FROM, RUN, CMD), three steps are seen in the console.
First the docker server checks whether there is an ubuntu image in the local build cache, if not it will be downloaded from the docker hub. In the second step, docker server creates a container from the previous image and runs the given command inside the container. As soon as the operation such as installing new libraries or configuring the OS environment is completed, the temporarily created container is stopped and the latest file system snapshot is taken to pass as a new image to the next step. This image contains all changes that has been made in the previous step. Note that the image ID what is generated in the previous step is different in the second step, this is also an indicator for us to see the image changes at each step. Each image includes a file system snapshot and startup commands. In the final step, the command is assigned to as a startup command, however, it is not executed. For this step, a temporary container is created, the startup command is placed and generated as a final image. Once the container is started via docker run command, the startup command will be running. In the following figure, the interpretation of the docker file is visualized.
If any change in the dockerfile is done, then from the beginning to the change point, docker server will make use of the cache, since it is already built. After the change point, every item will build once again. If you change the order of the commands in the dockerfile, as the structure of the images differs, the whole file will be built again. Briefly, it matters the position of the change in the docker file to reduce the build time. In the meantime, we see also the approach of the docker to decrease the build time by using the cache mechanism.