Chapter 8. Container command-line reference

8.1. podman

The podman command (which stands for Pod Manager) lets you run containers as standalone entities, without requiring that Kubernetes, the Docker runtime, or any other container runtime be involved. It is a tool that can act as a replacement for the docker command, implementing the same command-line syntax, while it adds even more container management features. The podman features include:

  • Based on docker interface: Because podman syntax mirrors the docker command, transitioning to podman should be easy for those familiar with docker.
  • Managing containers and images: Both Docker- and OCI-compatible container images can be used with podman to:

    • Run, stop and restart containers
    • Create and manage container images (push, commit, configure, build, and so on)
  • Managing pods: Besides running individual containers, podman can run a set of containers grouped in a pod. A pod is the smallest container unit that Kubernetes manages.
  • Working with no runtime: No runtime environment is used by podman to work with containers.

Here are a few implementation features of podman you should know about:

  • Podman, Buildah, and the CRI-O container engine all use the same back-end store directory, /var/lib/containers, instead of using the Docker storage location (/var/lib/docker), by default.
  • Although Podman, Buildah, and CRI-O share the same storage directory, they cannot interact with each other’s containers. Those tools can share images, however. Eventually those features will be able to share containers.
  • The podman command, like the docker command, can build container images from a Dockerfile.
  • The podman command can be a useful troubleshooting tool when the CRI-O service is unavailable.
  • Options to the docker command that are not supported by podman include network, node, plugin (podman does not support plugins), rename (use rm and create to rename containers with podman), secret, service, stack, and swarm (podman does not support Docker Swarm). The container and image options are used to run subcommands that are used directly in podman.
  • To interact programmatically with podman, a remote API for Podman is available using a technology called varlink. This will let podman listen for API requests from remote tools (such as the RHEL 8 web console or the atomic command) and respond to them.

8.1.1. Using podman commands

If you are used to using the docker command to work with containers, you will find most of the features and options match those of podman. Table 1 shows a list of commands you can use with podman (type podman -h to see this list):

Table 8.1. Commands supported by podman

podman command

Description

podman command

Description

attach

Attach to a running container

commit

Create new image from changed container

build

Build an image using Dockerfile instructions

create

Create, but do not start, a container

diff

Inspect changes on container’s filesystems

exec

Run a process in a running container

export

Export container’s filesystem contents as a tar archive

help, h

Shows a list of commands or help for one command

history

Show history of a specified image

images

List images in local storage

import

Import a tarball to create a filesystem image

info

Display system information

inspect

Display the configuration of a container or image

kill

Send a specific signal to one or more running containers

load

Load an image from an archive

login

Login to a container registry

logout

Logout of a container registry

logs

Fetch the logs of a container

mount

Mount a working container’s root filesystem

pause

Pauses all the processes in one or more containers

ps

List containers

port

List port mappings or a specific mapping for the container

pull

Pull an image from a registry

push

Push an image to a specified destination

restart

Restart one or more containers

rm

Remove one or more containers from host. Add -f if running.

rmi

removes one or more images from local storage

run

run a command in a new container

save

Save image to an archive

search

search registry for image

start

Start one or more containers

stats

Display percentage of CPU, memory, network I/O, block I/O and PIDs for one or more containers

stop

Stop one or more containers

tag

Add an additional name to a local image

top

Display the running processes of a container

umount, unmount

Unmount a working container’s root filesystem

unpause

Unpause the processes in one or more containers

version

Display podman version information

wait

Block on one or more containers

  

8.1.2. Trying basic podman commands

Because the use of podman mirrors the features and syntax of the docker command, you can refer to Working with Docker Formatted Container Images for examples of how to use those options to work with containers. Simply replace docker with podman in most cases. Here are some examples of using podman.

8.1.3. Pull a container image to the local system

# podman pull registry.redhat.io/ubi8/ubi
Trying to pull registry.redhat...Getting image source signatures
Copying blob sha256:d1fe25896eb5cbcee...
Writing manifest to image destination
Storing signatures
fd1ba0b398a82d56900bb798c...

8.1.4. List local container images

# podman images
REPOSITORY                    TAG      IMAGE ID       CREATED       SIZE
registry.redhat.io/ubi8/ubi   latest   de9c26f23799   5 weeks ago   80.1MB
registry.redhat.io/ubi8/ubi   latest   fd1ba0b398a8   5 weeks ago   211MB

8.1.5. Inspect a container image

# podman inspect registry.redhat.io/ubi8/ubi | less
[
    {
        "Id": "4bbd153adf8487a8a5114af0d6...",
        "Digest": "sha256:9999e735605c73f...",
        "RepoTags": [
            "registry.access.redhat.com/ubi8/ubi:latest"
        ],
        "RepoDigests": [
            "registry.access.redhat.com/ubi8/ubi/rhel@sha256:9999e7356...

8.1.6. Run a container image

Run a container that opens a shell inside the container:

# podman run -it registry.redhat.io/ubi8/ubi /bin/bash
[root@8414218c04f9 /]# ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 13:48 pts/0    00:00:00 /bin/bash
root        21     1  0 13:49 pts/0    00:00:00 ps -ef
[root@8414218c04f9 /]# exit
#

8.1.7. List containers that are running or have exited

# podman ps -a
CONTAINER ID   IMAGE                                             COMMAND
   CREATED AT                      STATUS                  PORTS NAMES
440becd26893   registry.redhat.io/ubi8/ubi-minimal:latest  /bin/bash
   2018-05-10 09:02:52 -0400 EDT   Exited (0) About an hour ago  happy_hodgkin
8414218c04f9   registry.redhat.io/ubi8/ubi:latest          /bin/bash
   2018-05-10 09:48:07 -0400 EDT   Exited (0) 14 minutes ago     nostalgic_boyd

8.1.8. Remove a container or image

Remove a container by its container ID:

# podman rm 440becd26893

Remove a container image by its image ID or name (use -f to force):

# podman rmi registry.redhat.io/ubi8/ubi
# podman rmi de9c26f23799
# podman rmi -f registry.redhat.io/ubi8/ubi:latest

8.1.9. Generate a Kube pod yaml or systemd unit file

Using the podman generate command you can create a systemd unit file or a Kubernetes pod yaml file from a container or a pod. Here’s an example of generating a Kubernetes yaml file:

  1. Start a containerized service that runs as a daemon process (mariadb, in this example):

    # podman run -d -e MYSQL_USER=user -e MYSQL_PASSWORD=pass \
         -e MYSQL_DATABASE=db -p 3306:3306 --name mymariadb rhscl/mariadb-102-rhel7
  2. Get the container name or ID:

    # podman ps
    CONTAINER ID  IMAGE
        COMMAND               CREATED         STATUS
             PORTS                   NAMES
    e421a3424ab0  registry.access.redhat.com/rhscl/mariadb-102-rhel7:latest
        container-entrypo...  19 seconds ago  Up 16 seconds ago
             0.0.0.0:3306->3306/tcp  mymariadb
  3. Use the container name or ID to generate the Kubernetes yaml and direct it into a file:

    # podman generate kube mymariadb > mymariadbkube.yaml
    # less mymariadbkube.yaml
    apiVersion: v1
    kind: Pod
    metadata:
      creationTimestamp: "2019-10-31T13:19:41Z"
      labels:
        app: mymariadb
      name: mymariadb
    spec:
      containers:
      - command:
    ...
     - name: MYSQL_VERSION
          value: "10.2"
        - name: CONTAINER_SCRIPTS_PATH
          value: /usr/share/container-scripts/mysql
        - name: MYSQL_PREFIX
          value: /opt/rh/rh-mariadb102/root/usr
        - name: ENABLED_COLLECTIONS
          value: rh-mariadb102
        - name: DESCRIPTION
          value: MariaDB is a multi-user, multi-threaded SQL database server. The container
            image provides a containerized packaging of the MariaDB mysqld daemon and
            client application. The mysqld server daemon accepts connections from clients
            and provides access to content from MariaDB databases on behalf of the clients.
     - name: STI_SCRIPTS_PATH
          value: /usr/libexec/s2i
        - name: PROMPT_COMMAND
          value: . /usr/share/container-scripts/mysql/scl_enable
        - name: MYSQL_USER
          value: user
        - name: MYSQL_PASSWORD
          value: pass
    ...

    Note that this tool does not handle volumes and PVs.

  4. You can now use the yaml file to create a pod in your Kubernetes or OpenShift environment:

    # kubectl create -f mymariadbkube.yaml

8.1.10. Build a container

# cat Dockerfile
FROM registry.redhat.io/ubi8/ubi
ENTRYPOINT "echo 'Podman built this container.'"

# podman build -t podbuilt .
STEP 1: FROM registry.access...
...
Writing manifest to image destination
Storing signatures
91e043c11617c08d4f8...

# podman run podbuilt
Podman build this container.

8.2. runc

"runC" is a lightweight, portable implementation of the Open Container Initiative (OCI) container runtime specification. 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.

runc 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 OCI-compatible images with runc.

8.2.1. Running containers with 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 filesystem. The root filesystem contains the contents of the container.

To create a bundle, run:

$ 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 Red Hat Enterprise Linux base image (ubi8/ubi) using podman 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:

# podman pull registry.redhat.io/ubi8/ubi
# podman export $(podman create registry.redhat.io/ubi8/ubi) > 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 any setting you like
# runc create -b rhel-runc/ rhel-container
# 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".

8.3. skopeo

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, Red Hat Quay or OpenShift 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 (such as Red Hat Quay. Container registry software available in the docker-distribution package for RHEL 7, is not available for RHEL 8.
  • Pull the latest RHEL image to your local system (podman pull ubi8/ubi).
  • Retag the RHEL image and push it to your local registry as follows:

    # podman tag ubi8/ubi localhost/myubi8
    # podman push localhost/myubi8

The rest of this section describes how to inspect, copy and get layers from the RHEL 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.

8.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), and the repository/image (such as ubi8/ubi).

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

# 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": "2018-06-10T01:53:48.812217692Z",
    "DockerVersion": "1.10.3",
    "Labels": {},
    "Architecture": "amd64",
    "Os": "linux",
    "Layers": [
...

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

# skopeo inspect docker://localhost/myubi8
{
    "Name": "localhost/myubi8",
    "Tag": "latest",
    "Digest": "sha256:4e09c308a9ddf56c0ff6e321d135136eb04152456f73786a16166ce7cba7c904",
    "RepoTags": [
        "latest"
    ],
    "Created": "2018-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": "myubi8",
        "Release": "75",
        "Vendor": "Red Hat, Inc.",
        "Version": "8.0"
    },
    "Architecture": "amd64",
    "Os": "linux",
    "Layers": [
        "sha256:16dc1f96e3a1bb628be2e00518fec2bb97bd5933859de592a00e2eb7774b6ecf"
    ]
}

8.3.2. Copying container images with skopeo

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

# skopeo copy docker://localhost/myubi8 dir:/root/test/
INFO[0000] Downloading myubi8/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.json file representing the image being 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.

8.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/myubi8
INFO[0000] Downloading myubi8/blobs/sha256:16dc1f96e3a1bb628be2e00518fec2bb97bd5933859de592a00e2eb7774b6ecf
# find .
./layers-myubi8-latest-698503105
./layers-myubi-latest-698503105/manifest.json
./layers-myubi8-latest-698503105/16dc1f96e3a1bb628be2e00518fec2bb97bd5933859de592a00e2eb7774b6ecf.tar

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