Extending the System via Dockerfiles

Build a custom Hadron image using a Dockerfile, add an extra binary, publish it to an OCI registry, and upgrade a running node to the new image.

Now that you’ve launched your first Kubernetes cluster on Hadron, you might want to extend the system. Kairos supports multiple approaches for this—Dockerfiles, systemd system extensions, and bundles. There isn’t a single “best” option: each has trade-offs, and the right choice depends on your needs. In this quickstart, we’ll extend the system using a Dockerfile.

Prerequisites

To extend and run Hadron, you’ll need a container engine and virtualization software that can run (or emulate) the amd64 architecture. In this guide, we’ll use:

Prefer to watch a video?

Building

Hadron by itself is not immutable. To get the full Kairos experience—immutability, atomic upgrades, and more—we first need to initialize (often called “kairosify”) the system using kairos-init.

Create a Dockerfile with the following content:

FROM quay.io/kairos/kairos-init:v0.6.8 AS kairos-init

FROM ghcr.io/kairos-io/hadron:v0.0.1-beta2 AS base
ARG VERSION

RUN --mount=type=bind,from=kairos-init,src=/kairos-init,dst=/kairos-init \
    eval /kairos-init -l debug -s install --model generic --provider k3s --version \"${VERSION}\" && \
    eval /kairos-init -l debug -s init --model generic --provider k3s --version \"${VERSION}\"

Build it with the following command. Here, 0.1.0 is the version we’re assigning to my-hadron. We tag the image and also pass the version as a build argument so kairos-init writes it into /etc/kairos-release. We’ll use that in later steps.

docker build -t my-hadron:0.1.0 --build-arg=VERSION=0.1.0 .

If the command finishes successfully, you should see my-hadron among your local images:

docker images | grep my-hadron
my-hadron                          0.1.0          5effd0969bfe   4 minutes ago   397MB

Adding a binary

Hadron doesn’t ship with a package manager. That means the two straightforward options to extend the system are:

  • build packages yourself, or
  • add a prebuilt binary.

To keep this quickstart short, we’ll use the second approach.

As an example, we’ll download and install bottom (btm) to inspect system resource usage.

FROM quay.io/kairos/kairos-init:v0.6.4 AS kairos-init

FROM ghcr.io/kairos-io/hadron-toolchain:v0.0.1-beta1 AS bottom
RUN curl -L -o bottom.tar.gz https://github.com/ClementTsang/bottom/releases/download/0.11.4/bottom_x86_64-unknown-linux-musl.tar.gz
RUN tar xvzf bottom.tar.gz

FROM ghcr.io/kairos-io/hadron:v0.0.1-beta1 AS base
ARG VERSION

RUN --mount=type=bind,from=kairos-init,src=/kairos-init,dst=/kairos-init \
    eval /kairos-init -l debug -s install --provider k3s --version \"${VERSION}\" && \
    eval /kairos-init -l debug -s init --provider k3s --version \"${VERSION}\"

COPY --from=bottom /btm /usr/bin/btm

Now build the image again, but assign a new version. Since we’re using SemVer, bumping the minor version to 0.2.0 is a good next step. This makes it easy to distinguish images and perform upgrades.

docker build -t my-hadron:0.2.0 --build-arg=VERSION=0.2.0 .

Next, push the image to a registry you can access. If you don’t have one available, you can use ttl.sh. Keep in mind ttl.sh is an anonymous registry, so an image with the same name might already exist—use a unique image name.

docker tag my-hadron:0.2.0 ttl.sh/my-hadron:0.2.0
docker push ttl.sh/my-hadron:0.2.0

Conclusion

Congratulations—you’ve successfully extended a Hadron image.

What’s Next?

Other ways to extend the system

Extend with systemd extensions

Continue the quickstart

If you’re new to Kairos, follow these in order to learn the full workflow: build a custom image, upgrade atomically, then harden the system.

Upgrade & rollback (atomic upgrades) Trusted Boot (TPM + Secure Boot) quickstart

Deep dive docs

If you’re already comfortable with Kairos and want details, jump straight to the reference docs.

Cloud-config reference

Frequently Asked Questions (FAQs)

What is the hadron-toolchain container for?

Hadron builds many packages that are available in the toolchain image but are not included in the final production images. They’re useful for building code from source and other build-time tasks, but you typically avoid shipping them at runtime for security and size reasons.

Can I have a specific version of Kubernetes?

Yes, with the --provider flag you can define if you want k3s or k0s installed, and with the --provider-k3s-version and --provider-k0s-version respectively, you can define the exact version to install.

What if I don’t need Kubernetes?

No problem—remove the --provider flag from kairos-init and you’ll get a core image without Kubernetes installed.