Open In App

How To Use Dockerfile Best Practices for Efficient Image Building?

Last Updated : 16 Jul, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Docker is an open-source platform that enables developers to build, distribute, operate, update, and manage containers.

What is Dockerfile?

  • A Dockerfile is just a text file that contains all the commands that must be executed to create a Docker image. The Docker images can then be uploaded to places like DockerHub for either public usage or private usage.
  • It is used to automate the process of creating a Docker image from a source code or pre-compiled binary.
  • Dockerfile is similar to the Makefile which is used in C that contains all the commands which need to run to run the application.

A simple example of a Dockerfile could be this:

FROM registry.aws.site.com:443

RUN microdnf install wget

RUN wget -c project-with-dependencies.jar

COPY ./package.json

RUN npm install

RUN npm run build

This dockerfile will execute all the steps mentioned in the file and will eventually run the npm application. To better understand the file, we should know the Dockerfile commands i.e., FROM, RUN, CMD, COPY, etc.

Explaining them with respect to this example:

  • The first line usually uses the FROM command. It is basically used to form the first layer for the container which means it uses that as the base image for the container to run something.
  • The RUN command is basically running some Linux command – whatever comes after “RUN” is the Linux command that needs to run on the container. This is mostly used to install some packages and use it. In this case, it is used to install wget and then run a wget command to download the jar in the container. And then it is also used to run the npm commands.
  • COPY command as the name suggests copies the folders and files to the container so that it can be accessed from the container directly. Here we copy the package.json file from the current directory to the container.

Best Practices For Efficient Image Building

Some of the best practices for creating a Dockerfile which optimizes image building and increases efficiency are as follows:

  • Using smaller size official images: Using larger size images can lead to longer building time for the containers. It is therefore advised to utilize leaner OS releases with smaller images that just contain the essential system tools and libraries to reduce the attack surface and provide more secure images.
  • Using the right privileged user: The root user will be used by default if the user isn’t specified in the Dockerfile, which poses a significant security concern as your application doesn’t typically require a root user. Simply add the USER directive to the Dockerfile to utilize that user to run the program to avoid this by creating a dedicated user and a dedicated group.
  • Using Multi-Stage Builds: This enables us to have reproducible builds inside the container. The basic idea is to separate the build stage from the runtime stage.
  • Decoupling applications: Each container should only do one thing. It is simpler to scale horizontally and reuse containers when applications are decoupled into several containers.
  • Scanning for Security Vulnerabilities: By running the docker scan command we can scan our images for security vulnerabilities and make it safer.
  • Reducing the number of layers: The order of instructions in a Dockerfile plays a very important role. Grouping several commands together will decrease the number of levels because RUN, COPY, ADD, and other instructions will add a new container layer.
  • Updating images frequently: It is a general security best practice to use the most recent security updates because new security flaws are continually being found. Don’t use the latest version since it might not be stable but use the latest stable version.
  • Avoid unnecessary packages: Refrain from installing unnecessary packages just because they might seem good to have. It will result in an image having less complexity and reduced dependencies.
  • Do not expose secrets: Do not add credentials or secrets in the Dockerfile. Add it to the .dockerignore file instead, for using sensitive information.

 Examples of Best Practices In Action

A multi-stage build that uses a lightweight base image: to build a production-ready image. To utilize multi-stage builds, we can use numerous FROM statements in our Dockerfile. Each FROM command can start a new stage of the build and therefore will use a different base. This also helps to handle multiple environments like dev, QA, UAT, and PROD. An example of the same could be this:

FROM golang:alpine AS dev
COPY --from=dev /binary/bin

FROM golang:alpine AS uat
COPY --from=uat /binary/bin

FROM golang:alpine AS prod
COPY --from=prod /binary/bin
RUN go test

A lightweight base image that is optimized for production use: Using a lightweight base image can help reduce the size of the image and container to a lot of extents (even 90% sometimes). This could be achieved by using specific images and not the original ones like using an alpine-based image instead of the original.

Using this:
FROM golang:alpine
Instead of this:
FROM golang

A caching strategy: that uses a Dockerfile to cache dependencies and speed up the build process. To understand the importance of caching, we can look at it this way – all the Dockerfile commands create a new layer in the image. Suppose we change something in any command, that in turn affects that layer and it needs to rebuild. And whichever layer rebuilds, all the layers below it also need to rebuild whether or not something changed for them. To optimize this, we use a caching strategy.

1. Using smaller layers that do not include any unnecessary files and trying to combine the RUN command in whatever ways possible.

Instead of this:
RUN microdnf install wget
RUN wget -c project-with-dependencies.jar
Use this:
RUN microdnf install wget && wget -c project-with-dependencies.jar

2. Ordering the layers properly so as to not include anything later which is not affected by the initial commands.

3. Using multistage builds like those mentioned above also helps here.

Conclusion

In conclusion, we have seen what a Dockerfile is, how we use it, and what advantages we get by using it. We then saw some of the best practices that should be followed while using the Dockerfile to have efficient image building.

By following these best practices, you can build efficient Docker images that are smaller, faster, and more secure.

We should be able to use its functionality in an optimum way by following good practices. This could also be achieved by going through some official Dockerfiles and understanding them.



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads