Building container image with Buildah

Building container image with Buildah

The purpose of this tutorial is to demonstrate how to create OCI compliant container image with Buildah. Building a container image implemented in CI Pipeline using Jenkins and Vault.

Buildah is a tool that facilitates building OCI container images. You can also create an image in the docker format. For more information about OCI image specifications check here.

The Buildah package provides a command line tool that can be used to

  • create a working container, either from scratch or using an image as a starting point
  • create an image, either from a working container or via the instructions in a Dockerfile
  • images can be built in either the OCI image format or the traditional upstream docker image format
  • mount a working container’s root filesystem for manipulation
  • unmount a working container’s root filesystem
  • use the updated contents of a container’s root filesystem as a filesystem layer to create a new image
  • delete a working container or an image
  • rename a local container


It is integrated with Jenkins Pipeline. Basically, in this pipeline, Buildah pull an alpine image in the public repository, install Nginx, injects nginx.conf, website documents(index.html) to the folders in the image. Finally, it commits all the changes and unmount the container image file system from the host and pushes it to the Dockerhub. Dockerhub credentials stored in Vault and fetch from the Vault server to login to Dockerhub to push the image.

Pipeline script configured to get Jenkinsfile from github repo.(Pipeline script from SCM.) You can get the all files in the github repo.

Creating a Secret on Vault

To put credentials or to get credentials from Vault, you MUST have a valid TOKEN, which is provided to you via your Vault admin. If it is installed by yourself, Vault provides you ROOT TOKEN if installation is successful. This token is eligible to do everything. So, as best practice on production is create new token for a user to access to specific secret on specific path from specific network address.

To interact with vault you need to setup Vault server address and your valid token.

export VAULT_ADDR=''
export VAULT_TOKEN=xxxxxxxxxxxxxxxxxyyyyz

We are creating a new secret engine which is key value pair(version 2). and this secret will be stored in the path secret/dockerhub.

vault secrets enable -path=secret/dockerhub -version=2 kv
vault kv put secret/dockerhub  username="youdockerhubuser" password="yourdockerhubpassword" registry_url=""
  • For registry_url you can use any of them such as, etc.,

Configuring Vault from scratch is another post. So, I assumed that your Vault server already exits on your environment. To check more info about Vault

pipeline {
    agent none
    stages {
        stage('BUILD') {
            agent{label "buildah"}
            steps {
                sh 'sudo ./'

        stage('GETVAULTCREDS') {
            agent{label "buildah"}
            steps {
            withVault(configuration: [timeout: 60, vaultCredentialId: '835dadcc-6e30-4a33-8983-7ac3cd065ebe', vaultUrl: 'http://devops:8200'], vaultSecrets: [[path: 'secret/dockerhub', secretValues: [[vaultKey: 'username'], [vaultKey: 'password'], [vaultKey: 'registry_url']]]]) {
             sh 'sudo buildah login --username "${username}" --password "${password}" "${registry_url}"'

            agent {label "buildah"}
                sh 'sudo buildah push buildah-nginx docker://'
  • Do not forget to Install Vault Plugin and configure the Vault address on Configure System menu on Jenkins UI.
  • As you may know, Vault server on my environment uses http to connect to Vault Server, That is not acceptable for the production deployment of Vault.



Jenkins Open Blue Ocean Flow view.

Starting Pod With Podman

To test the container image, it will be run on the Container engine Podman.

[tesla@podman ~]$ sudo podman run -dt -p 8080:8080/tcp manintheit/buildah-nginx
[tesla@podman ~]$ sudo podman container ls
CONTAINER ID  IMAGE                                      COMMAND  CREATED         STATUS             PORTS                   NAMES
c55bae99f32f  /bin/sh  10 seconds ago  Up 10 seconds ago>8080/tcp  tender_nobel