Title: Make your own container base images from trusted sources
Author: Solène
Date: 12 March 2026
Tags: security linux supply-chain
Description: In this article, you will learn how to create an OCI
container image of Alpine or Ubuntu using a trustable base image
# Introduction
I really like containers, but they are something that is currently very
bad from a security point of view: distribution
We download container images from container registries, whether it is
docker.io, quay.io or ghcr.io, but the upstream project do not sign
them, so we can not verify a CI pipeline or the container registry did
not mess with the image. There are actually a few upstream actors
signing their images: Fedora, Red Hat and universial-blue based distros
(Bluefin, Aurora, Bazzite), so if you acquire their public key using
for signing from a different channel, you can verify if you got the
image originally built. Please do not hesitate to get in touch with me
if you know about other major upstream that sign their container
images.
Nevertheless, we can still create containers ourself from trustable
artifacts signed by upstream. Let's take a look at how to proceed with
Alpine Linux.
# Get the rootfs
The first step is to download a few files:
* Alpine's linux GPG key
* Alpine's "mini root filesystem" build for the architecture you want
* The GPG file (extension .asc) for the mini root filesystem you
downloaded
(HTM) Alpine linux download page on the official website
The GPG file is at the top of the list, it is better to get it from a
different channel to make sure that if the website was hacked, the key
was not changed accordingly with all the signed files, in which case
you would just trust the key of an attacker and it would validate the
artifacts. A simple method is to check the page from webarchive a few
days / week before and verify that the GPG file is the same on
webarchive and the official website.
The GPG key fingerprint I used is 0482 D840 22F5 2DF1 C4E7 CD43 293A
CD09 07D9 495A as of the date of publication.
# Verify the artifacts
You will need to have gpg installed and a initialized keyring (I do not
cover this here). Run the following command:
```
gpg --import ncopa.asc
gpg --verify alpine-minirootfs-3.23.3-x86_64.tar.gz.asc alpine-minirootfs-3.23.3-x86_64.tar.gz
```
It should answer something like this:
```
gpg: Signature made Wed Jan 28 00:25:36 2026 CET
gpg: using RSA key 0482D84022F52DF1C4E7CD43293ACD0907D9495A
gpg: Good signature from "Natanael Copa <ncopa@alpinelinux.org>" [unknown]
gpg: WARNING: This key is not certified with a trusted signature!
gpg: There is no indication that the signature belongs to the owner.
Primary key fingerprint: 0482 D840 22F5 2DF1 C4E7 CD43 293A CD09 07D9 495A
```
The line "Good signature...." tells you that the file integrity check
matches the GPG key you imported. The rest of the message tells you
that the key is not trustable. This is actually a GPG thing, you would
need to edit your keyring and mark the key as "trustable" or have in
your keyring a trusted key that signed this key (this is the web of
trust GPG wanted to create), but this will only remove the warning. Of
course, you can mark that key trustable if you plan to use it for a
long time and you are absolutely sure it is the genuine one.
You do not need to verify the checksum using sha256, the GPG check did
the same in addition to authenticate the person who produced the
checksum.
Now you validated the minirootfs authenticity, you can create an Alpine
container!
# Container creation
You can use podman or docker for this:
```
podman import alpine-minirootfs-3.23.3-x86_64.tar.gz alpine:3.23.3-local
```
You are now ready to build more containers based on your own
cryptographically verified Alpine container image.
# Example of use
It is rather easy to build new containers with useful purpose on top of
your new base container.
Create a Containerfile (or Dockerfile, your mileage may vary):
```
FROM alpine:3.23.3-local
RUN apk add nginx
CMD ["nginx", "-c", "/app/nginx.conf", "-g", "daemon off;"]
```
Build a container with this command:
```
podman build . -t alpine_local_nginx
```
# Conclusion
Without any kind of cryptographic signature mechanism available between
upstream and the end user, it is not possible to ensure a container
from a third party registry was not tampered with.
It is best for security to rebuild the container image, and then
rebuild all the containers you need using your base image, rather than
blindly trusting registries.
One tool to sign container images is cosign.
(HTM) Cosign project GitHub page
# Going further
This process works for other Linux distributions of course. For
instance, for Ubuntu you can download Ubuntu base image, the
SHA256SUMS.gpg and SHA256SUMS files, and make sure to get a genuine GPG
key to verify the signature.
(HTM) Ubuntu official website: ubuntu-base 24.04 releases