Chapter 1. Get Started with Linux Containers

1.1. Overview

Linux Containers have emerged as a key open source application packaging and delivery technology, combining lightweight application isolation with the flexibility of image-based deployment methods.

Red Hat Enterprise Linux implements Linux Containers using core technologies such as Control Groups (Cgroups) for Resource Management, Namespaces for Process Isolation, SELinux for Security, enabling secure multi-tenancy and reducing the risk of security exploits. All this is meant to provide you with an environment for producing and running enterprise-quality containers.

Red Hat OpenShift provides powerful command-line and Web UI tools for building, managing and running containers in units referred to as pods. However, sometimes you might want to build and manage individual containers and images outside of OpenShift. Some tools provided to perform those tasks that run directly on RHEL systems are described in this guide.

Unlike other container tools implementations, tools described here do not center around the monolithic Docker container engine and docker command. Instead, we provide a set of command-line tools that can operate without a container engine. These include:

  • podman - For directly managing pods and container images (run, stop, start, ps, attach, exec, and so on)
  • buildah - For building, pushing and signing container images
  • skopeo - For copying, inspecting, deleting, and signing images
  • runc - For providing container run and build features to podman and buildah

Because these tools are compatible with the Open Container Initiative (OCI), they can be used to manage the same Linux containers that are produced and managed by Docker and other OCI-compatible container engines. However, they are especially suited to run directly on Red Hat Enterprise Linux, in single-node use cases.

For a multi-node container platform, see OpenShift. Instead of relying on the single-node, daemonless tools described in this document, OpenShift requires a daemon-based container engine. Please see Using the CRI-O Container Engine for details.

While this guide introduces you to container tools and images, see Managing Containers for more details on those tools.

If you are still interested in using the docker command and docker service, refer to Using the docker command and service for information on how to use those features in RHEL 7.

1.2. Background

Containers provide a means of packaging applications in lightweight, portable entities. Running applications within containers offers the following advantages:

  • Smaller than Virtual Machines: Because container images include only the content needed to run an application, saving and sharing is much more efficient with containers than it is with virtual machines (which include entire operating systems)
  • Improved performance: Likewise, since you are not running an entirely separate operating system, a container will typically run faster than an application that carries with it the overhead of a whole new virtual machine.
  • Secure: Because a container typically has its own network interfaces, file system, and memory, the application running in that container can be isolated and secured from other activities on a host computer.
  • Flexible: With an application’s run time requirements included with the application in the container, a container is capable of being run in multiple environments.

Currently, you can run containers on Red Hat Enterprise Linux 7 (RHEL 7) Server, Workstation, and Atomic Host systems. If you are unfamiliar with RHEL Atomic Host, you can learn more about it from RHEL Atomic Host 7 Installation and Configuration Guide or the upstream Project Atomic site. Project Atomic produces smaller derivatives of RPM-based Linux distributions (RHEL, Fedora, and CentOS) that is made specifically to run containers in OpenStack, VirtualBox, Linux KVM and several different cloud environments.

This topic will help you get started with containers in RHEL 7 and RHEL Atomic Host. Besides offering you some hands-on ways of trying out containers, it also describes how to:

  • Access RHEL-based container images from the Red Hat Registry
  • Incorporate RHEL-entitled software into your containers

1.3. Supported Architectures for Containers on RHEL

Red Hat provides container images and container-related software for the following architectures:

  • X86 64-bit (base and layered images) (no support for X86 32-bit)
  • PowerPC 8 64-bit (base image and most layered images)
  • PowerPC 9 64-bit (base image and most layered images)
  • IBM s390x (base image and most layered images)
  • ARM 64-bit (base image only, separate container repo)
Note

Container images for all architectures are available from the same repository in the Red Hat Registry, with one exception. ARM 64-bit images are available from the rhel7-aarch64 repo in the Red Hat Registry. Currently, only the rhel base image is available with the ARM architecture: registry.redhat.io/rhel7-aarch64

For RHEL and RHEL Atomic 7.5.3, many of the Red Hat-supported container images that were available only on X86_64 became available in the other supported architectures as well. These images are described in this guide and the Managing Containers Guide. Table 1 notes which Red Hat container images are supported on each architecture.

Table 1.1. Red Hat container images and supported architectures

Image name

X86_64

PowerPC 8 & 9

s390x

ARM 64

rhel7/flannel

Yes

No

No

No

rhel7/ipa-server

Yes

No

No

No

rhel7/open-vm-tools

Yes

No

No

No

rhel7/rhel-tools

Yes

No

No

No

rhel7/support-tools

Yes

No

No

No

rhel7/rhel

Yes

Yes

Yes

No

rhel7-init

Yes

Yes

Yes

No

rhel7/net-snmp

Yes

Yes

Yes

No

rhel7/sssd

Yes

Yes

Yes

No

rhel7/sadc

Yes

Yes

Yes

No

rhel7/etcd

Yes

Yes

Yes

No

rhel7/rsyslog

Yes

Yes

Yes

No

rhel7/cockpit-ws

Yes

Yes

Yes

No

rhel7-minimal / rhel7-atomic

Yes

Yes

Yes

No

rhel7/openscap

Yes

Yes

Yes

No

rhel7-aarch64

No

No

No

Yes

As you use the Red Hat containers on the different architectures, you should be aware of a few issues:

  • The Power 8 and Power 9 base image was originally referred to as rhel7-ppc64le. That image name will be retired in RHEL 7.6. For RHEL 7.5.2 and later, simply refer to it as rhel7/rhel.
  • There is no RHEL Atomic Host installation medium available for IBM Power or s390x systems. You must use installation media from Red Hat that provides the IBM Power or s390x versions of RHEL Server.
  • The container-related software repositories that you enable with subscription-manager are different for X86_64 systems, Power, ARM, and s390x systems. See the Table 2 for the repository names to use in place of the X86_64 repository names for Power, ARM, and s390x systems.

Table 1.2. RHEL Server container-related software repos for different architectures

Repository Name

Description

Power 8

Red Hat Enterprise Linux Server

rhel-7-for-power-le-rpms

Red Hat Enterprise Linux 7 for IBM Power LE (RPMs)

rhel-7-for-power-le-debug-rpms

Red Hat Enterprise Linux 7 for IBM Power LE (Debug RPMs)

rhel-7-for-power-le-source-rpms

Red Hat Enterprise Linux 7 for IBM Power LE (Source RPMs)

rhel-7-for-power-le-extras-rpms

Red Hat Enterprise Linux 7 for IBM Power LE - Extras (RPMs)

rhel-7-for-power-le-extras-debug-rpms

Red Hat Enterprise Linux 7 for IBM Power LE - Extras (Debug RPMs)

rhel-7-for-power-le-extras-source-rpms

Red Hat Enterprise Linux 7 for IBM Power LE - Extras (Source RPMs)

rhel-7-for-power-le-optional-rpms

Red Hat Enterprise Linux 7 for IBM Power LE - Optional (RPMs)

rhel-7-for-power-le-optional-debug-rpms

Red Hat Enterprise Linux 7 for IBM Power LE - Optional (Debug RPMs)

rhel-7-for-power-le-optional-source-rpms

Red Hat Enterprise Linux 7 for IBM Power LE - Optional (Source RPMs)

Power 9

Red Hat Enterprise Linux Server

rhel-7-for-power-9-rpms

Red Hat Enterprise Linux 7 for IBM Power 9 (RPMs)

rhel-7-for-power-9-debug-rpms

Red Hat Enterprise Linux 7 for IBM Power 9 (Debug RPMs)

rhel-7-for-power-9-source-rpms

Red Hat Enterprise Linux 7 for IBM Power 9 (Source RPMs)

rhel-7-for-power-9-extras-rpms

Red Hat Enterprise Linux 7 for IBM Power 9 - Extras (RPMs)

rhel-7-for-power-9-extras-debug-rpms

Red Hat Enterprise Linux 7 for IBM Power 9 - Extras (Debug RPMs)

rhel-7-for-power-9-extras-source-rpms

Red Hat Enterprise Linux 7 for IBM Power 9 - Extras (Source RPMs)

rhel-7-for-power-9-optional-rpms

Red Hat Enterprise Linux 7 for IBM Power 9 - Optional (RPMs)

rhel-7-for-power-9-optional-debug-rpms

Red Hat Enterprise Linux 7 for IBM Power 9 - Optional (Debug RPMs)

rhel-7-for-power-9-optional-source-rpms

Red Hat Enterprise Linux 7 for IBM Power 9 - Optional (Source RPMs)

s390x (RHEL-ALT)

Red Hat Enterprise Linux Server

rhel-7-for-system-z-a-rpms

Red Hat Enterprise Linux 7 for IBM s390x (RPMs)

rhel-7-for-system-z-a-debug-rpms

Red Hat Enterprise Linux 7 for IBM s390x (Debug RPMs)

rhel-7-for-system-z-a-source-rpms

Red Hat Enterprise Linux 7 for IBM s390x (Source RPMs)

rhel-7-for-system-z-a-extras-rpms

Red Hat Enterprise Linux 7 for IBM s390x - Extras (RPMs)

rhel-7-for-system-z-a-extras-debug-rpms

Red Hat Enterprise Linux 7 for IBM s390x - Extras (Debug RPMs)

rhel-7-for-system-z-a-extras-source-rpms

Red Hat Enterprise Linux 7 for IBM s390x - Extras (Source RPMs)

rhel-7-for-system-z-a-extras-optional-rpms

Red Hat Enterprise Linux 7 for IBM s390x - Optional (RPMs)

rhel-7-for-system-z-a-extras-optional-debug-rpms

Red Hat Enterprise Linux 7 for IBM s390x - Optional (Debug RPMs)

rhel-7-for-system-z-a-extras-optional-source-rpms

Red Hat Enterprise Linux 7 for IBM s390x - Optional (Source RPMs)

ARM (RHEL-ALT)

Red Hat Enterprise Linux Server

rhel-7-for-arm-64-rpms

Red Hat Enterprise Linux 7 for ARM (RPMs)

rhel-7-for-arm-64-debug-rpms

Red Hat Enterprise Linux 7 for ARM (Debug RPMs)

rhel-7-for-arm-64-source-rpms

Red Hat Enterprise Linux 7 for ARM (Source RPMs)

rhel-7-for-arm-64-extras-rpms

Red Hat Enterprise Linux 7 for ARM - Extras (RPMs)

rhel-7-for-arm-64-extras-debug-rpms

Red Hat Enterprise Linux 7 for ARM - Extras (Debug RPMs)

rhel-7-for-arm-64-extras-source-rpms

Red Hat Enterprise Linux 7 for ARM - Extras (Source RPMs)

rhel-7-for-arm-64-extras-optional-rpms

Red Hat Enterprise Linux 7 for ARM - Optional (RPMs)

rhel-7-for-arm-64-extras-optional-debug-rpms

Red Hat Enterprise Linux 7 for ARM - Optional (Debug RPMs)

rhel-7-for-arm-64-extras-optional-source-rpms

Red Hat Enterprise Linux 7 for ARM - Optional (Source RPMs)

1.4. Getting container tools in RHEL 7

To get an environment where you can work with individual containers, you can install a Red Hat Enterprise Linux 7 system. Using the RHEL 7 subscription model, if you want to create images or containers, you must properly register and entitle the host computer on which you build them. When you use yum install within a container to add packages, the container automatically has access to entitlements available from the RHEL 7 host, so it can get RPM packages from any repository enabled on that host.

  1. Install RHEL: If you are ready to begin, you can start by installing a Red Hat Enterprise Linux system (Workstation or Server edition) as described in the following: Red Hat Enterprise Linux 7 Installation Guide

    Note

    Running containers on RHEL 7 Workstations has some limitations:

    • Standard single-user, single-node rules apply to running containers on RHEL Workstations.
    • Only Universal Base Image (UBI) content is supported when you build containers on RHEL workstations. In other words, you cannot include RHEL Server RPMS.
    • You can run containers supported by third party ISVs, such as compilers.
  2. Register RHEL: Once RHEL 7 is installed, register the system. You will be prompted to enter your user name and password. Note that the user name and password are the same as your login credentials for Red Hat Customer Portal.

    # subscription-manager register
    Registering to: subscription.rhsm.redhat.com:443/subscription
    Username: ********
    Password: **********
  3. Choose pool ID: Determine the pool ID of a subscription that includes Red Hat Enterprise Linux Server. Type the following at a shell prompt to display a list of all subscriptions that are available for your system, then attach the pool ID of one that meets that requirement:

    # subscription-manager list --available    Find valid RHEL pool ID
    # subscription-manager attach --pool=pool_id
  4. Enable repositories: Enable the following repositories, which will allow you to install the docker package and related software:

    NOTE: The repos shown here are for X86_64 architectures. See Supported Architectures for Containers on RHEL to learn the names of repositories for other architectures.

    # subscription-manager repos --enable=rhel-7-server-rpms
    # subscription-manager repos --enable=rhel-7-server-extras-rpms
    # subscription-manager repos --enable=rhel-7-server-optional-rpms

    It is possible that some Red Hat subscriptions include enabled repositories that can conflict with eachother. If you believe that has happened, before enabling the repos shown above, you can disable all repos. See the How are repositories enabled solution for information on how to disable unwanted repositories.

  5. Install packages: To install the podman, skopeo, and buildah packages, type the following:

    # yum install podman skopeo buildah -y

1.5. Enabling container settings

No container engine (such as Docker or CRI-O) is required for you to run containers on your local system. However, configuration settings in the /etc/containers/registries.conf file let you define access to container registries when you work with container tools such as podman and buildah.

Here are example settings in the /etc/containers/registries.conf file:

[registries.search]
registries = ['registry.access.redhat.com', 'docker.io', 'registry.fedoraproject.org', 'quay.io', 'registry.centos.org']

[registries.insecure]
registries = []

[registries.block]
registries = []

By default, when you use podman search to search for images from a container registries, based on the registries.conf file, podman looks for the requested image in registry.access.redhat.com, docker.io, registry.fedoraproject.org, docker.io, and registry.centos.org in that order.

To add access to a registry that doesn’t require authentication (an insecure registry), you must add the name of that registry under the [registries.insecure] section. Any registries that you want to disallow from access from your local system need to be added under the [registries.block] section.

1.6. Using containers as root or rootless

At first, root privilege (either as the root user or as a regular user with sudo privilege) was required to work with container tools in RHEL. As of RHEL 7.7, the rootless container feature (currently a Technology Preview) lets regular user accounts work with containers. All container tools described in this document can be run as root user. For restrictions on running these from regular user accounts, see the rootless containers section of the Managing Containers guide.

1.7. Working with container images

Using podman, you can run, investigate, start, stop, and remove container images. If you are familiar with the docker command, you will notice that you can use the same syntax with podman to work with containers and container images.

1.7.1. Getting images from registries

To get images from a remote registry (such as Red Hat’s own Docker registry) and add them to your local system, use the podman pull command:

# podman pull <registry>[:<port>]/[<namespace>/]<name>:<tag>

The <registry> is a host that provides the registry service on TCP <port> (default: 5000). Together, <namespace> and <name> identify a particular image controlled by <namespace> at that registry. Some registries also support raw <name>; for those, <namespace> is optional. When it is included, however, the additional level of hierarchy that <namespace> provides is useful to distinguish between images with the same <name>. For example:

NamespaceExamples (<namespace>/<name>)

organization

redhat/kubernetes, google/kubernetes

login (user name)

alice/application, bob/application

role

devel/database, test/database, prod/database

The registries that Red Hat supports are registry.redhat.io (requiring authentication) and registry.access.redhat.com (requires no authentication, but is deprecated). For details on the transition to registry.redhat.io, see Red Hat Container Registry Authentication . Before you can pull containers from registry.redhat.io, you need to authenticate. For example:

# podman login registry.redhat.io
Username: myusername
Password: ************
Login Succeeded!

To get started with container images, you can use the pull option to pull an image from a remote registry. To pull the RHEL 7 UBI base image and rsyslog image from the Red Hat registry, type:

# podman pull registry.access.redhat.com/ubi7/ubi
# podman pull registry.access.redhat.com/rhel7/rsyslog

An image is identified by a repository name (registry.access.redhat.com), a namespace name (rhel7) and the image name (rsyslog). You could also add a tag (which defaults to :latest if not entered). The repository name rhel7, when passed to the podman pull command without the name of a registry preceding it, is ambiguous and could result in the retrieval of an image that originates from an untrusted registry. If there are multiple versions of the same image, adding a tag, such as latest to form a name such as rsyslog:latest, lets you choose the image more explicitly.

To see the images that resulted from the above podman pull command, along with any other images on your system, type podman images:

# podman images
REPOSITORY
             TAG        IMAGE ID      CREATED       VIRTUAL SIZE
registry.access.redhat.com/rhel7/rsyslog
             latest     39ec6b2004a3  9 days ago    236 MB
registry.access.redhat.com/ubi7/ubi
             latest     967cb403b7ee  3 days ago     215 MB

1.7.2. Investigating images

Using podman images you can see which images have been pulled to your local system. To look at the metadata associated with an image, use podman inspect.

1.7.2.1. Listing images

To see which images have been pulled to your local system and are available to use, type:

# podman images
REPOSITORY                                            TAG    IMAGE ID     CREATED      VIRTUAL SIZE
registry.access.redhat.com/rhel7/rsyslog              latest 39ec6b2004a3 10 days ago  236 MB
registry.access.redhat.com/ubi7/ubi                   latest 967cb403b7ee 10 days ago  215 MB
registry.access.redhat.com/rhscl/postgresql-10-rhel7  1-35   27b15d85ca6b 3 months ago 336 MB

1.7.2.2. Inspecting local images

After you pull an image to your local system and before you run it, it is a good idea to investigate that image. Reasons for investigating an image before you run it include:

  • Understanding what the image does
  • Checking what software is inside the image

The podman inspect command displays basic information about what an image does. You also have the option of mounting the image to your host system and using tools from the host to investigate what’s in the image. Here is an example of investigating what a container image does before you run it:

  1. Inspect an image: Run podman inspect to see what command is executed when you run the container image, as well as other information. Here are examples of examining the ubi7/ubi and rhel7/rsyslog container images (with only snippets of information shown here):

    # podman inspect registry.access.redhat.com/ubi7/ubi
    ...
    Cmd": [
             "/bin/bash"
             ],
             "Labels": {
                "architecture": "x86_64",
                "authoritative-source-url": "registry.access.redhat.com",
                "build-date": "2019-08-01T09:28:54.576292",
                "com.redhat.build-host": "cpt-1007.osbs.prod.upshift.rdu2.redhat.com",
                "com.redhat.component": "ubi7-container",
                "com.redhat.license_terms": "https://www.redhat.com/en/about/red-hat-end-user-license-agreements#UBI",
                "description": "The Universal Base Image is designed and engineered to be ...
    ...
    # podman inspect registry.access.redhat.com/rhel7/rsyslog
       "Cmd": [
         "/bin/rsyslog.sh"
       ],
       "Labels": {
         "License": "GPLv3",
         "architecture": "x86_64",
    ...
         "install": "docker run --rm --privileged -v /:/host -e HOST=/host \
            -e IMAGE=IMAGE -e NAME=NAME IMAGE /bin/install.sh",
    
    ...
         "run": "docker run -d --privileged --name NAME --net=host --pid=host \
            -v /etc/pki/rsyslog:/etc/pki/rsyslog -v /etc/rsyslog.conf:/etc/rsyslog.conf \
            -v /etc/sysconfig/rsyslog:/etc/sysconfig/rsyslog -v /etc/rsyslog.d:/etc/rsyslog.d \
            -v /var/log:/var/log -v /var/lib/rsyslog:/var/lib/rsyslog -v /run:/run \
            -v /etc/machine-id:/etc/machine-id -v /etc/localtime:/etc/localtime \
            -e IMAGE=IMAGE -e NAME=NAME --restart=always IMAGE /bin/rsyslog.sh",
         "summary": "A containerized version of the rsyslog utility
    ...

    The ubi7/ubi container will execute the bash shell, if no other argument is given when you start it with podman run. If an Entrypoint were set, its value would be used instead of the Cmd value (and the value of Cmd would be used as an argument to the Entrypoint command).

    In the second example, the rhel7/rsyslog container image has built-in install and run labels. Those labels give an indication of how the container is meant to be set up on the system (install) and executed (run). You would use the podman command instead of docker.

  2. Mount a container: Using the podman command, mount an active container to further investigate its contents. This example runs and lists a running rsyslog container, then displays the mount point from which you can examine the contents of its file system:

    # podman run -d registry.access.redhat.com/rhel7/rsyslog
    # podman ps
    CONTAINER ID IMAGE             COMMAND         CREATED        STATUS      PORTS NAMES
    1cc92aea398d ...rsyslog:latest /bin/rsyslog.sh 37 minutes ago Up 1 day ago      myrsyslog
    # podman mount 1cc92aea398d
    /var/lib/containers/storage/overlay/65881e78.../merged
    # ls /var/lib/containers/storage/overlay/65881e78*/merged
    bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

    After running the podman mount command, the contents of the container are accessible from the listed directory on the host. Use ls to explore the contents of the image.

  3. Check the image’s package list: To check the packages installed in the container, tell the rpm command to examine the packages installed on the container’s mount point:

    # rpm -qa --root=/var/lib/containers/storage/overlay/65881e78.../merged
    redhat-release-server-7.6-4.el7.x86_64
    filesystem-3.2-25.el7.x86_64
    basesystem-10.0-7.el7.noarch
    ncurses-base-5.9-14.20130511.el7_4.noarch
    glibc-common-2.17-260.el7.x86_64
    nspr-4.19.0-1.el7_5.x86_64
    libstdc++-4.8.5-36.el7.x86_64

1.7.2.3. Inspecting remote images

To inspect a container image before you pull it to your system, you can use the skopeo inspect command. With skopeo inspect, you can display information about an image that resides in a remote container registry.

The following command inspects the rhel-init image from the Red Hat registry:

# skopeo inspect docker://registry.access.redhat.com/ubi7/ubi
   {
    "Name": "registry.access.redhat.com/ubi7/ubi",
    "Digest": "sha256:caf8d01ac73911f872d184a73a5e72a1eeb7bba733cbad13e8253b567d16899f",
    "RepoTags": [
        "latest",
        "7.6",
        "7.7"
    ],
    "Created": "2019-08-01T09:29:20.753891Z",
    "DockerVersion": "1.13.1",
    "Labels": {
        "architecture": "x86_64",
        "authoritative-source-url": "registry.access.redhat.com",
        "build-date": "2019-08-01T09:28:54.576292",
        "com.redhat.build-host": "cpt-1007.osbs.prod.upshift.rdu2.redhat.com",
        "com.redhat.component": "ubi7-container",

1.7.3. Tagging images

You can add names to images to make it more intuitive to understand what they contain. Tagging images can also be used to identify the target registry for which the image is intended. Using the podman tag command, you essentially add an alias to the image that can consist of several parts. Those parts can include:

registryhost/username/NAME:tag

You can add just NAME if you like. For example:

# podman tag 967cb403b7ee myrhel7

Using podman tag, the name myrhel7 now also is attached to the ubi7/ubi image (image ID 967cb403b7ee) on your system. So you could run this container by name (myrhel7) or by image ID. Notice that without adding a :tag to the name, it was assigned :latest as the tag. You could have set the tag to 7.7 as follows:

# podman tag 967cb403b7ee myrhel7:7.7

To the beginning of the name, you can optionally add a user name and/or a registry name. The user name is actually the repository on Docker.io or other registry that relates to the user account that owns the repository. Here’s an example of adding a user name:

# podman tag 967cb403b7ee jsmith/myrhel7
# podman images | grep 967cb403b7ee
localhost/jsmith/myrhel7             latest  967cb403b7ee   10 days ago  215 MB
localhost/myrhel7                    7.7     967cb403b7ee   10 days ago  215 MB
registry.access.redhat.com/ubi7/ubi  latest  967cb403b7ee   10 days ago  215 MB

Above, you can see all the image names assigned to the single image ID.

1.7.4. Saving and importing images

If you want to save a container image you created, you can use podman save to save the image to a tarball. After that, you can store it or send it to someone else, then reload the image later to reuse it. Here is an example of saving an image as a tarball:

# podman save -o myrsyslog.tar registry.access.redhat.com/rhel7/rsyslog
# ls
myrsyslog.tar

The myrsyslog.tar file should now be stored in your current directory. Later, when you are ready to reuse the tarball as a container image, you can import it to another podman environment as follows:

# cat myrsyslog.tar | podman import - rhel7/myrsyslog
Getting image source signatures
Copying blob baa75547a1df done
Copying config 6722efbc0c done
Writing manifest to image destination
Storing signatures
6722efbc0ce5591161f773ef6371390965dc54212ac710c7517ee6d55eee6485
# podman images | grep myrsyslog
docker.io/rhel7/myrsyslog   latest  6722efbc0ce5  50 seconds ago   236 MB

1.7.5. Removing Images

To see a list of images that are on your system, run the podman images command. To remove images you no longer need, use the podman rmi command, with the image ID or name as an option. (You must stop any containers run from an image before you can remove the image.) Here is an example:

# podman rmi rhel-init
7e85c34f126351ccb9d24e492488ba7e49820be08fe53bee02301226f2773293

You can remove multiple images on the same command line:

# podman rmi registry.access.redhat.com/rhel7/rsyslog support-tools
46da8e23fa1461b658f9276191b4f473f366759a6c840805ed0c9ff694aa7c2f
85cfba5cd49c84786c773a9f66b8d6fca04582d5d7b921a308f04bb8ec071205

If you want to clear out all your images, you could use a command like the following to remove all images from your local registry (make sure you mean it before you do this!):

# podman rmi $(podman images -a -q)
1ca061b47bd70141d11dcb2272dee0f9ea3f76e9afd71cd121a000f3f5423731
ed904b8f2d5c1b5502dea190977e066b4f76776b98f6d5aa1e389256d5212993
83508706ef1b603e511b1b19afcb5faab565053559942db5d00415fb1ee21e96

To remove images that have multiple names (tags) associated with them, you need to add the force option to remove them. For example:

# podman rmi $(podman images -a -q)
unable to delete eb205f07ce7d0bb63bfe5603ef8964648536963e2eee51a3ebddf6cfe62985f7 (must force) - image is referred to in multiple tags
unable to delete eb205f07ce7d0bb63bfe5603ef8964648536963e2eee51a3ebddf6cfe62985f7 (must force) - image is referred to in multiple tags

# podman rmi -f eb205f07ce7d
eb205f07ce7d0bb63bfe5603ef8964648536963e2eee51a3ebddf6cfe62985f7

1.8. Working with containers

Containers represent a running or stopped process spawned from the files located in a decompressed container image. Tools for running containers and working with them are described in this section.

1.8.1. Running containers

When you execute a podman run command, you essentially spin up and create a new container from a container image. The command you pass on the podman run command line sees the inside the container as its running environment so, by default, very little can be seen of the host system. For example, by default, the running applications sees:

  • The file system provided by the container image.
  • A new process table from inside the container (no processes from the host can be seen).

If you want to make a directory from the host available to the container, map network ports from the container to the host, limit the amount of memory the container can use, or expand the CPU shares available to the container, you can do those things from the podman run command line. Here are some examples of podman run command lines that enable different features.

EXAMPLE #1 (Run a quick command): This podman command runs the cat /etc/os-release command to see the type of operating system used as the basis for the container. After the container runs the command, the container exits and is deleted (--rm).

# podman run --rm registry.access.redhat.com/ubi7/ubi cat /etc/os-release
NAME="Red Hat Enterprise Linux Server"
VERSION="7.7 (Maipo)"
ID="rhel"
ID_LIKE="fedora"
VARIANT="Server"
VARIANT_ID="server"
VERSION_ID="7.7"
PRETTY_NAME="Red Hat Enterprise Linux Server 7.7 (Maipo)"
...

EXAMPLE #2 (View the Dockerfile in the container): This is another example of running a quick command to inspect the content of a container from the host. All layered images that Red Hat provides include the Dockerfile from which they are built in /root/buildinfo. In this case you do not need to mount any volumes from the host.

# podman run --rm registry.access.redhat.com/ubi7/ubi ls /root/buildinfo
Dockerfile-ubi7-7.7-99

Now you know what the Dockerfile is called, you can list its contents:

# podman run --rm registry.access.redhat.com/ubi7/ubi \
    cat /root/buildinfo/Dockerfile-ubi7-7.7-99
FROM sha256:94577870ec362083c6513cfadb00672557fc5dd360e67befde6c81b9b753d06e
RUN mv -f /etc/yum.repos.d/ubi.repo /tmp || :

MAINTAINER Red Hat, Inc.

LABEL com.redhat.component="ubi7-container"
LABEL name="ubi7"
LABEL version="7.7"
...

EXAMPLE #3 (Run a shell inside the container): Using a container to launch a bash shell lets you look inside the container and change the contents. This sets the name of the container to mybash. The -i creates an interactive session and -t opens a terminal session. Without -i, the shell would open and then exit. Without -t, the shell would stay open, but you wouldn’t be able to type anything to the shell.

Once you run the command, you are presented with a shell prompt and you can start running commands from inside the container:

# podman run --name=mybash -it registry.access.redhat.com/ubi7/ubi /bin/bash
[root@ed904b8f2d5c/]#  yum install nmap
[root@ed904b8f2d5c/]#  ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 00:46 pts/0    00:00:00 /bin/bash
root        35     1  0 00:51 pts/0    00:00:00 ps -ef
[root@49830c4f9cc4/]# exit

Although the container is no longer running once you exit, the container still exists with the new software package still installed. Use podman ps -a to list the container:

# podman ps -a
CONTAINER ID IMAGE                 COMMAND   CREATED        STATUS                PORTS NAMES        IS INFRA
1ca061b47bd7 .../ubi8/ubi:latest   /bin/bash 8 minutes ago  Exited 12 seconds ago       musing_brown false
...

You could start that container again using podman start with the -ai options. For example:

# podman start -ai mybash
[root@ed904b8f2d5c/]#

EXAMPLE #4 (Bind mounting log files): One way to make log messages from inside a container available to the host system is to bind mount the host’s /dev/log device inside the container. This example illustrates how to run an application in a RHEL container that is named log_test that generates log messages (just the logger command in this case) and directs those messages to the /dev/log device that is mounted in the container from the host. The --rm option removes the container after it runs.

# podman run --name="log_test" -v /dev/log:/dev/log --rm \
     registry.access.redhat.com/ubi7/ubi logger "Testing logging to the host"
# journalctl -b | grep Testing
Aug 11 18:22:48 rhel76_01 root[6237]: Testing logging to the host

1.8.2. Investigating running and stopped containers

After you have some running container, you can list both those containers that are still running and those that have exited or stopped with the podman ps command. You can also use the podman inspect to look at specific pieces of information within those containers.

1.8.2.1. Listing containers

Let’s say you have one or more containers running on your host. To work with containers from the host system, you can open a shell and try some of the following commands.

podman ps: The ps option shows all containers that are currently running:

# podman run -d registry.access.redhat.com/rhel7/rsyslog
# podman ps
CONTAINER ID IMAGE          COMMAND         CREATED       STATUS            PORTS NAMES
50e5021715e4 rsyslog:latest /bin/rsyslog.sh 5 seconds ago Up 3 seconds ago  epic_torvalds

If there are containers that are not running, but were not removed (--rm option), the containers are still hanging around and can be restarted. The podman ps -a command shows all containers, running or stopped.

# podman ps -a
CONTAINER ID IMAGE           COMMAND    CREATED        STATUS                   PORTS NAMES
86a6f6962042 ubi7/ubi:latest /bin/bash  11 minutes ago Exited (0) 6 minutes ago       mybash

1.8.2.2. Inspecting containers

To inspect the metadata of an existing container, use the podman inspect command. You can show all metadata or just selected metadata for the container. For example, to show all metadata for a selected container, type:

# podman inspect 50e5021715e4
    ...
[
    {
        "Id": "50e5021715e4829a3a37255145056ba0dc634892611a2f1d71c647cf9c9aa1d5",
        "Created": "2019-08-11T18:27:55.493059669-04:00",
        "Path": "/bin/rsyslog.sh",
        "Args": [
            "/bin/rsyslog.sh"
        ],
        "State": {
            "OciVersion": "1.0.1-dev",
            "Status": "running",
            "Running": true,
    ...

You can also use inspect to pull out particular pieces of information from a container. The information is stored in a hierarchy. So to see the container’s IP address (IPAddress under NetworkSettings), use the --format option and the identity of the container. For example:

# podman inspect --format='{{.NetworkSettings.IPAddress}}' 50e5021715e4
10.88.0.36

Examples of other pieces of information you might want to inspect include .Path (to see the command run with the container), .Args (arguments to the command), .Config.ExposedPorts (TCP or UDP ports exposed from the container), .State.Pid (to see the process id of the container) and .HostConfig.PortBindings (port mapping from container to host). Here’s an example of .State.Pid and .State.StartedAt:

# podman inspect --format='{{.State.Pid}}' 50e5021715e4
7544
# ps -ef | grep 7544
root     7544 7531  0 10:30 ?        00:00:00 /usr/sbin/rsyslogd -n
# podman inspect --format='{{.State.StartedAt}}' 50e5021715e4
2019-08-11 18:27:57.946930227 -0400 EDT

In the first example, you can see the process ID of the containerized executable on the host system (PID 7544). The ps -ef command confirms that it is the rsyslogd daemon running. The second example shows the date and time that the container was run.

1.8.2.3. Investigating within a container

To investigate within a running container, you can use the podman exec command. With podman exec, you can run a command (such as /bin/bash) to enter a running container process to investigate that container.

The reason for using podman exec, instead of just launching the container into a bash shell, is that you can investigate the container as it is running its intended application. By attaching to the container as it is performing its intended task, you get a better view of what the container actually does, without necessarily interrupting the container’s activity.

Here is an example using podman exec to look into a running rsyslog, then look around inside that container.

  1. Launch a container: Launch a container such the rsyslog container image described earlier. Type podman ps to make sure it is running:

    # podman ps
    CONTAINER ID   IMAGE           COMMAND           CREATED       STATUS        PORTS   NAMES
    50e5021715e4   rsyslog:latest "/usr/rsyslog.sh   6 minutes ago Up 6 minutes          rsyslog
  2. Enter the container with podman exec: Use the container ID or name to open a bash shell to access the running container. Then you can investigate the attributes of the container as follows:

    # podman exec -it 50e5021715e4 /bin/bash
    [root@50e5021715e4 /]# cat /etc/redhat-release
    Red Hat Enterprise Linux release 7.7 (Maipo)
    [root@50e5021715e4 /]# ps -ef
    UID        PID  PPID  C STIME TTY          TIME CMD
    root         1     0  0 15:30 ?        00:00:00 /usr/sbin/rsyslogd -n
    root         8     0  6 16:01 pts/0    00:00:00 /bin/bash
    root        21     8  0 16:01 pts/0    00:00:00 ps -ef
    [root@50e5021715e4 /]# df -h
    Filesystem      Size  Used Avail Use% Mounted on
    overlay          39G  2.5G   37G   7% /
    tmpfs            64M     0   64M   0% /dev
    tmpfs           1.5G  8.7M  1.5G   1% /etc/hosts
    shm              63M     0   63M   0% /dev/shm
    tmpfs           1.5G     0  1.5G   0% /sys/fs/cgroup
    tmpfs           1.5G     0  1.5G   0% /proc/acpi
    tmpfs           1.5G     0  1.5G   0% /proc/scsi
    tmpfs           1.5G     0  1.5G   0% /sys/firmware
    tmpfs           1.5G     0  1.5G   0% /sys/fs/selinux
    [root@50e5021715e4 /]# uname -r
    3.10.0-957.27.2.el7.x86_64
    [root@50e5021715e4 /]# rpm -qa | more
    tzdata-2019b-1.el7.noarch
    setup-2.8.71-10.el7.noarch
    basesystem-10.0-7.el7.noarch
    ncurses-base-5.9-14.20130511.el7_4.noarch
    ...
    bash-4.2# free -m
                  total        used        free      shared  buff/cache   available
    Mem:           7792        2305        1712          18        3774        5170
    Swap:          2047           0        2047
    
    [root@50e5021715e4 /]# exit

The commands just run from the bash shell (running inside the container) show you several things.

  • The container was built from a RHEL release 7.7 image.
  • The process table (ps -ef) shows that the /usr/sbin/rsyslogd command is process ID 1.
  • Processes running in the host’s process table cannot be seen from within the container. Although the rsyslogd process can be seen on the host process table (it was process ID 7544 on the host).
  • There is no separate kernel running in the container (uname -r shows the host system’s kernel).
  • The rpm -qa command lets you see the RPM packages that are included inside the container. In other words, there is an RPM database inside of the container.
  • Viewing memory (free -m) shows the available memory on the host (although what the container can actually use can be limited using cgroups).

1.8.3. Starting and stopping containers

If you ran a container, but didn’t remove it (--rm), that container is stored on your local system and ready to run again. To start a previously run container that wasn’t removed, use the start option. To stop a running container, use the stop option.

1.8.3.1. Starting containers

A container that doesn’t need to run interactively can sometimes be restarted after being stopped with only the start option and the container ID or name. For example:

# podman start myrhel_httpd
myrhel_httpd

To start a container so you can work with it from the local shell, use the -a (attach) and -i (interactive) options. Once the bash shell starts, run the commands you want inside the container and type exit to kill the shell and stop the container.

# podman start -a -i agitated_hopper
[root@d65aecc325a4 /]#  exit

1.8.3.2. Stopping containers

To stop a running container that is not attached to a terminal session, use the stop option and the container ID or number. For example:

# podman stop 74b1da000a11
74b1da000a114015886c557deec8bed9dfb80c888097aa83f30ca4074ff55fb2

The stop option sends a SIGTERM signal to terminate a running container. If the container doesn’t stop after a grace period (10 seconds by default), podman sends a SIGKILL signal. You could also use the podman kill command to kill a container (SIGKILL) or send a different signal to a container. Here’s an example of sending a SIGHUP signal to a container (if supported by the application, a SIGHUP causes the application to re-read its configuration files):

# podman kill --signal="SIGHUP" 74b1da000a11
74b1da000a114015886c557deec8bed9dfb80c888097aa83f30ca4074ff55fb2

1.8.4. Removing containers

To see a list of containers that are still hanging around your system, run the podman ps -a command. To remove containers you no longer need, use the podman rm command, with the container ID or name as an option. Here is an example:

# podman rm goofy_wozniak

You can remove multiple containers on the same command line:

# podman rm clever_yonath furious_shockley drunk_newton

If you want to clear out all your containers, you could use a command like the following to remove all containers (not images) from your local system (make sure you mean it before you do this!):

# podman rm $(podman ps -a -q)