One place for hosting & domains


      How to Use Buildah to Build OCI Container Images

      Buildah is an open source containerization tool capable of creating images from scratch, Dockerfiles, or Containerfiles. It also follows the Open Container Initiative (OCI) specifications, making Buildah images both versatile and open.

      Learn how to install and start using Buildah in this tutorial. Below, find steps for creating containers and rendering those containers to images.

      Before You Begin

      1. Familiarize yourself with our
        Getting Started with Linode guide, and complete the steps for setting your Linode’s hostname and timezone.

      2. This guide uses sudo wherever possible. Complete the sections of our
        How to Secure Your Server guide to create a standard user account, harden SSH access, and remove unnecessary network services.

      3. Update your system.

        • AlmaLinux, CentOS Stream, Fedora, or Rocky Linux:

          sudo dnf upgrade
        • Ubuntu:

          sudo apt update && sudo apt upgrade


      This guide is written for a non-root user. Commands that require elevated privileges are prefixed with sudo. If you’re not familiar with the sudo command, see the
      Users and Groups guide.

      What Is Buildah?

      Buildah is an open source tool for building container images that are compliant with the OCI.

      The OCI seeks to create an open standard for containerization. To that end, it defines specifications for container runtimes and images. Another goal of the OCI is to help secure and streamline operating system virtualization.

      Buildah provides powerful tools to create and maintain OCI-compliant images. You may be familiar with Dockerfiles, one of the most common formats for container images. Buildah fully supports them, and can create images directly from them.

      But Buildah can also craft container images from scratch. Buildah allows you to use the command line to build up the container from a complete blank slate, giving it only the contents you need. Buildah can then render and export an OCI container image from your work.

      Buildah vs Docker

      Overall, Buildah is similar in functionality to Docker. So what sets it apart? Why use Buildah instead of Docker?

      One of Buildah’s primary advantages is it avoids the security risks of the Docker daemon. The Docker daemon runs on a socket with root-level access, and this has the potential to introduce security risks. Buildah avoids this risk by running without a daemon, allowing containers to be truly rootless.

      With Buildah, the user also has the ability to create container images from scratch. Buildah can mount an empty container and let the user add only what they need. This feature can be extraordinarily useful when you need a lightweight image.

      Buildah also gives the user precise control of images, and specifically image layers. For those wanting more capabilities in their containerization tools, Buildah tends to offer what they need.

      However, Buildah is not as useful when it comes to running and deploying container images. It can run them, but lacks some of the features to be found in other tools. Instead, Buildah puts the vast majority of its emphasis on creating containers and building container images.

      For that reason, users often build their OCI images in Buildah and run them using Podman, a tool for running and managing containers. You can learn more about Podman in our guide
      Podman vs Docker: Comparing the Two Containerization Tools.

      How to Install Buildah

      1. Install Buildah using your distribution’s package manager.

        • AlmaLinux, CentOS Stream (8 or later), Fedora, or Rocky Linux:

          sudo dnf install buildah
        • Ubuntu (20.10 or later):

          sudo apt install buildah
      2. Verify your installation by checking the installed Buildah version using the command below:

        buildah -v

        Your output may vary from what is shown here, but you are just looking to see that Buildah installed successfully:

        buildah version 1.26.1 (image-spec 1.0.2-dev, runtime-spec 1.0.2-dev)

      Configuring Buildah for Rootless Usage

      By default, Buildah commands are executed with root privileges, prefaced with the sudo command. However, one of the most appealing features of Buildah is its ability to run containers in rootless mode. This lets limited users work securely with Buildah.

      While Docker also allows you to run commands as a limited user, the Docker daemon still runs as root. This is a potential security issue with Docker, one that may allow limited users to execute privileged commands through the daemon.

      Buildah’s rootless mode solves this because it runs containers completely in a non-root environment, without a root daemon. Find the steps needed to set up your Buildah instance for rootless usage below.

      1. Install the slirp4netns and fuse-overlayfs tools to support your rootless Buildah operations.

        • AlmaLinux, CentOS Stream, Fedora, or Rocky Linux:

          sudo dnf install slirp4netns fuse-overlayfs
        • Ubuntu:

          sudo apt install slirp4netns fuse-overlayfs
      2. Add subuids and subgids ranges for your limited user. This example does so for the user example_user. It gives that user a sub-UID and sub-GID of 100000, each with a range of 65535 IDs:

        sudo usermod --add-subuids 100000-165535 --add-subgids 100000-165535 example_user

      How to Use Buildah

      Buildah is primarily used for creating container images. Like Docker, Buildah can construct containers from Dockerfiles, but Buildah stands out for also allowing you to craft images from scratch.

      The next two sections show you how to build container images using each of these methods.

      Creating an Image from a Dockerfile

      Dockerfiles provide an approachable way to create containers with Buildah, especially for users already familiar with Docker or Dockerfiles.

      Buildah is fully capable of interpreting Dockerfile script, making it straightforward to build your Docker container images with Buildah.

      This guide uses an example Dockerfile provided in one of the official Buildah tutorials. This Dockerfile results in a container with the latest version of Fedora and the Apache HTTP server (httpd). It also “exposes” the HTTP server via port 80.

      1. Create a new file named Dockerfile in your user’s home directory:

        nano Dockerfile
      2. Fill it with the following contents:

        File: Dockerfile
        # Base on the most recently released Fedora
        FROM fedora:latest
        MAINTAINER ipbabble email [email protected] # not a real email
        # Install updates and httpd
        RUN echo "Updating all fedora packages"; dnf -y update; dnf -y clean all
        RUN echo "Installing httpd"; dnf -y install httpd && dnf -y clean all
        # Expose the default httpd port 80
        EXPOSE 80
        # Run the httpd
        CMD ["/usr/sbin/httpd", "-DFOREGROUND"]
      3. Press CTRL+X to exit, Y to save, and Enter to quit nano.

        Assuming you are still in the directory where this Dockerfile is located (your user’s home directory), you can immediately build the container’s image.

      4. This example names the new image fedora-http-server:

        buildah build -t fedora-http-server

        The output should look like the following:

        STEP 1/6: FROM fedora:latest
        Resolved "fedora" as an alias (/etc/containers/registries.conf.d/000-shortnames.conf)
        Trying to pull
        Getting image source signatures
        Copying blob 75f075168a24 done
        Copying config 3a66698e60 done
        Writing manifest to image destination
        Storing signatures
        STEP 2/6: MAINTAINER ipbabble email [email protected] # not a real email
        STEP 3/6: RUN echo "Updating all fedora packages"; dnf -y update; dnf -y clean all

        Now you can now run the image with Podman, a tool for working with containers which is often used as a compliment to Buildah.

      5. First, install Podman:

        • AlmaLinux, CentOS Stream, Fedora, or Rocky Linux:

          sudo dnf install podman
        • Ubuntu:

          sudo apt install podman
      6. In the command below, the -p option “publishes” a given port, here routing the container’s port 80 to the local machine’s port 8080. The --rm option automatically removes the container when it has finished running, a fitting solution for a quick test like this.

        podman run -p 8080:80 --rm fedora-http-server
      7. Now you can open another Terminal session on the machine where the image is running, and use a cURL command to verify the default page is being served on port 8080:

        curl localhost:8080

        You should see the raw HTML of the Fedora HTTP Server test page as output:

        <!doctype html>
            <meta charset='utf-8'>
            <meta name='viewport' content='width=device-width, initial-scale=1'>
            <title>Test Page for the HTTP Server on Fedora</title>
            <style type="text/css">
              html {
                height: 100%;
                width: 100%;
                body {
      8. When done, stop the container, but first, determine your container’s ID or name:

        podman ps

        You should see an out put like this:

        CONTAINER ID  IMAGE                                COMMAND               CREATED        STATUS            PORTS                 NAMES
        daadb647b880  localhost/fedora-http-server:latest  /usr/sbin/httpd -...  8 seconds ago  Up 8 seconds ago>80/tcp  suspicious_goodall
      9. Now stop the container. Replace container-name-or-id with your container name or ID:

        podman stop container-name-or-id

        Since we set this example container to automatically remove when done with the --rm flag, stopping it also removes it.

      10. You can now logout, close the second Terminal session, and return to the original Terminal:


      Learn more about Podman in our guide
      How to Install Podman for Running Containers.

      You can also learn more about crafting Dockerfiles in our guide
      How to Use a Dockerfile to Build a Docker Image. This guide also includes links to further tutorials with more in-depth coverage of Dockerfiles.

      Creating an Image from Scratch

      As noted above, Buildah stands out for its ability to create container images from scratch. This section walks you through an example of how you can do just that.


      Buildah’s commands for working with containers can involve a few keywords, so often these commands are executed using environment variables. So, for instance, to create a new container with Fedora, you may see something like:

      fedoracontainer=$(buildah from fedora)

      Learn more about how environment variables work in our guide
      How to Use and Set Environment Variables.

      The example container that follows starts with an empty container. It then adds Bash and some other core utilities to that container to demonstrate how you can add programs to create a minimal container image.


      This section assumes you want to run Buildah in rootless mode, being its major draw versus Docker. Unfortunately, the Ubuntu package manager, APT, presents issues with installing packages onto a non-root container. So the instructions that follow are for RHEL-derived distributions such as AlmaLinux, CentOS Stream, Fedora, and Rocky Linux.

      If you want to run Buildah under Ubuntu in regular root mode, simply preface each buildah command that follows with sudo.

      For rootless operation, you need to execute the unshare command first. This command puts you in a shell within the user namespace. The next several steps presume your are in the user namespace shell until noted, otherwise the buildah mount command below will fail.

      1. Enter the user namespace shell:

        buildah unshare
      2. Create a blank container using Buildah’s scratch base:

        scratchcontainer=$(buildah from scratch)
      3. Mount the container as a virtual file system:

        scratchmnt=$(buildah mount $scratchcontainer)
      4. Install Bash and coreutils to the empty container.

        • AlmaLinux, CentOS Stream, Fedora, or Rocky Linux:

          Replace the value 36 below with the version of your RHEL-derived distribution:

          dnf install --installroot $scratchmnt --releasever 36 bash coreutils --setopt install_weak_deps=false
        • Debian or Ubuntu:

          Replace the value bullseye below with the codename of your Debian-based distribution:

          sudo apt install debootstrap
          sudo debootstrap bullseye $scratchmnt
      5. You can now test Bash on the container. The following command puts you in a Bash shell within the container:

        buildah run $scratchcontainer bash
      6. You can then exit the Bash shell using:

      7. You can now safely operate the container from outside of the user namespace shell initiated with unshare:


        From here on out, we replace $scratchcontainer with the container’s name, which should be working-container. However, if you have more than one container, the container’s name may differ. You can verify the container name via the buildah containers command.

      8. Now let’s recreate the test script file. From your user’s home directory, create the script-files folder and the file in the script-files folder:

        mkdir script-files
        nano script-files/

        Give it the following contents:

        File: script-files/
        echo "This is an example script."

        When done, press CTRL+X to exit, Y to save, and Enter to quit.

      9. The command below copies that file to the container’s /usr/bin directory:

        buildah copy working-container ~/script-files/ /usr/bin
      10. Verify the file’s delivery by running the ls command on the container for the /usr/bin directory:

        buildah run working-container ls /usr/bin

        Your file should be among the listed files:

      11. For a working example of how to execute scripts on a Buildah container, give this file executable permissions:

        buildah run working-container chmod +x /usr/bin/
      12. You can now run the script via the run command:

        buildah run working-container /usr/bin/

        Your output should be identical to the following:

        This is an example script.
      13. Once you are satisfied with the container, you can commit the change to an image:

        buildah commit working-container bash-core-image

        Your output should look something like this:

        Getting image source signatures
        Copying blob a0282af9505e done
        Copying config 9ea7958840 done
        Writing manifest to image destination
        Storing signatures
      14. You can now unmount and remove the container:

        buildah unmount working-container
        buildah rm working-container

      Managing Images and Containers

      Buildah is oriented towards creating container images, but it does have a few features for reviewing available containers and images. Here’s a brief list of the associated commands for these features.

      • To see a list of images built with your Buildah instance, run the following command:

        buildah images

        If you followed along for the sections above on creating Buildah images, you may have an image listing like this:

        REPOSITORY                  TAG      IMAGE ID       CREATED              SIZE
        localhost/fedora-http-server        latest   c313b363840d   8 minutes ago    314 MB
        localhost/bash-core-image           latest   9ea79588405b   20 minutes ago   108 MB   latest   3a66698e6040   2 months ago     169 MB
      • To list containers currently running under Buildah, use the following command:

        buildah containers

        Should you use this command while the container is still running from the section above on building an image from scratch, you may get an output like:

        68a1cc02025d     *                  scratch                          working-container
      • You can get the details of a particular image using a command like the following one, replacing 9ea79588405b with your image’s ID. You can get your image’s ID when the image is built or from the buildah images command show above:

        buildah inspect 9ea79588405b

        The image details actually consist of the JSON document that fully represents the image’s contents. All container images are just that: JSON documents with the instructions for building their corresponding containers.

        Here is an example of the first portion of a container image JSON resulting from the section above on creating an image from scratch:

            "Type": "buildah 0.0.1",
            "FromImage": "localhost/bash-core-image:latest",
            "FromImageID": "9ea79588405b48ff7b0572438a81a888c2eb25d95e6526b75b1020108ac11c10",
            "FromImageDigest": "sha256:beee0e0603e62647addab15341f1a52361a9684934d8d6ecbe1571fabd083dca",
            "Config": "{\"created\":\"2022-07-20T17:34:55.16639723Z\",\"architecture\":\"amd64\",\"os\":\"linux\",\"config\":{\"Labels\":{\"io.buildah.version\":\"1.26.1\"}},\"rootfs\":{\"type\":\"layers\",\"diff_ids\":[\"sha256:a0282af9505ed0545c7fb82e1408e1b130cad13a9c3393870c7c4a0d5cf06a62\"]},\"history\":[{\"created\":\"2022-07-20T17:34:55.72288433Z\",\"created_by\":\"/bin/sh\"}]}",
            "Manifest": "{\"schemaVersion\":2,\"mediaType\":\"application/vnd.oci.image.manifest.v1+json\",\"config\":{\"mediaType\":\"application/vnd.oci.image.config.v1+json\",\"digest\":\"sha256:9ea79588405b48ff7b0572438a81a888c2eb25d95e6526b75b1020108ac11c10\",\"size\":324},\"layers\":[{\"mediaType\":\"application/vnd.oci.image.layer.v1.tar\",\"digest\":\"sha256:a0282af9505ed0545c7fb82e1408e1b130cad13a9c3393870c7c4a0d5cf06a62\",\"size\":108421632}],\"annotations\":{\"org.opencontainers.image.base.digest\":\"\",\"\":\"\"}}",
            "Container": "",
            "ContainerID": "",
            "MountPoint": "",
            "ProcessLabel": "",
            "MountLabel": "",
            "ImageAnnotations": {
                "org.opencontainers.image.base.digest": "",
                "": ""


      Buildah gives you a simple yet robust tool for crafting container images. It’s more than just an alternative to Docker. Buildah is a containerization tool for securely creating open containers and container images. With this tutorial, you have everything you need to get started building your own images and using Buildah to the utmost.

      More Information

      You may wish to consult the following resources for additional information
      on this topic. While these are provided in the hope that they will be
      useful, please note that we cannot vouch for the accuracy or timeliness of
      externally hosted materials.

      Source link

      How To Use docker exec to Run Commands in a Docker Container


      Docker is a containerization tool that helps developers create and manage portable, consistent Linux containers.

      When developing or deploying containers you’ll often need to look inside a running container to inspect its current state or debug a problem. To this end, Docker provides the docker exec command to run programs in containers that are already running.

      In this tutorial we will learn about the docker exec command and how to use it to run commands and get an interactive shell in a running Docker container.


      This tutorial assumes you already have Docker installed, and your user has permission to run docker. If you need to run docker as the root user, please remember to prepend sudo to the commands in this tutorial.

      For more information on using Docker without sudo access, please see the Executing the Docker Command Without Sudo section of our How To Install Docker tutorial.

      Starting a Test Container

      To use the docker exec command, you will need a running Docker container. If you don’t already have a container, start a test container with the following docker run command:

      • docker run -d --name container-name alpine watch "date >> /var/log/date.log"

      This command creates a new Docker container from the official alpine image. This is a popular Linux container image that uses Alpine Linux, a lightweight, minimal Linux distribution.

      We use the -d flag to detach the container from our terminal and run it in the background. --name container-name will name the container container-name. You could choose any name you like here, or leave this off entirely to have Docker automatically generate a unique name for the new container.

      Next we have alpine, which specifies the image we want to use for the container.

      And finally we have watch "date >> /var/log/date.log". This is the command we want to run in the container. watch will repeatedly run the command you give it, every two seconds by default. The command that watch will run in this case is date >> /var/log/date.log. date prints the current date and time, like this:


      • Fri Jul 23 14:57:05 UTC 2021

      The >> /var/log/date.log portion of the command redirects the output from date and appends it to the file /var/log/date.log. Every two seconds a new line will be appended to the file, and after a few seconds it will look something like this:


      Fri Jul 23 15:00:26 UTC 2021 Fri Jul 23 15:00:28 UTC 2021 Fri Jul 23 15:00:30 UTC 2021 Fri Jul 23 15:00:32 UTC 2021 Fri Jul 23 15:00:34 UTC 2021

      In the next step we’ll learn how to find the names of Docker containers. This will be useful if you already have a container you’re targeting, but you’re not sure what its name is.

      Finding the Name of a Docker Container

      We’ll need to provide docker exec with the name (or container ID) of the container we want to work with. We can find this information using the docker ps command:

      This command lists all of the Docker containers running on the server, and provides some high-level information about them:


      CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 76aded7112d4 alpine "watch 'date >> /var…" 11 seconds ago Up 10 seconds container-name

      In this example, the container ID and name are highlighted. You may use either to tell docker exec which container to use.

      If you’d like to rename your container, use the docker rename command:

      • docker rename container-name new-name

      Next, we’ll run through several examples of using docker exec to execute commands in a running Docker container.

      Running an Interactive Shell in a Docker Container

      If you need to start an interactive shell inside a Docker Container, perhaps to explore the filesystem or debug running processes, use docker exec with the -i and -t flags.

      The -i flag keeps input open to the container, and the -t flag creates a pseudo-terminal that the shell can attach to. These flags can be combined like this:

      • docker exec -it container-name sh

      This will run the sh shell in the specified container, giving you a basic shell prompt. To exit back out of the container, type exit then press ENTER:

      If your container image includes a more advanced shell such as bash, you could replace sh with bash above.

      Running a Non-interactive Command in a Docker Container

      If you need to run a command inside a running Docker container, but don’t need any interactivity, use the docker exec command without any flags:

      • docker exec container-name tail /var/log/date.log

      This command will run tail /var/log/date.log on the container-name container, and output the results. By default the tail command will print out the last ten lines of a file. If you’re running the demo container we set up in the first section, you will see something like this:


      Mon Jul 26 14:39:33 UTC 2021 Mon Jul 26 14:39:35 UTC 2021 Mon Jul 26 14:39:37 UTC 2021 Mon Jul 26 14:39:39 UTC 2021 Mon Jul 26 14:39:41 UTC 2021 Mon Jul 26 14:39:43 UTC 2021 Mon Jul 26 14:39:45 UTC 2021 Mon Jul 26 14:39:47 UTC 2021 Mon Jul 26 14:39:49 UTC 2021 Mon Jul 26 14:39:51 UTC 2021

      This is essentially the same as opening up an interactive shell for the Docker container (as done in the previous step with docker exec -it container-name sh) and then running the tail /var/log/date.log command. However, rather than opening up a shell, running the command, and then closing the shell, this command returns that same output in a single command and without opening up a pseudo-terminal.

      Running Commands in an Alternate Directory in a Docker Container

      To run a command in a certain directory of your container, use the --workdir flag to specify the directory:

      • docker exec --workdir /tmp container-name pwd

      This example command sets the /tmp directory as the working directory, then runs the pwd command, which prints out the present working directory:



      The pwd command has confirmed that the working directory is /tmp.

      Running Commands as a Different User in a Docker Container

      To run a command as a different user inside your container, add the --user flag:

      • docker exec --user guest container-name whoami

      This will use the guest user to run the whoami command in the container. The whoami command prints out the current user’s username:



      The whoami command confirms that the container’s current user is guest.

      Passing Environment Variables into a Docker Container

      Sometimes you need to pass environment variables into a container along with the command to run. The -e flag lets you specify an environment variable:

      • docker exec -e TEST=sammy container-name env

      This command sets the TEST environment variable to equal sammy, then runs the env command inside the container. The env command then prints out all the environment variables:


      PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin HOSTNAME=76aded7112d4 TEST=sammy HOME=/root

      The TEST variable is set to sammy.

      To set multiple variables, repeat the -e flag for each one:

      • docker exec -e TEST=sammy -e ENVIRONMENT=prod container-name env

      If you’d like to pass in a file full of environment variables you can do that with the --env-file flag.

      First, make the file with a text editor. We’ll open a new file with nano here, but you can use any editor you’re comfortable with:

      We’re using .env as the filename, as that’s a popular standard for using these sorts of files to manage information outside of version control.

      Write your KEY=value variables into the file, one per line, like the following:



      Save and close the file. To save the file and exit nano, press CTRL+O, then ENTER to save, then CTRL+X to exit.

      Now run the docker exec command, specifying the correct filename after --env-file:

      • docker exec --env-file .env container-name env


      PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin HOSTNAME=76aded7112d4 TEST=sammy ENVIRONMENT=prod HOME=/root

      The two variables in the file are set.

      You may specify multiple files by using multiple --env-file flags. If the variables in the files overlap each other, whichever file was listed last in the command will override the previous files.

      Common Errors

      When using the docker exec command, you may encounter a few common errors:

      Error: No such container: container-name

      The No such container error means the specified container does not exist, and may indicate a misspelled container name. Use docker ps to list out your running containers and double-check the name.

      Error response from daemon: Container 2a94aae70ea5dc92a12e30b13d0613dd6ca5919174d73e62e29cb0f79db6e4ab is not running

      This not running message means that the container exists, but it is stopped. You can start the container with docker start container-name

      Error response from daemon: Container container-name is paused, unpause the container before exec

      The Container is paused error explains the problem fairly well. You need to unpause the container with docker unpause container-name before proceeding.


      In this tutorial we learned how to execute commands in a running Docker container, along with some command line options available when doing so.

      For more information on Docker in general, please see our Docker tag page, which has links to Docker tutorials, Docker-related Q&A pages, and more.

      For help with installing Docker, take a look at How To Install and Use Docker on Ubuntu 20.04.

      Source link

      What is a Container?

      A container is a minimalist, isolated user-space environment that runs at the operating system level and shares system resources with other instances. Containers are designed to provide a portable and consistent runtime environment for applications, while consuming less resources than a traditional server or virtual machine. This allows for an overall better use of computing resources in multi-component, distributed applications, and highly-available systems.

      Unlike virtual machines, which are typically built on top of computer-emulated hardware and run fully isolated operating systems, containers share resources from the host such as the kernel and the filesystem, which results in a smaller footprint.

      Docker, a popular open source containerization tool, was largely instrumental in spurring the adoption of component-based application design with self-contained micro services. While other containerizing systems exist, Docker became popular for providing a more accessible and comprehensive interface around the technology.

      To learn more about containers, you can refer to the following resources:

      Source link