Chapter 3. Working with containers and pods

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.

3.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 to the podman run command line sees the inside of the container as its running environment so, by default, very little can be seen of the host system. For example, by default, the running application 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.redhat.io/ubi8/ubi cat /etc/os-release
NAME="Red Hat Enterprise Linux"
VERSION="8.2 (Ootpa)"
ID="rhel"
ID_LIKE="fedora"
VERSION_ID="8.2"
PLATFORM_ID="platform:el8"
PRETTY_NAME="Red Hat Enterprise Linux 8.2 (Ootpa)"
ANSI_COLOR="0;31"
CPE_NAME="cpe:/o:redhat:enterprise_linux:8.2:GA"
HOME_URL="https://www.redhat.com/"
BUG_REPORT_URL="https://bugzilla.redhat.com/"

REDHAT_BUGZILLA_PRODUCT="Red Hat Enterprise Linux 8"
REDHAT_BUGZILLA_PRODUCT_VERSION=8.2
REDHAT_SUPPORT_PRODUCT="Red Hat Enterprise Linux"
REDHAT_SUPPORT_PRODUCT_VERSION="8.2"
...

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.redhat.io/rhel8/rsyslog  \
    ls /root/buildinfo
Dockerfile-rhel8-rsyslog-8.2-25

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

# podman run --rm registry.redhat.io/rhel8/rsyslog \
    cat /root/buildinfo/Dockerfile-rhel8-rsyslog-8.2-25
FROM sha256:eb205f07ce7d0bb63bfe560...
LABEL maintainer="Red Hat, Inc."

RUN INSTALL_PKGS="\
rsyslog \
rsyslog-gnutls \
rsyslog-gssapi \
rsyslog-mysql \
rsyslog-pgsql \
rsyslog-relp \
" && dnf -y install $INSTALL_PKGS && rpm -V --nosize
    --nofiledigest --nomtime --nomode $INSTALL_PKGS && dnf clean all
LABEL com.redhat.component="rsyslog-container"
LABEL name="rhel8/rsyslog"
LABEL version="8.2"
...

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 would not 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.redhat.io/ubi8/ubi /bin/bash
[root@ed904b8f2d5c/]#  yum install procps-ng
[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 /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.redhat.io/ubi8/ubi logger "Testing logging to the host"
# journalctl -b | grep Testing
Nov 12 20:00:10 ubi8 root[17210]: Testing logging to the host

EXAMPLE #5 (Run a service as a daemon with a static IP address): The following example runs an rsyslog service as a daemon process, so it runs continuously in the background. It also tells podman to set the container network interface to a particular IP address (for example, 10.88.0.44). After that, you can run podman inspect command to check that the IP address was set properly:

# podman run -d --ip=10.88.0.44 registry.access.redhat.com/rhel7/rsyslog
efde5f0a8c723f70dd5cb5dc3d5039df3b962fae65575b08662e0d5b5f9fbe85
# podman inspect efde5f0a8c723 | grep 10.88.0.44
            "IPAddress": "10.88.0.44",

3.2. Investigating running and stopped containers

After you have some running containers, 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.

3.2.1. Listing containers

Let us 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.redhat.io/rhel8/rsyslog
# podman ps
CONTAINER ID IMAGE              COMMAND         CREATED       STATUS            PORTS NAMES
74b1da000a11 rhel8/rsyslog /bin/rsyslog.sh 2 minutes ago Up About a minute       musing_brown

If there are containers that are not running, but were not removed (--rm option), the containers are present 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     IS INFRA
d65aecc325a4 ubi8/ubi      /bin/bash  3 secs ago Exited (0) 5 secs ago peaceful_hopper false
74b1da000a11 rhel8/rsyslog rsyslog.sh 2 mins ago Up About a minute     musing_brown    false

3.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 74b1da000a11
    ...
  "ID": "74b1da000a114015886c557deec8bed9dfb80c888097aa83f30ca4074ff55fb2",
  "Created": "2018-11-13T10:30:31.884673073-05: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 IP address (IPAddress under NetworkSettings), use the --format option and the identity of the container. For example:

# podman inspect --format='{{.NetworkSettings.IPAddress}}' 74b1da000a11
10.88.0.31

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 is an example of .State.Pid and .State.StartedAt:

# podman inspect --format='{{.State.Pid}}' 74b1da000a11
19593
# ps -ef | grep 19593
root     19593 19583  0 10:30 ?        00:00:00 /usr/sbin/rsyslogd -n
# podman inspect --format='{{.State.StartedAt}}' 74b1da000a11
2018-11-13 10:30:35.358175255 -0500 EST

In the first example, you can see the process ID of the containerized executable on the host system (PID 19593). 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.

3.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
    74b1da000a11   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 74b1da000a11 /bin/bash
    [root@74b1da000a11 /]# cat /etc/redhat-release
    Red Hat Enterprise Linux release 8.0
    [root@74b1da000a11 /]# yum install procps-ng
    [root@74b1da000a11 /]# 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@74b1da000a11 /]# 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
    [root@74b1da000a11 /]# uname -r
    4.18.0-80.1.2.el8_0.x86_64
    [root@74b1da000a11 /]# rpm -qa | more
    redhat-release-8.0-0.44.el8.x86_64
    filesystem-3.8-2.el8.x86_64
    basesystem-11-5.el8.noarch
    ncurses-base-6.1-7.20180224.el8.noarch
    ...
    bash-4.2# free -m
                  total        used        free      shared  buff/cache   available
    Mem:           1941         560         139          10        1241        1189
    Swap:          1023          15        1008
    [root@74b1da000a11 /]# 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 8.0 image.
  • The process table (ps -ef) shows that the /usr/sbin/rsyslogd command is process ID 1.
  • Processes running in the host 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 19593 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).

3.3. Starting and stopping containers

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

3.3.1. Starting containers

A container that does not 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

3.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 does not 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 is 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

3.4. Sharing files between two containers

You can use volumes to persist data in containers even when a container is deleted. Volumes can be used for sharing data among multiple containers. The volume is a folder which is stored on the host machine. The volume can be shared between the container and the host.

Main advantages are:

  • Volumes can be shared among the containers.
  • Volumes are easier to back up or migrate.
  • Volumes do not increase the size of the containers.

Procedure

  1. To create a volume, enter:

    $ podman volume create hostvolume
  2. To display information about the volume, enter:

    $ podman volume inspect hostvolume
    [
        {
            "name": "hostvolume",
            "labels": {},
            "mountpoint": "/home/username/.local/share/containers/storage/volumes/hostvolume/_data",
            "driver": "local",
            "options": {},
            "scope": "local"
        }
    ]

    Notice that it creates a volume in the volumes directory. You can save the mount point path to the variable for easier manipulation: $ mntPoint=$(podman volume inspect hostvolume --format {{.Mountpoint}}).

    Notice that if you run sudo podman volume create hostvolume, then the mount point changes to /var/lib/containers/storage/volumes/hostroot/_data.

  3. Create a text file inside the directory using the path is stored in the mntPoint variable:

    $ echo "Hello from host" >> $mntPoint/host.txt
  4. List all files in the directory defined by the mntPoint variable:

    $ ls $mntPoint/
    host.txt
  5. Run the container named myubi1 and map the directory defined by the hostvolume volume name on the host to the /containervolume1 directory on the container:

    $ podman run -it --name myubi1 -v hostvolume:/containervolume1 registry.access.redhat.com/ubi8/ubi /bin/bash

    Note that if you use the volume path defined by the mntPoint variable (-v $mntPoint:/containervolume1), data can be lost when running podman volume prune command, which removes unused volumes. Always use -v hostvolume_name:/containervolume_name.

  6. List the files in the shared volume on the container:

    # ls /containervolume1
    host.txt

    You can see the host.txt file which you created on the host.

  7. Create a text file inside the /containervolume1 directory:

    # echo "Hello from container 1" >> /containervolume1/container1.txt
  8. Detach from the container with CTRL+p and CTRL+q.
  9. List the files in the shared volume on the host, you should see two files:

    $ ls $mntPoint
    container1.rxt  host.txt

    At this point, you are sharing files between the container and host. To share files between two containers, run another container named myubi2. Steps 10 - 13 are analogous to steps 5 - 8.

  10. Run the container named myubi2 and map the directory defined by the hostvolume volume name on the host to the /containervolume2 directory on the container:

    $ podman run -it --name myubi2 -v hostvolume:/containervolume2 registry.access.redhat.com/ubi8/ubi  /bin/bash
  11. List the files in the shared volume on the container:

    # ls /containervolume2
    container1.txt host.txt

    You can see the host.txt file which you created on the host and container1.txt which you created inside the myubi1 container.

  12. Create a text file inside the /containervolume2 directory:

    # echo "Hello from container 2" >> /containervolume2/container2.txt
  13. Detach from the container with CTRL+p and CTRL+q.
  14. List the files in the shared volume on the host, you should see three files:

    $ ls $mntPoint
    container1.rxt  container2.txt host.txt
  15. To stop and remove both containers, enter:

    $ podman stop myubi1
    $ podman stop myubi2
    $ podman rm myubi1
    $ podman rm myubi2
  16. To remove the host volume, enter:

    $ podman volume rm hostvolume
  17. To check that you deleted the volume, enter:

    $ podman volume ls

Additional resources

  • For more information on the podman volume command, type man podman-volume.

3.5. 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. You should stop any containers that are still running before removing them. 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 -a
56c496350bd534da7620fe2fa660526a6fc7f1c57b0298291cd2210311fe723b
83ad58c17b20f9e8271171f3023ae094dbfab6ce5708344a68feb121916961ca
a93b696a1f5629300382a8ce860c4ba42f664db98101e82c2dbcc2074b428faf
bee71e61b53bd8b036b2e8cb8f570ef8308403502760a27ee23a4b675d92b93d

3.6. Creating pods

Containers are the smallest unit that you can manage with Podman, Skopeo and Buildah container tools. A Podman pod is a group of one or more containers. The Pod concept was introduced by Kubernetes. Podman pods are similar to the Kubernetes definition. Pods are the smallest compute units that you can create, deploy, and manage in OpenShift or Kubernetes environments. Every Podman pod includes an infra container. This container holds the namespaces associated with the pod and allows Podman to connect other containers to the pod. It allows you to start and stop containers within the pod and the pod will stay running. The default infra container is based on the Kubernetes k8s.gcr.io/pause image.

This procedure shows how to create a pod with one container.

Procedure

  1. Create an empty pod:

    $ podman pod create --name mypod
    223df6b390b4ea87a090a4b5207f7b9b003187a6960bd37631ae9bc12c433aff
    The pod is in the initial state Created.

    The pod is in the initial state Created.

  2. List all pods:

    $ podman pod ps
    POD ID         NAME    STATUS    CREATED                  # OF CONTAINERS   INFRA ID
    223df6b390b4   mypod   Created   Less than a second ago   1                 3afdcd93de3e

    Notice that the pod has one container in it.

  3. List all pods and containers associated with them:

    $ podman ps -a --pod
    CONTAINER ID  IMAGE                 COMMAND  CREATED                 STATUS   PORTS  NAMES               POD
    3afdcd93de3e  k8s.gcr.io/pause:3.1           Less than a second ago  Created         223df6b390b4-infra  223df6b390b4

    You can see that the pod ID from podman ps command matches the pod ID in the podman pod ps command. The default infra container is based on the k8s.gcr.io/pause image.

  4. To run a container named myubi in the existing pod named mypod, type:

    $ podman run -dt --name myubi --pod mypod registry.access.redhat.com/ubi8/ubi  /bin/bash
    5df5c48fea87860cf75822ceab8370548b04c78be9fc156570949013863ccf71
  5. List all pods:

    $ podman pod ps
    POD ID         NAME    STATUS    CREATED                  # OF CONTAINERS   INFRA ID
    223df6b390b4   mypod   Running   Less than a second ago   2                 3afdcd93de3e

    You can see that the pod has two containers in it.

  6. List all pods and containers associated with them:

    $ podman ps -a --pod
    CONTAINER ID  IMAGE                                       COMMAND    CREATED                 STATUS                     PORTS  NAMES               POD
    5df5c48fea87  registry.access.redhat.com/ubi8/ubi:latest  /bin/bash  Less than a second ago  Up Less than a second ago         myubi               223df6b390b4
    3afdcd93de3e  k8s.gcr.io/pause:3.1                                   Less than a second ago  Up Less than a second ago         223df6b390b4-infra  223df6b390b4

Additional resources

3.7. Displaying pod information

This section provides information on how to display pod information.

Prerequisites

  • The pod has been created. For details, see section Creating pods.

Procedure

  • Display active processes running in a pod:

    • To display the running processes of containers in a pod, enter:

      $ podman pod top mypod
      USER   PID   PPID   %CPU    ELAPSED         TTY     TIME   COMMAND
      0      1     0      0.000   24.077433518s   ?       0s     /pause
      root   1     0      0.000   24.078146025s   pts/0   0s     /bin/bash
    • To display a live stream of resource usage stats for containers in one or more pods, enter:

      $ podman pod stats -a --no-stream
      ID             NAME              CPU %   MEM USAGE / LIMIT   MEM %   NET IO    BLOCK IO   PIDS
      a9f807ffaacd   frosty_hodgkin    --      3.092MB / 16.7GB    0.02%   -- / --   -- / --    2
      3b33001239ee   sleepy_stallman   --      -- / --             --      -- / --   -- / --    --
    • To display information describing the pod, enter:

      $ podman pod inspect mypod
      {
         "Id": "db99446fa9c6d10b973d1ce55a42a6850357e0cd447d9bac5627bb2516b5b19a",
         "Name": "mypod",
         "Created": "2020-09-08T10:35:07.536541534+02:00",
         "CreateCommand": [
             "podman",
             "pod",
             "create",
             "--name",
             "mypod"
         ],
         "State": "Running",
         "Hostname": "mypod",
         "CreateCgroup": false,
         "CgroupParent": "/libpod_parent",
         "CgroupPath": "/libpod_parent/db99446fa9c6d10b973d1ce55a42a6850357e0cd447d9bac5627bb2516b5b19a",
         "CreateInfra": false,
         "InfraContainerID": "891c54f70783dcad596d888040700d93f3ead01921894bc19c10b0a03c738ff7",
         "SharedNamespaces": [
             "uts",
             "ipc",
             "net"
         ],
         "NumContainers": 2,
         "Containers": [
             {
                 "Id": "891c54f70783dcad596d888040700d93f3ead01921894bc19c10b0a03c738ff7",
                 "Name": "db99446fa9c6-infra",
                 "State": "running"
             },
             {
                 "Id": "effc5bbcfe505b522e3bf8fbb5705a39f94a455a66fd81e542bcc27d39727d2d",
                 "Name": "myubi",
                 "State": "running"
             }
         ]
      }

      You can see information about containers in the pod.

Additional resources

  • For more information on the podman pod top command, type man podman-pod-top.
  • For more information on the podman pod stats command, type man podman-pod-stats.
  • For more information on the podman pod inspect command, type man podman-pod-inspect.

3.8. Stopping pods

You can stop one or more pods using the podman pod stop command.

Prerequisites

  • The pod has been created. For details, see section Creating pods.

Procedure

  1. To stop the pod mypod, type:

    $ podman pod stop mypod
  2. List all pods and containers associated with them:

    $ podman ps -a --pod
    CONTAINER ID  IMAGE                               COMMAND    CREATED             STATUS                    PORTS   NAMES               POD ID        PODNAME
    5df5c48fea87  registry.redhat.io/ubi8/ubi:latest  /bin/bash  About a minute ago  Exited (0) 7 seconds ago          myubi               223df6b390b4  mypod
    
    3afdcd93de3e  k8s.gcr.io/pause:3.2                           About a minute ago  Exited (0) 7 seconds ago          8a4e6527ac9d-infra  223df6b390b4  mypod

    You can see that the pod mypod and container myubi are in "Exited" status.

Additional resources

  • For more information on the podman pod stop command, type man podman-pod-stop.

3.9. Removing pods

You can remove one or more stopped pods and containers using the podman pod rm command.

Prerequisites

  • The pod has been created. For details, see section Creating pods.
  • The pod has been stopped. For details, see section Stopping pods.

Procedure

  1. To remove the pod mypod, type:

    $ podman pod rm mypod
    223df6b390b4ea87a090a4b5207f7b9b003187a6960bd37631ae9bc12c433aff

    Note that removing the pod automatically removes all containers inside it.

  2. To check that all containers and pods were removed, type:

    $ podman ps
    $ podman pod ps

Additional resources

  • For more information on the podman pod rm command, type man podman-pod-rm.