Red Hat Training
A Red Hat training course is available for RHEL 8
Chapter 14. Building container images with Buildah
Buildah facilitates building OCI container images that meet the OCI Runtime Specification. With Buildah, you can create a working container, either from scratch or using an image as a starting point. You can create an image either from a working container or using the instructions in a Containerfile
. You can mount and unmount a working container’s root filesystem.
14.1. The Buildah tool
Using Buildah is different from building images with the docker command in the following ways:
- No Daemon
- Buildah requires no container runtime.
- Base image or scratch
- You can build an image based on another container or start with an empty image (scratch).
- Build tools are external
Buildah does not include build tools within the image itself. As a result, Buildah:
- Reduces the size of built images.
- Increases security of images by excluding software (for example gcc, make, and yum) from the resulting image.
- Allows to transport the images using fewer resources because of the reduced image size.
- Compatibility
- Buildah supports building container images with Dockerfiles allowing for an easy migration from Docker to Buildah.
The default location Buildah uses for container storage is the same as the location the CRI-O container engine uses for storing local copies of images. As a result, the images pulled from a registry by either CRI-O or Buildah, or committed by the buildah command, are stored in the same directory structure. However, even though CRI-O and Buildah are currently able to share images, they cannot share containers.
Additional resources
- Buildah - a tool that facilitates building Open Container Initiative (OCI) container images
- Buildah Tutorial 1: Building OCI container images
- Buildah Tutorial 2: Using Buildah with container registries
- Building with Buildah: Dockerfiles, command line, or scripts
- How rootless Buildah works: Building containers in unprivileged environments
14.2. Installing Buildah
Install the Buildah tool using the yum
command.
Procedure
Install the Buildah tool:
# yum -y install buildah
Verification
Display the help message:
# buildah -h
14.3. Getting images with Buildah
Use the buildah from
command to create a new working container from scratch or based on a specified image as a starting point.
Procedure
Create a new working container based on the
registry.redhat.io/ubi8/ubi
image:# buildah from registry.access.redhat.com/ubi8/ubi Getting image source signatures Copying blob… Writing manifest to image destination Storing signatures ubi-working-container
Verification
List all images in local storage:
# buildah images REPOSITORY TAG IMAGE ID CREATED SIZE registry.access.redhat.com/ubi8/ubi latest 272209ff0ae5 2 weeks ago 234 MB
List the working containers and their base images:
# buildah containers CONTAINER ID BUILDER IMAGE ID IMAGE NAME CONTAINER NAME 01eab9588ae1 * 272209ff0ae5 registry.access.redhat.com/ub... ubi-working-container
Additional resources
-
buildah-from
man page -
buildah-images
man page -
buildah-containers
man page
14.4. Running commands inside of the container
Use the buildah run
command to execute a command from the container.
Prerequisites
- A pulled image is available on the local system.
Procedure
Display the operating system version:
# buildah run ubi-working-container cat /etc/redhat-release Red Hat Enterprise Linux release 8.4 (Ootpa)
Additional resources
-
buildah-run
man page
14.5. Building an image from a Containerfile with Buildah
Use the buildah bud
command to build an image using instructions from a Containerfile
.
The buildah bud
command uses a Containerfile
if found in the context directory, if it is not found the buildah bud
command uses a Dockerfile
; otherwise any file can be specified with the --file
option. The available commands that are usable inside a Containerfile
and a Dockerfile
are equivalent.
Procedure
Create a
Containerfile
:# cat Containerfile FROM registry.access.redhat.com/ubi8/ubi ADD myecho /usr/local/bin ENTRYPOINT "/usr/local/bin/myecho"
Create a
myecho
script:# cat myecho echo "This container works!"
Change the access permissions of
myecho
script:# chmod 755 myecho
Build the
myecho
image usingContainerfile
in the current directory:# buildah bud -t myecho . STEP 1: FROM registry.access.redhat.com/ubi8/ubi STEP 2: ADD myecho /usr/local/bin STEP 3: ENTRYPOINT "/usr/local/bin/myecho" STEP 4: COMMIT myecho ... Storing signatures
Verification
List all images:
# buildah images REPOSITORY TAG IMAGE ID CREATED SIZE localhost/myecho latest b28cd00741b3 About a minute ago 234 MB
Run the
myecho
container based on thelocalhost/myecho
image:# podman run --name=myecho localhost/myecho This container works!
List all containers:
# podman ps -a 0d97517428d localhost/myecho 12 seconds ago Exited (0) 13 seconds ago myecho
You can use the podman history
command to display the information about each layer used in the image.
Additional resources
-
buildah-bud
man page
14.6. Inspecting containers and images with Buildah
Use the buildah inspect
command to display information about a container or image.
Prerequisites
- An image was built using instructions from Containerfile. For details, see section Building an image from a Containerfile with Buildah.
Procedure
Inspect the image:
To inspect the myecho image, enter:
# buildah inspect localhost/myecho { "Type": "buildah 0.0.1", "FromImage": "localhost/myecho:latest", "FromImageID": "b28cd00741b38c92382ee806e1653eae0a56402bcd2c8d31bdcd36521bc267a4", "FromImageDigest": "sha256:0f5b06cbd51b464fabe93ce4fe852a9038cdd7c7b7661cd7efef8f9ae8a59585", "Config": ... "Entrypoint": [ "/bin/sh", "-c", "\"/usr/local/bin/myecho\"" ], ... }
To inspect the working container from the
myecho
image:Create a working container based on the
localhost/myecho
image:# buildah from localhost/myecho
Inspect the
myecho-working-container
container:# buildah inspect ubi-working-container { "Type": "buildah 0.0.1", "FromImage": "registry.access.redhat.com/ubi8/ubi:latest", "FromImageID": "272209ff0ae5fe54c119b9c32a25887e13625c9035a1599feba654aa7638262d", "FromImageDigest": "sha256:77623387101abefbf83161c7d5a0378379d0424b2244009282acb39d42f1fe13", "Config": ... "Container": "ubi-working-container", "ContainerID": "01eab9588ae1523746bb706479063ba103f6281ebaeeccb5dc42b70e450d5ad0", "ProcessLabel": "system_u:system_r:container_t:s0:c162,c1000", "MountLabel": "system_u:object_r:container_file_t:s0:c162,c1000", ... }
Additional resources
-
buildah-inspect
man page
14.7. Modifying a container using buildah mount
Use the buildah inspect
command to display information about a container or image.
Prerequisites
- An image built using instructions from Containerfile. For details, see section Building an image from a Containerfile with Buildah.
Procedure
Create a working container based on the
registry.access.redhat.com/ubi8/ubi
image and save the name of the container to themycontainer
variable:# mycontainer=$(buildah from localhost/myecho) # echo $mycontainer myecho-working-container
Mount the
myecho-working-container
container and save the mount point path to themymount
variable:# mymount=$(buildah mount $mycontainer) # echo $mymount /var/lib/containers/storage/overlay/c1709df40031dda7c49e93575d9c8eebcaa5d8129033a58e5b6a95019684cc25/merged
Modify the
myecho
script and make it executable:# echo 'echo "We modified this container."' >> $mymount/usr/local/bin/myecho # chmod +x $mymount/usr/local/bin/myecho
Create the
myecho2
image from themyecho-working-container
container:# buildah commit $mycontainer containers-storage:myecho2
Verification
List all images in local storage:
# buildah images REPOSITORY TAG IMAGE ID CREATED SIZE docker.io/library/myecho2 latest 4547d2c3e436 4 minutes ago 234 MB localhost/myecho latest b28cd00741b3 56 minutes ago 234 MB
Run the
myecho2
container based on thedocker.io/library/myecho2
image:# podman run --name=myecho2 docker.io/library/myecho2 This container works! We even modified it.
Additional resources
-
buildah-mount
man page -
buildah-commit
man page
14.8. Modifying a container using buildah copy and buildah config
Use buildah copy
command to copy files to a container without mounting it. You can then configure the container using the buildah config
command to run the script you created by default.
Prerequisites
- An image built using instructions from Containerfile. For details, see section Building an image from a Containerfile with Buildah.
Procedure
Create a script named
newecho
and make it executable:# cat newecho echo "I changed this container" # chmod 755 newecho
Create a new working container:
# buildah from myecho:latest myecho-working-container-2
Copy the newecho script to
/usr/local/bin
directory inside the container:# buildah copy myecho-working-container-2 newecho /usr/local/bin
Change the configuration to use the
newecho
script as the new entrypoint:# buildah config --entrypoint "/bin/sh -c /usr/local/bin/newecho" myecho-working-container-2
Optional. Run the
myecho-working-container-2
container whixh triggers thenewecho
script to be executed:# buildah run myecho-working-container-2 -- sh -c '/usr/local/bin/newecho' I changed this container
Commit the
myecho-working-container-2
container to a new image calledmynewecho
:# buildah commit myecho-working-container-2 containers-storage:mynewecho
Verification
List all images in local storage:
# buildah images REPOSITORY TAG IMAGE ID CREATED SIZE docker.io/library/mynewecho latest fa2091a7d8b6 8 seconds ago 234 MB
Additional resources
-
buildah-copy
man page -
buildah-config
man page -
buildah-commit
man page -
buildah-run
man page
14.9. Creating images from scratch with Buildah
Instead of starting with a base image, you can create a new container that holds only a minimal amount of container metadata.
When creating an image from scratch container, consider:
- You can copy the executable with no dependencies into the scratch image and make a few configuration settings to get a minimal container to work.
-
You must initialize an RPM database and add a release package in the container to use tools like
yum
orrpm
. - If you add a lot of packages, consider using the standard UBI or minimal UBI images instead of scratch images.
Procedure
This procedure adds a web service httpd to a container and configures it to run.
Create an empty container:
# buildah from scratch working-container
Mount the
working-container
container and save the mount point path to thescratchmnt
variable:# scratchmnt=$(buildah mount working-container) # echo $scratchmnt /var/lib/containers/storage/overlay/be2eaecf9f74b6acfe4d0017dd5534fde06b2fa8de9ed875691f6ccc791c1836/merged
Initialize an RPM database within the scratch image and add the
redhat-release
package:# yum install -y --releasever=8 --installroot=$scratchmnt redhat-release
Install the
httpd
service to thescratch
directory:# yum install -y --setopt=reposdir=/etc/yum.repos.d \ --installroot=$scratchmnt \ --setopt=cachedir=/var/cache/dnf httpd
Create the
$scratchmnt/var/www/html/index.html
file:# mkdir -p $scratchmnt/var/www/html # echo "Your httpd container from scratch works!" > $scratchmnt/var/www/html/index.html
Configure
working-container
to run thehttpd
daemon directly from the container:# buildah config --cmd "/usr/sbin/httpd -DFOREGROUND" working-container # buildah config --port 80/tcp working-container # buildah commit working-container localhost/myhttpd:latest
Verification
List all images in local storage:
# podman images REPOSITORY TAG IMAGE ID CREATED SIZE localhost/myhttpd latest 08da72792f60 2 minutes ago 121 MB
Run the
localhost/myhttpd
image and configure port mappings between the container and the host system:# podman run -p 8080:80 -d --name myhttpd 08da72792f60
Test the web server:
# curl localhost:8080 Your httpd container from scratch works!
Additional resources
-
buildah-config
man page -
buildah-commit
man page
14.10. Pushing containers to a private registry
Use buildah push
command to push an image from local storage to a public or private repository.
Prerequisites
- An image was built using instructions from Containerfile. For details, see section Building an image from a Containerfile with Buildah.
Procedure
Create the local registry on your machine:
# podman run -d -p 5000:5000 registry:2
Push the
myecho:latest
image to thelocalhost
registry:# buildah push --tls-verify=false myecho:latest localhost:5000/myecho:latest Getting image source signatures Copying blob sha256:e4efd0... ... Writing manifest to image destination Storing signatures
Verification
List all images in the
localhost
repository:# curl http://localhost:5000/v2/_catalog {"repositories":["myecho2]} # curl http://localhost:5000/v2/myecho2/tags/list {"name":"myecho","tags":["latest"]}
Inspect the
docker://localhost:5000/myecho:latest
image:# skopeo inspect --tls-verify=false docker://localhost:5000/myecho:latest | less { "Name": "localhost:5000/myecho", "Digest": "sha256:8999ff6050...", "RepoTags": [ "latest" ], "Created": "2021-06-28T14:44:05.919583964Z", "DockerVersion": "", "Labels": { "architecture": "x86_64", "authoritative-source-url": "registry.redhat.io", ... }
Pull the
localhost:5000/myecho
image:# podman pull --tls-verify=false localhost:5000/myecho2 # podman run localhost:5000/myecho2 This container works!
Additional resources
-
buildah-push
man page
14.11. Pushing containers to the Docker Hub
Use your Docker Hub credentials to push and pull images from the Docker Hub with the buildah
command.
Prerequisites
- An image built using instructions from Containerfile. For details, see section Building an image from a Containerfile with Buildah.
Procedure
Push the
docker.io/library/myecho:latest
to your Docker Hub. Replaceusername
andpassword
with your Docker Hub credentials:# buildah push --creds username:password \ docker.io/library/myecho:latest docker://testaccountXX/myecho:latest
Verification
Get and run the
docker.io/testaccountXX/myecho:latest
image:Using Podman tool:
# podman run docker.io/testaccountXX/myecho:latest This container works!
Using Buildah and Podman tools:
# buildah from docker.io/testaccountXX/myecho:latest myecho2-working-container-2 # podman run myecho-working-container-2
Additional resources
-
buildah-push
man page
14.12. Removing images with Buildah
Use the buildah rmi
command to remove locally stored container images. You can remove an image by its ID or name.
Procedure
List all images on your local system:
# buildah images REPOSITORY TAG IMAGE ID CREATED SIZE localhost/johndoe/webserver latest dc5fcc610313 46 minutes ago 263 MB docker.io/library/mynewecho latest fa2091a7d8b6 17 hours ago 234 MB docker.io/library/myecho2 latest 4547d2c3e436 6 days ago 234 MB localhost/myecho latest b28cd00741b3 6 days ago 234 MB localhost/ubi-micro-httpd latest c6a7678c4139 12 days ago 152 MB registry.access.redhat.com/ubi8/ubi latest 272209ff0ae5 3 weeks ago 234 MB
Remove the
localhost/myecho
image:# buildah rmi localhost/myecho
To remove multiple images:
# buildah rmi docker.io/library/mynewecho docker.io/library/myecho2
To remove all images from your system:
# buildah rmi -a
To remove images that have multiple names (tags) associated with them, add the
-f
option to remove them:# buildah rmi -f localhost/ubi-micro-httpd
Verification
Ensure that images were removed:
# buildah images
Additional resources
-
buildah-rmi
man page
14.13. Removing containers with Buildah
Use the buildah rm
command to remove containers. You can specify containers for removal with the container ID or name.
Prerequisites
- At least one container has been stopped.
Procedure
List all containers:
# buildah containers CONTAINER ID BUILDER IMAGE ID IMAGE NAME CONTAINER NAME 05387e29ab93 * c37e14066ac7 docker.io/library/myecho:latest myecho-working-container
Remove the myecho-working-container container:
# buildah rm myecho-working-container 05387e29ab93151cf52e9c85c573f3e8ab64af1592b1ff9315db8a10a77d7c22
Verification
Ensure that containers were removed:
# buildah containers
Additional resources
-
buildah-rm
man page