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.
How To Use Dockerfile Best Practices for Efficient Image Building?
Docker is an open-source platform that enables developers to build, distribute, operate, update, and manage containers.