Chapter 5. Finding, Running, and Building Containers without Docker

5.1. Overview

The docker daemon and docker command represent a bundled runtime environment for running and managing containers. With the advent of standards from the Open Container Initiative, other runtimes are being developed. One such runtime is CRI-O, which was created along with a set of tools to provide alternate ways to work with containers.

The following text describes some of the tools being developed to use with the CRI-O runtime. These tools can also be used with docker-formatted containers and can interact with the docker daemon. In fact, some of these commands can be used without any active runtime environment.

Note

CRI-O was created primarily as a container runtime for Kubernetes and is not currently available as a stand-alone service for Red Hat Enterprise Linux. For OpenShift 3.7, CRI-O is available in tech preview. The OpenShift 3.7 Release Notes tells how to set up CRI-O.

This chapter describes the following tools that you can use instead of the docker command and daemon to work with Open Container Format and docker-formatted containers:

  • runc: The runc command can be used to start up a docker-formatted container image (more specifically, an Open Container Format image).
  • skopeo: The skopeo command lets you inspect images from container image registries, get images and image layers, and use signatures to create and verify images.
Important

The skopeo version currently shipped with RHEL and Atomic Host only works with v2 registries and not the v1 registries Red Hat is currently using.

  • buildah: The buildah command can be used in place of docker build to build container images from Dockerfiles and, ultimately, files in other formats.

The following sections describe runc, skopeo, and buildah.

5.2. Running containers with runc

"runC" is a lightweight, portable implementation of the the Open Container Format (OCF) that provides container runtime. runC unites a lot of the low-level features that make running containers possible. It shares a lot of low-level code with Docker but it is not dependent on any of the components of the Docker platform. It supports Linux namespaces, live migration, and has portable performance profiles. It also provides full support for Linux security features such as SELinux, control groups (cgroups), seccomp, and others. You can build and run images with runc, or you can run docker-formatted images with runc.

5.2.1. Installing and running containers

The runc package is available for Red Hat Enterprise Linux in the Extras channel. You need to have the Extras channel enabled to install it with yum. If you are using Red Hat Enterprise Linux Atomic Host, the runc package is already included. For a regular RHEL system, to enable the extras repository and install the package, run:

$ sudo subscription-manager repos --enable=rhel-7-server-extras-rpms
$ sudo yum install runc

With runc, containers are configured using bundles. A bundle for a container is a directory that includes a specification file named "config.json" and a root file system. The root file system contains the contents of the container.

To create a bundle:

$ runc spec

This command creates a config.json file that only contains a bare-bones structure that you will need to edit. Most importantly, you will need to change the "args" parameter to identify the executable to run. By default, "args" is set to "sh".

    "args": [
      "sh"
    ],

As an example, you can download the docker-formatted Red Hat Enterprise Linux base image (rhel/rhel7) using docker, then export it, create a new bundle for it with runc, and edit the "config.json" file to point to that image. You can then create the container image and run an instance of that image with runc. Use the following commands:

$ sudo docker pull registry.access.redhat.com/rhel7/rhel
$ sudo docker export $(docker create registry.access.redhat.com/rhel7/rhel) > rhel.tar
$ mkdir -p rhel-runc/rootfs
$ tar -C rhel-runc/rootfs -xf rhel.tar
$ runc spec -b rhel-runc
$ vi rhel-runc/config.json      Change the value of terminal from *false* to *true*
$ sudo runc create -b rhel-runc/ rhel-container
$ sudo runc start rhel-container
sh-4.2#

In this example, the name of the container instance is "rhel-container". Running that container, by default, starts a shell, so you can begin looking around and running commands from inside that container. Type exit when you are done.

The name of a container instance must be unique on the host. To start a new instance of a container:

# runc start <container_name>

You can provide the bundle directory using the "-b" option. By default, the value for the bundle is the current directory.

You will need root privileges to start containers with runc. To see all commands available to runc and their usage, run "runc --help".

5.3. Using skopeo to work with container registries

With the skopeo command, you can work with container images from registries without using the docker daemon or the docker command. Registries can include the Docker Registry, your own local registries, or Atomic registries. Activities you can do with skopeo include:

  • inspect: The output of a skopeo inspect command is similar to what you see from a docker inspect command: low-level information about the container image. That output can be in json format (default) or raw format (using the --raw option).
  • copy: With skopeo copy you can copy a container image from a registry to another registry or to a local directory.
  • layers: The skopeo layers command lets you download the layers associated with images so that they are stored as tarballs and associated manifest files in a local directory.

Like the buildah command and other tools that rely on the containers/image library, the skopeo command can work with images from container storage areas other than those associated with Docker. Available transports to other types of container storage include: containers-storage (for images stored by buildah and CRI-O), ostree (for atomic and system containers), oci (for content stored in an OCI-compliant directory), and others. See the skopeo man page for details.

To try out skopeo, you could set up a local registry, then run the commands that follow to inspect, copy, and download image layers. If you want to follow along with the examples, start by doing the following:

  • Install a local registry as described in Working with Docker Registries.
  • Pull the latest RHEL 7 image to your local system (docker pull rhel7/rhel).
  • Retag the RHEL 7 image and push it to your local registry as follows:

    $ sudo docker tag rhel7/rhel localhost:5000/myrhel7
    $ sudo docker push localhost:5000/myrhel7

The rest of this section describes how to inspect, copy and get layers from the RHEL 7 image.

Note

The skopeo tool by default requires a TLS connection. It fails when trying to use an unencrypted connection. To override the default and use an http registry, prepend http: to the <registry>/<image> string.

5.3.1. Inspecting container images with skopeo

When you inspect a container image from a registry, you need to identify the container format (such as docker), the location of the registry (such as docker.io or localhost:5000), and the repository/image (such as rhel7/rhel).

The following example inspects the mariadb container image from the Docker Registry:

$ sudo skopeo inspect docker://docker.io/library/mariadb
{
    "Name": "docker.io/library/mariadb",
    "Tag": "latest",
    "Digest": "sha256:d3f56b143b62690b400ef42e876e628eb5e488d2d0d2a35d6438a4aa841d89c4",
    "RepoTags": [
        "10.0.15",
        "10.0.16",
        "10.0.17",
        "10.0.19",
...
    "Created": "2016-06-10T01:53:48.812217692Z",
    "DockerVersion": "1.10.3",
    "Labels": {},
    "Architecture": "amd64",
    "Os": "linux",
    "Layers": [
...

Assuming you pushed a container image tagged localhost:5000/myrhel7 to a docker registry running on your local system, the following command inspects that image:

$ sudo skopeo inspect docker://localhost:5000/myrhel7
{
    "Name": "localhost:5000/myrhel7",
    "Tag": "latest",
    "Digest": "sha256:4e09c308a9ddf56c0ff6e321d135136eb04152456f73786a16166ce7cba7c904",
    "RepoTags": [
        "latest"
    ],
    "Created": "2016-06-16T17:27:13Z",
    "DockerVersion": "1.7.0",
    "Labels": {
        "Architecture": "x86_64",
        "Authoritative_Registry": "registry.access.redhat.com",
        "BZComponent": "rhel-server-docker",
        "Build_Host": "rcm-img01.build.eng.bos.redhat.com",
        "Name": "rhel7/rhel",
        "Release": "75",
        "Vendor": "Red Hat, Inc.",
        "Version": "7.2"
    },
    "Architecture": "amd64",
    "Os": "linux",
    "Layers": [
        "sha256:16dc1f96e3a1bb628be2e00518fec2bb97bd5933859de592a00e2eb7774b6ecf"
    ]
}

5.3.2. Copying container images with skopeo

This command copies the myrhel7 container image from a local registry into a directory on the local system:

# skopeo copy docker://localhost:5000/myrhel7 dir:/root/test/
INFO[0000] Downloading myrhel7/blobs/sha256:16dc1f96e3a1bb628be2e00518fec2bb97bd5933859de592a00e2eb7774b6ecf
# ls /root/test
16dc1f96e3a1bb628be2e00518fec2bb97bd5933859de592a00e2eb7774b6ecf.tar manifest.json

The result of the skopeo copy command is a tarball (16d*.tar) and a manifest.jason file representing the image begin copied to the directory you identified. If there were multiple layers, there would be multiple tarballs. The skopeo copy command can also copy images to another registry. If you need to provide a signature to write to the destination registry, you can do that by adding a --sign-by= option to the command line, followed by the required key-id.

5.3.3. Getting image layers with skopeo

The skopeo layers command is similar to skopeo copy, with the difference being that the copy option can copy an image to another registry or to a local directory, while the layers option just drops the layers (tarballs and manifest.jason file) in the current directory. For example

# skopeo layers docker://localhost:5000/myrhel7
INFO[0000] Downloading myrhel7/blobs/sha256:16dc1f96e3a1bb628be2e00518fec2bb97bd5933859de592a00e2eb7774b6ecf
# find .
./layers-myrhel7-latest-698503105
./layers-myrhel7-latest-698503105/manifest.json
./layers-myrhel7-latest-698503105/16dc1f96e3a1bb628be2e00518fec2bb97bd5933859de592a00e2eb7774b6ecf.tar

As you can see from this example, a new directory is created (layers-myrhel7-latest-698503105) and, in this case, a single layer tarball and a manifest.json file are copied to that directory.

5.4. Building container images with Buildah

The buildah command lets you create container images from a working container, a Dockerfile, or from scratch. The resulting images are OCI compliant, so they will work on any runtimes that meet the OCI Runtime Specification (such as Docker and CRI-O).

This section describes how to use the buildah command to create and otherwise work with containers and container images.

5.4.1. Understanding Buildah

Using Buildah is different from building images with the docker command in the following ways:

  • No Daemon!: Buildah bypasses the Docker daemon! So no container runtime (Docker, CRI-O, or other) is needed to use Buildah.
  • Base image or scratch: Lets you not only build an image based on another container, but also lets you start with an empty image (scratch).
  • Build tools external: Doesn’t include build tools within the image itself. As a result, Buildah:

    • Reduces the size of images you build
    • Makes the image more secure by not having the software used to build the container (like gcc, make, and dnf) within the resulting image.
    • Creates images that require fewer resources to transport the images (because they are smaller).

Buildah is able to operate without Docker or other container runtimes by storing data separately and by including features that let you not only build images, but run those images as containers as well. By default, Buildah stores images in an area identified as containers-storage (/var/lib/containers). When you go to commit a container to an image, you can export that container as a local Docker image by indicating docker-daemon (stored in /var/lib/docker).

NOTE: The containers-storage location that the buildah command uses by default is the same place that the CRI-O container runtime uses for storing local copies of images. So images pulled from a registry by either CRI-O or Buildah, or committed by the buildah command, should be visible to both.

There are more than a dozen options to use with the buildah command. Some of the main activities you can do with the buildah command include:

  • Build a container from a Dockerfile: Use a Dockerfile to build a new container image (buildah bud).
  • Build a container from another image or scratch: Build a new container, starting with an existing base image (buildah from <imagename>) or from scratch (buildah from scratch)
  • Inspecting a container or image: View metadata associated with the container or image (buildah inspect)
  • Mount a container: Mount a container’s root filesystem to add or change content (buildah mount).
  • Create a new container layer: Use the updated contents of a container’s root filesystem as a filesystem layer to commit content to a new image (buildah commit).
  • Unmount a container: Unmount a mounted container (buildah umount).
  • Delete a container or an image: Remove a container (buildah rm) or a container image (buildah rmi).

The buildah package is technology preview for Red Hat Enterprise Linux version 7.4.4. For more details on Buildah, see the GitHub Buildah page. The GitHub Buildah site includes man pages and software that might be more recent than is available with the RHEL version. Here are some other articles on Buildah that might interest you:

5.4.2. Installing Buildah

The buildah package is available from the Red Hat Enterprise Linux Server Extras repository. From a RHEL Server system with a valid subscription, install the buildah package as follows:

# subscription-manager repos --enable=rhel-7-server-rpms
# subscription-manager repos --enable=rhel-7-server-extras-rpms
# yum -y install buildah

With the buildah package installed, you can refer to the man pages included with the buildah package for details on how to use it. To see the available man pages and other documentation, type:

# rpm -qd buildah

The following sections describe how to use buildah to get containers, build a container from a Dockerfile, build one from scratch, and manage containers in various ways.

5.4.3. Getting Images with buildah

To get a container image to use with buildah, use the buildah from command. Here’s how to get a RHEL 7 image from the Red Hat Registry as a working container to use with the buildah command:

# buildah from docker://registry.access.redhat.com/rhel7/rhel-atomic
Getting image source signatures
Copying blob…
Writing manifest to image destination
Storing signatures
rhel-atomic-working-container
# buildah images
IMAGE ID     IMAGE NAME  CREATED AT             SIZE
1456eedf8101 registry.access.redhat.com/rhel7/rhel-atomic:latest
                         Oct 12, 2017 15:15     74.77 MB
# buildah containers
CONTAINER ID  BUILDER  IMAGE ID     IMAGE NAME  CONTAINER NAME
dc8f21af4a47     *     1456eedf8101 registry.access.redhat.com/rhel7/rhel-atomic:latest
               rhel-atomic-working-container

Notice that the result of the buildah from command is an image (registry.access.redhat.com/rhel7/rhel-atomic:latest) and a working container that is ready to run from that image (rhel-atomic-working-container). Here’s an example of how to execute a command from that container:

# buildah run rhel-atomic-working-container cat /etc/redhat-release
Red Hat Enterprise Linux Server release 7.4 (Maipo)

The image and container are now ready for use with Buildah.

5.4.4. Building an Image from a Dockerfile with Buildah

With the buildah command, you can create a new image from a Dockerfile. The following steps show how to build an image that includes a simple script that is executed when the image is run.

This simple example starts with two files in the current directory: Dockerfile (which holds the instructions for building the container image) and myecho (a script that echoes a few words to the screen):

# ls
Dockerfile  myecho
# cat Dockerfile
FROM registry.access.redhat.com/rhel7/rhel-atomic
ADD myecho /usr/local/bin
ENTRYPOINT "/usr/local/bin/myecho"
# cat myecho
echo "This container works!"
# chmod 755 myecho

With the Dockerfile in the current directory, build the new container as follows:

# buildah bud -t myecho .
STEP 1: FROM registry.access.redhat.com/rhel7/rhel-atomic
STEP 2: ADD myecho /usr/local/bin
STEP 3: ENTRYPOINT "/usr/local/bin/myecho"
STEP 4: COMMIT containers-storage:[devicemapper@/var/lib/containers/storage+/var/run/containers/storage]docker.io/library/myecho:latest

The buildah bud command creates a new image named myecho, but doesn’t create a working container, as demonstrated when you run buildah containers below:

# buildah images
IMAGE ID     IMAGE NAME          CREATED AT          SIZE
1456eedf8101 registry.access.redhat.com/rhel7/rhel-atomic:latest
                                 Oct 12, 2017 15:15  74.77 MB
ab230ac5aba3  docker.io/library/myecho:latest
                                 Oct 12, 2017 15:15  2.854 KB
# buildah containers

Next, you can make the image into a container and run it, to make sure it is working.

5.4.5. Running a Container with Buildah

To check that the image you built previously works, you need to create a working container from the image, then use buildah run to run the working container.

# buildah from myecho
myecho-working-container
# buildah containers
CONTAINER ID  BUILDER  IMAGE ID     IMAGE NAME  CONTAINER NAME
dc8f21af4a47     *     1456eedf8101  registry.access.redhat.com/rhel7/rhel-atomic:latest
    rhel-atomic-working-container
6d1ffccb557d     *     ab230ac5aba3 docker.io/library/myecho:latest
    myecho-working-container
# buildah run myecho-working-container
This container works!

The steps just shown used the image (myecho) to create a container (myecho-working-container). After that, buildah containers showed the container exists and buildah run ran the container, producing the output: This container works!

5.4.6. Inspecting a Container with buildah

With buildah inspect, you can show information about a container or image. For example, to inspect the myecho image you created earlier, type:

# buildah inspect myecho | less
{
    "type": "buildah 0.0.1",
    "image": "docker.io/library/myecho:latest",
    "image-id": "e2b190ac8a37737ec03cfa4c9bfd989845b9bec3aa81ff48d8350d7418d748f6",
    "config": "eyJjcmVh...
    "ociv1": {
        "created": "2017-10-12T15:15:00.207103Z",
        "author": "Red Hat, Inc.",
        "architecture": "amd64",
        "os": "linux",
        "config": {
            "Entrypoint": [
                "/bin/sh",
                "-c",
                "\"/usr/local/bin/myecho\""
            ],
            "WorkingDir": "/",
            "Labels": {
                "architecture": "x86_64",
                "authoritative-source-url": "registry.access.redhat.com",

To inspect a container from that same image, type the following:

# buildah inspect myecho-working-container | less
{
    "type": "buildah 0.0.1",
    "image": "docker.io/library/myecho:latest",
    "image-id": "e2b190ac8a37737ec03cfa4c9bfd989845b9bec3aa81ff48d8350d7418d748f6",
    "config": "eyJjcmV...
    "container-name": "myecho-working-container",
    "container-id": "70f22e886310bba26bb57ca7afa39fd19af2791c4c66067cb6206b7c3ebdcd20",
    "process-label": "system_u:system_r:svirt_lxc_net_t:s0:c225,c716",
    "mount-label": "system_u:object_r:svirt_sandbox_file_t:s0:c225,c716",
    "ociv1": {
        "created": "2017-10-12T15:15:00.207103Z",
        "author": "Red Hat, Inc.",
        "architecture": "amd64",

Note that the container output has added information, such as the container name, container id, process label, and mount label to what was in the image.

5.4.7. Modifying a Container to Create a new Image with Buildah

There are several ways you can modify an existing container with the buildah command and commit those changes to a new container image:

  • Mount a container and copy files to it
  • Use buildah copy and buildah config to modify a container

Once you have modified the container, use buildah commit to commit the changes to a new image.

5.4.7.1. Using buildah mount to Modify a Container

After getting an image with buildah from, you can use that image as the basis for a new image. The following text shows how to create a new image by mounting a working container, adding files to that container, then committing the changes to a new image.

Type the following to view the working container you used earlier:

# buildah containers
CONTAINER ID BUILDER IMAGE ID     IMAGE NAME  CONTAINER NAME

dc8f21af4a47   *     1456eedf8101 registry.access.redhat.com/rhel7/rhel-atomic:latest
               rhel-atomic-working-container
6d1ffccb557d   *     ab230ac5aba3 docker.io/library/myecho:latest
               myecho-working-container

Mount the container image and set the mount point to a variable ($mymount) to make it easier to deal with:

# mymount=$(buildah mount myecho-working-container)
# echo $mymount
/var/lib/containers/storage/devicemapper/mnt/176c273fe28c23e5319805a2c48559305a57a706cc7ae7bec7da4cd79edd3c02/rootfs

Add content to the script created earlier in the mounted container:

# echo 'echo "We even modified it."' >> $mymount/usr/local/bin/myecho

To commit the content you added to create a new image (named myecho), type the following:

# buildah commit myecho-working-container containers-storage:myecho2

To check that the new image includes your changes, create a working container and run it:

# buildah images
IMAGE ID     IMAGE NAME     CREATED AT          SIZE
a7e06d3cd0e2 docker.io/library/myecho2:latest
                            Oct 12, 2017 15:15  3.144 KB
# buildah from docker.io/library/myecho2:latest
myecho2-working-container
# buildah run myecho2-working-container
This container works!
We even modified it.

You can see that the new echo command added to the script displays the additional text.

When you are done, you can unmount the container:

# buildah umount myecho-working-container

5.4.7.2. Using buildah copy and buildah config to Modify a Container

With buildah copy, you can copy files to a container without mounting it first. Here’s an example, using the myecho-working-container created (and unmounted) in the previous section, to copy a new script to the container and change the container’s configuration to run that script by default.

Create a script called 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 newecho to /usr/local/bin 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 myecho-working-container-2 --entrypoint "/bin/sh -c /usr/local/bin/newecho"

Run the new container, which should result in the newecho command being executed:

# buildah run myecho-working-container-2
I changed this container

If the container behaved as you expected it would, you could then commit it to a new image (mynewecho):

# buildah commit myecho-working-container-2 containers-storage:mynewecho

5.4.8. Creating images from scratch with Buildah

Instead of starting with a base image, you can create a new container that holds no content and only a small amount of container metadata. This is referred to as a scratch container. Here are a few issues to consider when choosing to create an image starting from a scratch container with the buildah command:

  • With a scratch container, you can simply copy executables that have no dependencies to the scratch image and make a few configuration settings to get a minimal container to work.
  • To use tools like yum or rpm packages to populate the scratch container, you need to at least initialize an RPM database in the container and add a release package. The example below shows how to do that.
  • If you end up adding a lot of RPM packages, consider using the rhel or rhel-atomic base images instead of a scratch image. Those base images have had documentation, language packs, and other components trimmed out, which can ultimately result in your image being smaller.

This example adds a Web service (httpd) to a container and configures it to run. In the example, instead of committing the image to Buildah (containers-storage which stores locally in /var/lib/containers), we illustrate how to commit the image so it can be managed by the local Docker service (docker-daemon which stores locally in /var/lib/docker). You could just have easily committed it to Buildah, which would let you then push it to a Docker service (docker), a local OSTree repository (ostree), or other OCI-compliant storage (oci). (Type man buildah push for details.)

To begin, create a scratch container:

# buildah from scratch
working-container

This creates just an empty container (no image) that you can mount as follows:

# scratchmnt=$(buildah mount working-container)
# echo $scratchmnt
/var/lib/containers/storage/devicemapper/mnt/cc92011e9a2b077d03a97c0809f1f3e7fef0f29bdc6ab5e86b85430ec77b2bf6/rootfs

Initialize an RPM database within the scratch image and add the redhat-release package (which includes other files needed for RPMs to work):

# rpm --root $scratchmnt --initdb
# yum install yum-utils       (if not already installed)
# yumdownloader --destdir=/tmp redhat-release-server
# rpm --root $scratchmnt -ihv /tmp/redhat-release-server*.rpm

Install the httpd service to the scratch directory:

# yum install -y --installroot=$scratchmnt httpd

Add some text to an index.html file in the container, so you will be able to test it later:

# echo "Your httpd container from scratch worked." > $scratchmnt/var/www/html/index.html

Instead of running httpd as an init service, set a few buildah config options to run the httpd 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 docker-daemon:myhttpd:latest

By default, the buildah commit command adds the docker.io repository name to the image name and copies the image to the storage area for your local Docker service (/var/lib/docker). For now, you can use the Image ID to run the new image as a container with the docker command:

# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
docker.io/myhttpd   latest              47c0795d7b0e        9 minutes ago       665.6 MB
# docker run -p 8080:80 -d --name httpd-server 47c0795d7b0e
# curl localhost:8080
Your httpd container from scratch worked.

5.4.9. Removing Images or Containers with Buildah

When you are done with particular containers or images, you can remove them with buildah rm or buildah rmi, respectively. Here are some examples.

To remove the container created in the previous section, you could type the following to see the mounted container, unmount it and remove it:

# buildah containers
CONTAINER ID  BUILDER  IMAGE ID     IMAGE NAME                       CONTAINER NAME
05387e29ab93     *     c37e14066ac7 docker.io/library/myecho:latest  myecho-working-container
# buildah mount
05387e29ab93 /var/lib/containers/storage/devicemapper/mnt/9274181773a.../rootfs
# buildah umount 05387e29ab93
# buildah rm 05387e29ab93
05387e29ab93151cf52e9c85c573f3e8ab64af1592b1ff9315db8a10a77d7c22

To remove the image you created previously, you could type the following:

# buildah rmi docker.io/library/myecho:latest
untagged: docker.io/library/myecho:latest
ab230ac5aba3b5a0a7c3d2c5e0793280c1a1b4d2457a75a01b70a4b7a9ed415a

5.4.10. Using container registries with Buildah

With Buildah, you can push and pull container images between your local system and public or private container registries. The following examples show how to:

  • Push containers to and pull them from a private registry with buildah.
  • Push and pull container between your local system and the Docker Registry.
  • Use credentials to associated you containers with a registry account when you push them.

Use the skopeo command, in tandem with the buildah command, to query registries for information about container images.

5.4.10.1. Pushing containers to a private registry

Pushing containers to a private container registry with the buildah command works much the same as pushing containers with the docker command. You need to:

  • Set up a private registry (OpenShift provides a container registry or you can set up a simple registry with the docker-distribution package, as shown below).
  • Create or acquire the container image you want to push.
  • Use buildah push to push the image to the registry.

To install a registry on your local system, start it up, and enable it to start on boot, type:

# yum install -y docker-distribution
# systemctl start docker-distribution
# systemctl enable docker-distribution

By default, the docker-distribution service listens on TCP port 5000 on your localhost.

To push an image from your local Buildah container storage, check the image name, then push it it using the buildah push command. Remember to identify both the local image name and a new name that includes the location (localhost:5000, in this case):

# buildah images
IMAGE ID     IMAGE NAME                       CREATED AT          SIZE
cb702d492ee9 docker.io/library/myecho2:latest Nov 21, 2017 16:50     3.143 KB
# buildah push --tls-verify=false myecho2:latest localhost:5000/myecho2:latest
Getting image source signatures
Copying blob sha256:e4efd0...
...
Writing manifest to image destination
Storing signatures

Use the curl command to list the images in the registry and skopeo to inspect metadata about the image:

# curl http://localhost:5000/v2/_catalog
{"repositories":["myatomic","myecho2"]}
# curl http://localhost:5000/v2/myecho2/tags/list
{"name":"myecho2","tags":["latest"]}
# skopeo inspect --tls-verify=false docker://localhost:5000/myecho2:latest | less
{
    "Name": "localhost:5000/myecho2",
    "Digest": "sha256:8999ff6050...",
    "RepoTags": [
        "latest"
    ],
    "Created": "2017-11-21T16:50:25.830343Z",
    "DockerVersion": "",
    "Labels": {
        "architecture": "x86_64",
        "authoritative-source-url": "registry.access.redhat.com",

At this point, any tool that can pull container images from a container registry can get a copy of your pushed image. For example, you could start the docker daemon and try to pull the image so it can be used by the docker command as follows:

# systemctl start docker
# docker pull localhost:5000/myecho2
# docker run localhost:5000/myecho2
This container works!

5.4.10.2. Pushing containers to the Docker Hub

You can use your Docker Hub credentials to push and pull images from the Docker Hub with the buildah command. For this example, replace the username and password (testaccountXX:My00P@sswd) with your own Docker Hub credentials:

# buildah push --creds testaccountXX:My00P@sswd \
     docker.io/library/myecho2:latest docker://testaccountXX/myecho2:latest

As with the private registry, you can then get and run the container from the Docker Hub with either the buildah or docker command:

# docker run docker.io/textaccountXX/myecho2:latest
This container works!
# buildah from docker.io/textaccountXX/myecho2:latest
myecho2-working-container-2
# buildah run myecho2-working-container-2
This container works!