Skip to content

Commit f86a4b5

Browse files
Rafid Bin Mostofacjdcordeiro
andauthored
feat: add how-to guide on chiselled docker image (#11)
--------- Co-authored-by: Cristovao Cordeiro <cristovao.cordeiro@canonical.com>
1 parent e4156d6 commit f86a4b5

File tree

3 files changed

+248
-0
lines changed

3 files changed

+248
-0
lines changed

docs/.custom_wordlist.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
AGPL
22
Armored
3+
Dockerfile
34
Levenshtein
45
OpenPGP
56
SBOM
@@ -12,10 +13,13 @@ armored
1213
basename
1314
chiseled
1415
distroless
16+
entrypoint
1517
esm
18+
favorite
1619
fips
1720
http
1821
https
22+
initialize
1923
jsonwall
2024
optimize
2125
recognized

docs/how-to/index.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,14 @@ yourself.
1616
1717
install-chisel
1818
```
19+
20+
## Creating a chiseled container image
21+
22+
Chiseled file systems are ideal for creating minimal and distroless-like
23+
container images.
24+
25+
```{toctree}
26+
:maxdepth: 1
27+
28+
use-chisel-in-dockerfile
29+
```
Lines changed: 233 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,233 @@
1+
# Use Chisel in a Dockerfile
2+
3+
Chiseled file systems are ideal for creating minimal and distroless-like
4+
container images. This guide shows how to use Chisel in a Dockerfile to create a
5+
chiseled Docker image.
6+
7+
8+
## Design the image
9+
10+
Let's set some goals for our chiseled image. Consider a Python 3 image, which
11+
contains a Python 3 interpreter and is able to run Python 3 scripts and
12+
commands.
13+
14+
- The [image entrypoint] must be `python3`.
15+
- The image must be able to run Python 3 scripts.
16+
- The image must be minimal.
17+
18+
To build this image, we will use [multi-stage docker builds].
19+
20+
In earlier stage(s), we will
21+
22+
1. install Chisel and other dependencies that we may need, and
23+
2. install the slices, using Chisel, into a staging area.
24+
25+
Finally, we will copy the staging area's root file system to the `/` directory
26+
in the final stage. The final stage's base image will be [`scratch`]. Thus, the
27+
image only contains the root file system installed by Chisel and nothing else.
28+
29+
30+
## Write the Dockerfile
31+
32+
Create a `Dockerfile` and open it with your favorite text editor.
33+
34+
35+
## Install Chisel and dependencies
36+
37+
To make building easier and configurable, let's first define some variables that
38+
we can re-use. Visit the {{latest_release_page}} to determine the latest version
39+
of Chisel and assign the latest version to `CHISEL_VERSION`.
40+
41+
```docker
42+
ARG UBUNTU_RELEASE=24.04
43+
ARG CHISEL_VERSION=v1.1.0
44+
```
45+
46+
Let's now initialize a new build stage where we install Chisel and dependencies
47+
and prepare the final chiseled root file system.
48+
49+
```docker
50+
FROM ubuntu:$UBUNTU_RELEASE AS builder
51+
ARG TARGETARCH UBUNTU_RELEASE CHISEL_VERSION
52+
SHELL ["/bin/bash", "-oeux", "pipefail", "-c"]
53+
```
54+
55+
Chisel needs the `ca-certificates` package in order to fetch files from the
56+
archives. Let's install that.
57+
58+
```docker
59+
RUN apt-get update \
60+
&& DEBIAN_FRONTEND=noninteractive apt-get install -y ca-certificates \
61+
&& apt-get clean -y \
62+
&& rm -rf /var/lib/apt/lists/*
63+
```
64+
65+
Install Chisel.
66+
67+
```docker
68+
ADD "https://github.com/canonical/chisel/releases/download/${CHISEL_VERSION}/chisel_${CHISEL_VERSION}_linux_${TARGETARCH}.tar.gz" \
69+
chisel.tar.gz
70+
RUN tar -xvf chisel.tar.gz -C /usr/bin/
71+
```
72+
73+
74+
## Prepare the chiseled root file system
75+
76+
Now that we have Chisel installed in the `builder` stage, we can install the
77+
appropriate slices and prepare the root file system.
78+
79+
The [`python3_standard` slice] provides `python3`. We will install this slice,
80+
along with a few others:
81+
82+
- `base-files_base` for file structure.
83+
- `base-files_release-info` for release info.
84+
- `base-files_chisel` for the chisel manifest.
85+
- `ca-certificates_data` for network support.
86+
87+
```docker
88+
RUN mkdir /staging-rootfs \
89+
&& chisel cut --release "ubuntu-$UBUNTU_RELEASE" --root /staging-rootfs \
90+
base-files_base \
91+
base-files_release-info \
92+
base-files_chisel \
93+
ca-certificates_data \
94+
python3_standard
95+
```
96+
97+
Next, let's copy the `/etc/passwd` and `/etc/group` files to the installed root
98+
file system to use the existing `ubuntu` user. We will also create a working
99+
directory for the user, per the `/etc/passwd` file.
100+
101+
```docker
102+
RUN cp /etc/passwd /etc/group /staging-rootfs/etc \
103+
&& install -o ubuntu -g ubuntu -d /staging-rootfs/home/ubuntu
104+
```
105+
106+
107+
### Copy the root file system to the final image
108+
109+
Finally, we will initialize a new stage where we will copy the prepared root
110+
file system (`/staging-rootfs`) from the previous stage.
111+
112+
```docker
113+
FROM scratch
114+
115+
COPY --from=builder /staging-rootfs /
116+
```
117+
118+
119+
### Set user and working directory
120+
121+
Now we will set the `USER` to `ubuntu` and the `WORKDIR` to `/home/ubuntu`.
122+
123+
```docker
124+
USER ubuntu
125+
WORKDIR /home/ubuntu
126+
```
127+
128+
129+
### Set the entrypoint
130+
131+
All that remains is to set the entrypoint to `python3`.
132+
133+
```docker
134+
ENTRYPOINT ["python3"]
135+
```
136+
137+
138+
## Build and test the image
139+
140+
Let's copy all the code-blocks above and save it to `Dockerfile`.
141+
142+
```docker
143+
ARG UBUNTU_RELEASE=24.04
144+
ARG CHISEL_VERSION=v1.1.0
145+
146+
FROM ubuntu:$UBUNTU_RELEASE AS builder
147+
ARG TARGETARCH UBUNTU_RELEASE CHISEL_VERSION
148+
SHELL ["/bin/bash", "-oeux", "pipefail", "-c"]
149+
150+
RUN apt-get update \
151+
&& DEBIAN_FRONTEND=noninteractive apt-get install -y ca-certificates \
152+
&& apt-get clean -y \
153+
&& rm -rf /var/lib/apt/lists/*
154+
155+
ADD "https://github.com/canonical/chisel/releases/download/${CHISEL_VERSION}/chisel_${CHISEL_VERSION}_linux_${TARGETARCH}.tar.gz" \
156+
chisel.tar.gz
157+
158+
RUN tar -xvf chisel.tar.gz -C /usr/bin/
159+
160+
RUN mkdir /staging-rootfs \
161+
&& chisel cut --release "ubuntu-$UBUNTU_RELEASE" --root /staging-rootfs \
162+
base-files_base \
163+
base-files_release-info \
164+
base-files_chisel \
165+
ca-certificates_data \
166+
python3_standard
167+
168+
RUN cp /etc/passwd /etc/group /staging-rootfs/etc \
169+
&& install -o ubuntu -g ubuntu -d /staging-rootfs/home/ubuntu
170+
171+
172+
FROM scratch
173+
174+
COPY --from=builder /staging-rootfs /
175+
176+
USER ubuntu
177+
WORKDIR /home/ubuntu
178+
179+
ENTRYPOINT ["python3"]
180+
```
181+
182+
Run the following command to build the image.
183+
184+
```sh
185+
docker build -t python:3-chiseled .
186+
```
187+
188+
Once it's built, run the following command to check if the interpreter works.
189+
190+
```{terminal}
191+
:input: docker run -it python:3-chiseled
192+
193+
Python 3.12.3 (main, Feb 4 2025, 14:48:35) [GCC 13.3.0] on linux
194+
Type "help", "copyright", "credits" or "license" for more information.
195+
>>> print('Hello world!')
196+
Hello world!
197+
>>> import os
198+
>>> os.getuid()
199+
1000
200+
>>> os.getcwd()
201+
'/home/ubuntu'
202+
>>> exit()
203+
```
204+
205+
We can further test the image by writing a custom script and checking if the
206+
script successfully runs. Consider the following `./src/app.py` file.
207+
208+
```py
209+
# ./src/app.py
210+
import datetime
211+
212+
x = datetime.datetime.now()
213+
print(x)
214+
```
215+
216+
Run the following command to run the script in our container image.
217+
218+
```{terminal}
219+
:input: docker run -v $PWD/src:/src:ro python:3-chiseled /src/app.py
220+
221+
2025-03-11 06:36:50.717280
222+
```
223+
224+
It should print out the current date and time.
225+
226+
227+
<!-- LINKS -->
228+
229+
[python3 package on Noble]: https://packages.ubuntu.com/noble/python3
230+
[image entrypoint]: https://github.com/opencontainers/image-spec/blob/main/config.md
231+
[multi-stage docker builds]: https://docs.docker.com/build/building/multi-stage/
232+
[`scratch`]: https://hub.docker.com/_/scratch
233+
[`python3_standard` slice]: https://github.com/canonical/chisel-releases/blob/ubuntu-24.04/slices/python3.yaml#L13

0 commit comments

Comments
 (0)