Use Chisel in a Dockerfile¶
Chiseled file systems are ideal for creating minimal and distroless-like container images. This guide shows how to use Chisel in a Dockerfile to create a chiseled Docker image.
Design the image¶
Let’s set some goals for our chiseled image. Consider a Python 3 image, which contains a Python 3 interpreter and is able to run Python 3 scripts and commands.
The image entrypoint must be
python3.The image must be able to run Python 3 scripts.
The image must be minimal.
To build this image, we will use multi-stage docker builds.
In earlier stage(s), we will
install Chisel and other dependencies that we may need, and
install the slices, using Chisel, into a staging area.
Finally, we will copy the staging area’s root file system to the / directory
in the final stage. The final stage’s base image will be scratch. Thus, the
image only contains the root file system installed by Chisel and nothing else.
Write the Dockerfile¶
Create a Dockerfile and open it with your favorite text editor.
Install Chisel and dependencies¶
To make building easier and configurable, let’s first define some variables that
we can re-use. Visit the latest release page
to determine the latest version
of Chisel and assign the latest version to CHISEL_VERSION.
ARG UBUNTU_RELEASE=24.04
ARG CHISEL_VERSION=v1.1.0
Let’s now initialize a new build stage where we install Chisel and dependencies and prepare the final chiseled root file system.
FROM ubuntu:$UBUNTU_RELEASE AS builder
ARG TARGETARCH UBUNTU_RELEASE CHISEL_VERSION
SHELL ["/bin/bash", "-oeux", "pipefail", "-c"]
Chisel needs the ca-certificates package in order to fetch files from the
archives. Let’s install that.
RUN apt-get update \
&& DEBIAN_FRONTEND=noninteractive apt-get install -y ca-certificates \
&& apt-get clean -y \
&& rm -rf /var/lib/apt/lists/*
Install Chisel.
ADD "https://github.com/canonical/chisel/releases/download/${CHISEL_VERSION}/chisel_${CHISEL_VERSION}_linux_${TARGETARCH}.tar.gz" \
chisel.tar.gz
RUN tar -xvf chisel.tar.gz -C /usr/bin/
Prepare the chiseled root file system¶
Now that we have Chisel installed in the builder stage, we can install the
appropriate slices and prepare the root file system.
The python3_standard slice provides python3. We will install this slice,
along with a few others:
base-files_basefor file structure.base-files_release-infofor release info.base-files_chiselfor the chisel manifest.ca-certificates_datafor network support.
RUN mkdir /staging-rootfs \
&& chisel cut --release "ubuntu-$UBUNTU_RELEASE" --root /staging-rootfs \
base-files_base \
base-files_release-info \
base-files_chisel \
ca-certificates_data \
python3_standard
Next, let’s copy the /etc/passwd and /etc/group files to the installed root
file system to use the existing ubuntu user. We will also create a working
directory for the user, per the /etc/passwd file.
RUN cp /etc/passwd /etc/group /staging-rootfs/etc \
&& install -o ubuntu -g ubuntu -d /staging-rootfs/home/ubuntu
Copy the root file system to the final image¶
Finally, we will initialize a new stage where we will copy the prepared root
file system (/staging-rootfs) from the previous stage.
FROM scratch
COPY --from=builder /staging-rootfs /
Set user and working directory¶
Now we will set the USER to ubuntu and the WORKDIR to /home/ubuntu.
USER ubuntu
WORKDIR /home/ubuntu
Set the entrypoint¶
All that remains is to set the entrypoint to python3.
ENTRYPOINT ["python3"]
Build and test the image¶
Let’s copy all the code-blocks above and save it to Dockerfile.
ARG UBUNTU_RELEASE=24.04
ARG CHISEL_VERSION=v1.1.0
FROM ubuntu:$UBUNTU_RELEASE AS builder
ARG TARGETARCH UBUNTU_RELEASE CHISEL_VERSION
SHELL ["/bin/bash", "-oeux", "pipefail", "-c"]
RUN apt-get update \
&& DEBIAN_FRONTEND=noninteractive apt-get install -y ca-certificates \
&& apt-get clean -y \
&& rm -rf /var/lib/apt/lists/*
ADD "https://github.com/canonical/chisel/releases/download/${CHISEL_VERSION}/chisel_${CHISEL_VERSION}_linux_${TARGETARCH}.tar.gz" \
chisel.tar.gz
RUN tar -xvf chisel.tar.gz -C /usr/bin/
RUN mkdir /staging-rootfs \
&& chisel cut --release "ubuntu-$UBUNTU_RELEASE" --root /staging-rootfs \
base-files_base \
base-files_release-info \
base-files_chisel \
ca-certificates_data \
python3_standard
RUN cp /etc/passwd /etc/group /staging-rootfs/etc \
&& install -o ubuntu -g ubuntu -d /staging-rootfs/home/ubuntu
FROM scratch
COPY --from=builder /staging-rootfs /
USER ubuntu
WORKDIR /home/ubuntu
ENTRYPOINT ["python3"]
Run the following command to build the image.
docker build -t python:3-chiseled .
Once it’s built, run the following command to check if the interpreter works.
user@host:~$ docker run -it python:3-chiseledPython 3.12.3 (main, Feb 4 2025, 14:48:35) [GCC 13.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> print('Hello world!')
Hello world!
>>> import os
>>> os.getuid()
1000
>>> os.getcwd()
'/home/ubuntu'
>>> exit()
We can further test the image by writing a custom script and checking if the
script successfully runs. Consider the following ./src/app.py file.
# ./src/app.py
import datetime
x = datetime.datetime.now()
print(x)
Run the following command to run the script in our container image.
user@host:~$ docker run -v $PWD/src:/src:ro python:3-chiseled /src/app.py2025-03-11 06:36:50.717280
It should print out the current date and time.