In a previous post, I explained how we made our Ubuntu image 15 times smaller by chiselling a specific slice of Ubuntu for .NET developers. In this blog, I will provide step-by-step instructions on customising your chiselled Ubuntu base images for any use case.

  • Chiselled Ubuntu containers combine Distroless and Ubuntu to create smaller, more secure containers.
  • The reduced size of the containers reduces the overall attack surface. Combined with the support and content quality from the Ubuntu distribution, chiselled Ubuntu is a significant security improvement.
  • Chisel provides a developer-friendly CLI to install slices of packages from the upstream Ubuntu distribution onto container filesystems.
That’s what chiselled Ubuntu containers could look like… well, if you ask the DALL-E2 AI.

I don’t believe in a perfect container base image anymore. I remember thinking that Google’s Distroless base was pretty close, but it turned out that the most perfect base image would in fact be FROM scratch:  only exactly what you need and installed from a popular, well-maintained and supported Linux distribution. Here’s how you can build your own.

Step 1: Build Chisel with Docker

To build chiselled Ubuntu images, you first need a chisel. The chisel package slicing tool used to craft chiselled Ubuntu base images is a Go application that currently doesn’t provide pre-built releases. Therefore, you’ll need to build it using the Golang SDK.

I provided a 20-line Dockerfile that shows how to build Chisel and package it as a container image using Docker, the Go SDK and Chisel itself! Once built, the output will be a less than 16MB chiselled Ubuntu-based chisel image, which is excellent proof of the effectiveness of chiselled Ubuntu images. The final chisel OCI image contains a custom chiselled Ubuntu base (mostly Glibc and CA certificates) and the Go-compiled Chisel tool, ready to be used in our future container builds.

Step 2: DIY chiselled Ubuntu

To create your own chiselled Ubuntu base image, you will start with a FROM scratch base image and add the necessary chiselled Ubuntu bits from your selected package dependencies.

Inspired by Google’s Distroless base image, for this example, I chose the following package slices from the Ubuntu distribution: base-files_base, base-files_release-info, ca-certificates_data, and libc6_libs.

To do this, use the following 5-instruction Dockerfile:

# chiselled-base.dockerfile # "chisel:22.04" is our previous "chisel" image from Step 1
# we built and tagged it locally using the Docker CLI
FROM chisel:22.04 as installer WORKDIR /staging
# Use chisel to cut out the necessary package slices from the
# chisel:22.04 image and store them in the /staging directory
RUN ["chisel", "cut", "--root", "/staging", \ "base-files_base", \ "base-files_release-info", \ "ca-certificates_data", \ "libc6_libs" ] # Start with a scratch image as the base for our chiselled Ubuntu base image
FROM scratch
# Copy the package slices from the installer image
# to the / directory of our chiselled Ubuntu base image
COPY --from=installer [ "/staging/", "/" ]

Once you have created this Dockerfile, you can build your new chiselled Ubuntu image using the command: docker build . -t chiselled-base:22.04 -f chiselled-base.dockerfile

Your custom chiselled Ubuntu base image should be around 5MB and is ready to run many C/C++, Golang, or other dynamically linked self-contained programs. You can test it using the provided sample Dockerfile that layers a C program on top of your new base image.

Step 3: Add SSL support for your base image

If your application requires SSL support, you can easily add it to your chiselled Ubuntu base image by adding the following 30 characters to your previous Dockerfile:

# chiselled-ssl-base.dockerfile # "chisel:22.04" is our previous "chisel" image from Step 1
# we built and tagged it locally using the Docker CLI
FROM chisel:22.04 as installer
WORKDIR /staging
RUN ["chisel", "cut", "--root", "/staging", \ "base-files_base", \ "base-files_release-info", \ "ca-certificates_data", \ "libc6_libs", \ "libssl3_libs", \ "openssl_config" ] FROM scratch
COPY --from=installer [ "/staging/", "/" ]

To build your new chiselled Ubuntu base image with SSL support, use the command: docker build . -t chiselled-ssl-base:22.04 -f chiselled-ssl-base.dockerfile

Your new base image with SSL support should be less than 11 MB and is ready for use in applications that require SSL.

This simple process allows you to easily add and remove package dependencies and customise your chiselled Ubuntu base image to fit your specific needs and requirements. For more examples and use cases, including creating extra package slices, check out our examples git repo.

Chiselled Ubuntu container images offer the benefits of a well-known and well-maintained Linux distribution combined with the advantages of ultra-small Distroless-type container images, offering a secure and efficient foundation for building and deploying containerised applications.

So why not try chiselled Ubuntu container images and see the benefits for yourself? As they say, the proof is in the pudding – or in this case, the size of your container image!