Build OCI images with Buildah on sourcehut

Post created: 2020-03-29

Post updated: 2020-05-15

Written by Marcel Mehlmann

I like the concept of containerization. Isolating1 applications and deploying them with only a few commands on a large fleet of servers surely has its benefits. One major and importen part of every container setup is automation. If you are running arround and are building your container by hand you are doing it wrong. So let\'s take a look how you can automate your container building on the excellent sourcehut infrastructure.

For this tutorial we will use the following workflow:

Creating the Dockerfile --> Commiting to -->
Building and tagging the image via --> Pushing the image to a registry

As an example project i will be using my xdarkhttpd-docker project. Darkhttpd is a basic webserver originally written by Emil Mikulic. I am using a fork by Ryan M. Jacobs which supports basic auth and am extending it by adding some more mimetypes (for now).2

Step 1: Creating the Dockerfile

Since the main effort lies in creating the Dockerfile from which our image will be built we will take a closer look at that. At first i used Alpine as base image and compiled darkhttpd in it. This resulted in an image which was around 9 to 10 Mb in size. After trying to remove some bloat (something you should always strive for) i was able to reduce the image size to around 7 Mb by using a multi-stage build.

This method builds the binary in one container including all build dependencies and then copies the binary over into a second container. 7Mb is okayish but we can go even smaller. If we are able to build a static binary we can use an empty image (called scratch) to house and run the binary and a work directory. Which is what i did. The whole xdarkhttpd image is now \< 700kB in size. (I have to add that darkhttpd in itself is a very rudimentary server. No cgi, no dynamic content, etc.)

Without further ado here is the complete Dockerfile:

from alpine:latest as builder

RUN apk --no-cache add make musl-dev git gcc
run git clone
workdir darkhttpd
copy filetype.patch .
run patch darkhttpd.c < filetype.patch
run LDFLAGS=-static make bin

from scratch
LABEL maintainer=""
expose 8080
#workdir /usr/local/bin
copy --from=builder /darkhttpd/darkhttpd .
workdir /data
entrypoint ["../darkhttpd", ".", "--port", "8080"]

Normally i would commit this Dockerfile and the filetype.patch to a github repo and would connect my Docker Hub Account to it. Then i would add a build job on Docker Hub and it would pull everything from the repo build the image and then commit it to the registry. But we are here to talk about how we would achieve the same on sourcehut. Cue the next step...

2. Create a .build.yml to tell what to do

Sourcehut has no interface to configure the build system. Instead it relies on a YAML-file which you can add to your repository. I will publish my .build.yml and then will talk about some aspects which are not intuitive (not because of sourcehut but the whole process).

image: fedora/30
  - buildah
  - b525cc29-e3ad-488e-8b07-f267e3db3532
  - build_image: |
      cd xdarkhttpd-docker
      buildah bud -f Dockerfile -t containsliquid/xdarkhttpd:latest
  - push_image: |
      buildah login
      buildah push --format docker containsliquid/xdarkhttpd:latest docker://

I won\'t go into too much details since there is enough documentation and references on sourcehut for this matter. One of the biggest changes in the standard workflow is that i am not using Docker to build the image. But why? Docker, even though they are one of the two big players in the field of containerization, has a few drawbacks. And especially two of them are pretty annoying in this case:

Since it is my goal to make the process as simple as possible i opted in to use Buildah instead. Buildah is a tool developed by Redhat and is following the OCI specification for container images. Buildah does not require root to run and is also part of the standard Fedora/Centos repos. Buildah works very similar to Docker. So we do not need to change things in our Dockerfile. With the command in line 11 we are building and tagging the image. After the build_image task we start the push_image task. We log into Docker Hub and push the image to the repo there. Easy right?

3. Hurdles in the process

3.1. Docker Hub Login

This one is a bit tricky. The login process of Buildah requires you to pass your credentials either via --username & --password or via authfile. Usually this file is located in ~/.docker/config.json. Luckily enough you can add secrets on sourcehut. At this time sourcehut supports ssh-, pgp-keys and files as secrets. So log into the registry of your choice on your local machine (Docker or Podman/Buildah will work). Locate the corresponding config.json and add it to the sourcehut secret store. Remember to add the correct path for the file so Buildah can find the file. You are now able to log into the registry on

3.2. The weird OCI compatibility of Docker Hub

This is something which completely is the fault of Docker Inc.

  1. Their registry on is a V1 registry which means that it does not work with software that is following the OCI specification.4 This problem can be circumvented by using as base domain (which is an interface for the newer registry V2).
  2. Pushing an OCI compliant image to works in Buildah but the image won\'t show in the web ui. This is a weird one. I don\'t know if currently their registry or the frontend is broken. But you can add a --format docker flag to your push command and everything is working fine.

4. Conclusion

Sourcehut is an excellent environment to build and deploy container images. There are a few things to consider but all in all the workflow is not that different to github. The major benefit of using sourcehut over github is independance from the big silos. Furthermore sourcehuts buildsystem offers more flexibility than Dockers own system. One thing i will look into in the future is automated inspection and analysis of images. So stay tuned...

  1. Isolation in this context is mainly referring to bundeling dependencies not security. 

  2. Thus calling it e(x)tended darkhttpd or shor xdarkhttpd. I am awul at naming thing. 

  3. I never tested it, but i think docker would work fine on sourcehut. But i wanted to show an approach that could potentially work everywhere and does not rely on the right privileges to talk to daemon running as root. 

  4. V1 was Dockers own format for container images. Since the format has been specified by the Open Container Initiative version 2 of their registry is compatible with OCI compliant images.