How to build a Docker image?
Running the docker build command will build a Docker image based on the instructions defined in Dockerfile. Dockerfile will contain the command lines arranged by the user to form a Docker image. Example of a Dockerfile:
COPY . /app
RUN make /app
CMD python /app/app.py
Each command in this file represents a separate class in the Docker image. Here is a brief explanation of each command:
- FROM creates a class from ubuntu: 18.04 Docker image
- COPY adds the file from the Docker client’s current directory
- RUN builds your application
- CMD specifies which commands will run in the container These four commands will create classes in the Docker image when they are executed.
Optimizing the image build process
Now that we’ve covered the Docker creation process a bit, I’d like to share some optimization tips to help build images effectively.
The image defined by your Dockerfile will create temporary containers. Temporary containers mean containers can be stopped and destroyed, then rebuilt and replaced with a newly created container, using absolute minimal setup and configuration. Temporary containers may be considered disposable. All versions are new and not related to earlier container versions. When building Docker images, you should make use of as many temporary containers as possible.
Do not install unnecessary packages
Avoid installing unnecessary files and packages. The docker image should be as thin as possible. This results in portability, shorter build times, reduced complexity and smaller file sizes. For example, installing a text editor into a container is not required in most cases. Do not install any unnecessary apps or services.
Deploy .dockerignore files
The .dockerignore file excludes the files and folders that you have declared inside it. This avoids unnecessarily large or sensitive files and folders to the daemon and potentially adding them to the public image. To exclude files that are not related to the build use the .dockerignore file. This file has the same support as the .gitignore file.
Arrange the arguments in multiple lines
Whenever possible, ease future changes by arranging the multi-line arguments alphanumeric. This helps avoid duplication of packages and makes the list of updates much easier. This also makes it much easier to read and review. Adding a space before the backslash
Here’s an example from Docker’s buildpack-deps on Docker Hub:
RUN apt-get update && apt-get install -y
&& rm -rf /var/lib/apt/lists/*
Split the apps
In some cases, applications depend on other applications, they are hosted on the same server or computer. This is common in container deployments, but for small services, each application should exist in its container. Splitting applications into multiple containers makes it easy to horizontally scale and reuse containers. For example, a discrete web application stack could consist of three separate containers, the container with its own unique image: one for managing the web application, one for managing databases, and one for caching in memory. . Then, if the containers are dependent on each other, you can use the network to make sure the containers can communicate.
Minimize the number of layers
Only the RUN, COPY, and ADD commands create classes. Other commands create a temporary and final intermediate image that doesn’t increase the size of the build. If possible, just copy everything you need into the final image. This allows you to include tools and / or debugging during your build phase without increasing the size of the final image.
Make use of the cache
In building the image, Docker follows the instructions in your Dockerfile, executing each in order. At each tutorial, Docker looks for an existing image in its cache to use instead of creating a new duplicate image. Here is the basic rule that Docker follows:
Starting with the cached parent image, the next command is compared with all the child images derived from that base image to see if one of them was created using the same command. . If not, the cache is disabled.
In most cases, simply comparing the commands in Dockerfile with one of the child images is sufficient. For ADD and COPY commands, the content of the file (s) in the image is checked and the checksum is computed for each file. Last modified and last hit of the file (s) are not considered in these checksums. During the cache lookup, the checksum is compared with the checksum in the existing images. If anything has changed in the file (s), such as the content and metadata, the cache will be disabled.
In addition to the ADD and COPY commands, the cache check does not look at the files in the container to determine a cache match. For example, when processing the RUN apt-get -y update command, files updated in the container will not be checked to determine if a cache hit exists. In that case, the command sequence is used to find the match.
When the cache is invalidated, all subsequent Dockerfile commands create a new image and the cache is not used. Making use of your cache involves classifying your image so that only classes change frequently. You want your RUN steps to change more often towards the bottom of the Dockerfile, while steps that change less frequently should be arranged in order at the top.