kdocs
GitHub
T&O - Servers
T&O - Servers
  • Gateway
    • API Gateway
    • Kong API Gateway
      • New Project
  • Service Mesh
    • Service Mesh
    • Istio
      • New Project
  • Virtualization
    • Docker
      • Dockerfile
      • Docker Compose
      • Optimizing Images
    • Kubernetes
  • Web Servers
    • Nginx
  • Windows
    • WSL 2
Powered by GitBook
On this page
  • Some best practices
  • Multistage Building
  • Naming Build Stages
  1. Virtualization
  2. Docker

Optimizing Images

PreviousDocker ComposeNextKubernetes

Last updated 6 months ago

Use lighter Base Images

Opt for using alpine based versions of base images, since they are lighter and more tightly controlled versions.

Label you Dockerfile

Use Labels to help organize Images. Like:

LABEL com.example.version="1.0.0-beta"
LABEL com.example.release-date="2024-04-04"

Pinning Image tag versions

Even if you select images by a tag version, it is not garanteed that rebuilding the Image some time later will result in the same Image being made. (Since updates by a publisher on a version tag will change it)

FROM image:3.20

To avoid that and always get the same Image no matter what, pin the image version to a specific digest.

FROM image:3.20@sha256:13b7e62e8df80264dbb747995705a986aa530415763a6c58f84a3ca8af9a5bcd

This way, even if the publisher updates the Image with tag version 3.20, you are still pinned to the specific digest 13b7e62e8df80264dbb747995705a986aa530415763a6c58f84a3ca8af9a5bcd.

Doing this may lock you out of security updates, done by the publisher in their Images.

Use BuildKit instead of Legacy Builder

The Legacy Docker Engine builder processes all stages of a Dockerfile. It will build a stage even if the selected target doesn't depend on that stage.

BuildKit only builds stages that the target depend on.

Exclude with .dockerignore

To exclude files not relevant to the build, without restructuring your source repository, use a .dockerignore file.

Create disposable containers

Create containers that if stopped and destroyed, can easily be recreated with minium setup and configuration.

Decoupled applications

Containers should have only one concern. (Single responsability)

It is when you use multiple FROM instructions in the Dockerfile. Each one can use a different base image, and each one begins a new stage of the build.

The ideia is to then selectively copy artifacts from one stage to another, leaving behind everything you don't want in the final image. (Like temporary files)

Dockerfile
FROM golang:1.23
WORKDIR /src
COPY ./main.go .
RUN go build -o /bin/hello ./main.go

FROM scratch
# You could name the stage if you want
# Otherwise refer to them using their index number (starting from 0)
COPY --from=0 /bin/hello /bin/hello
CMD ["/bin/hello"]

In the final Image, only the binary is copied, so none of the required tools to compile are needed in the final image.

Naming Build Stages

FROM <image> AS <name>

Naming your stages helps on:

  • Debugging your Dockerfile.

  • Allows you to pick specific stages to execute when building.

  • Allows you to create different stages for different environments. (For instance, creating a stage that will populate a Database with mock data, instead of the real data)

Dockerfile
FROM golang:1.23 AS build
WORKDIR /src
COPY ./main.go .
RUN go build -o /bin/hello ./main.go

FROM scratch
COPY --from=build /bin/hello /bin/hello
CMD ["/bin/hello"]

Picking stages when building

docker build --target build -t "your-image-name" .

Using previous stage in FROM

FROM alpine:latest as build
...

FROM build AS optBuild
...

Some best practices
Multistage Building