Managing Containers with Podman

Containers, images, and image registries need to be able to interact with each other. For example, you need to be able to build images and put them into image registries. You also need to be able to retrieve an image from the image registry and build a container from that image. Podman is an open source tool for managing containers and container images and interacting with
image registries.

It offers the following key features:

  •  It uses image format specified by the Open Container Initiative [https://
    www.opencontainers.org] (OCI). Those specifications define an standard, community-driven, non-proprietary image format.
  • Podman stores local images in local file-system. Doing so avoids unnecessary client/server architecture or having daemons running on local machine.
  • Podman follows the same command patterns as the Docker CLI, so there is no need to learn a new toolset.
  • Podman is compatible with Kubernetes. Kubernetes can use Podman to manage its containers.

Currently, Podman is only available on Linux systems. To install Podman in Red Hat Enterprise Linux, CentOS, Fedora or similar RPM-based systems:

or

To get some help and find out how Podman is working, you can use the help:

For more details, you can review the manpages:

 

If you have prior experience with docker you won’t have any problem to work with podman. Podman use the same commands as docker so you can define an alias in your bash shell if you wan’t:

 

Fetching Container Images with Podman
Applications can run inside containers as a way to provide them with an isolated and controlled execution environment. Running a containerized application, that is, running an application inside a container, requires a container image, a file system bundle providing all application files, libraries, and dependencies the application needs to run. Container images can be found in image registries: services that allow users to search and retrieve container images. Podman users can use the search subcommand to find available images from remote or local registries:

After you have found an image, you can use Podman to download it. When using the pull subcommand, Podman fetches the image and saves it locally for future use:

Container images are named based on the following syntax:
registry_name/user_name/image_name:tag

  • registry_name, the name of the registry storing the image. It is usually the FQDN of the registry.
  • user_name stands for the user or organization the image belongs to.
  • The image_name should be unique in user namespace.
  • The tag identifies the image version. If the image name includes no image tag, latest is assumed.

After retrieval, Podman stores images locally and you can list them with the images subcommand:

Let’s pull the hello-world app:

Now we can run our test app:

If the images require interacting with the user with console input, Podman can redirect container input and output streams to the console. The run  subcommand requires the -t and -i flags (or, in short, -it flag) to enable interactivity.

To start a container image as a background process, pass the -d option to the podman run command:

Many Podman flags also have an alternative long form; some of these are explained below.
-t is equivalent to --tty, meaning a pseudo-tty (pseudo-terminal) is to be
allocated for the container.
-i is the same as --interactive. When used, standard input is kept open into the container.
-d, or its long form --detach, means the container runs in the background
(detached). Podman then prints the container id.

Now let’s map containers port (option -p):

podman inspect: This command lists metadata about a running or stopped container. The command produces JSON output:

This command allows formatting of the output string using the given Go template with the -f option. For example, to retrieve only the IP address, use the following command:

The previous example ran a containerized Apache HTTP server in the background. Then, the example uses the podman inspect command to retrieve the container’s internal IP address from container metadata. Finally, it uses the IP address to fetch the root page from Apache HTTP server. This response proves the container is still up and running after the podman run command.

If the image to be executed is not available locally when using the podman run
command, Podman automatically uses pull to download the image.
When referencing the container, Podman recognizes a container either with the container name or the generated container id. Use the --name option to set the container name when running the container with Podman. Container names must be unique. If the podman run command includes no container name, Podman generates a unique random name. If the images require interacting with the user with console input, Podman can redirect container input and output streams to the console. The run subcommand requires the -t and -i flags (or, in short, -it flag) to enable interactivity.

The following figure shows a summary of the most commonly used
subcommands that change container and image state.

Podman also provides a set of useful subcommands to obtain information about running and stopped containers.

The podman run command creates a new container from an image and starts a process inside the new container. If the container image is not available locally, this command attempts to download the image using the configured image repository:

  •  podman exec command starts an additional process inside an already running container:

Podman remembers the last container used in any command. Developers can skip writing this container’s ID or name in later Podman commands by replacing the container id by the -l option:

Let’s start a Bash session inside the container.

Change the index.html file to contain the text Hello World, replacing all of the
existing content.

Podman identifies containers by a unique container ID or container name. The podman ps command displays the container ID and names for all actively running containers:

The container ID is unique and generated automatically. The container name can be manually specified, otherwise it is generated automatically. This name must be unique or the run command fails.

Podman does not discard stopped containers immediately. Podman preserves their local file systems and other states for facilitating postmortem analysis. Option -a lists all containers, including stopped ones:

 

  •  podman stop: This command stops a running container gracefully:

  •  podman kill: This command sends Unix signals to the main process in the container. If no signal is specified, it sends the SIGKILL signal, terminating the main process and the container.

You can specify the signal with the -s option:

Any Unix signal can be sent to the main process. Podman accepts either the signal name and number. The following table shows several useful signals:

Signal Value Default Action Comment
SIGHUP 1 Term Hangup detected on controlling terminal or death of controlling process
SIGINT 2 Term Interrupt from keyboard
SIGQUIT 3 Core Quit from keyboard
SIGILL 4 Core Illegal Instruction
SIGABRT 6 Core Abort signal from abort(3)
SIGFPE 8 Core Floating point exception
SIGKILL 9 Term Kill signal
SIGSEGV 11 Core Invalid memory reference
SIGPIPE 13 Term Broken pipe: write to pipe with no readers
SIGALRM 14 Term Timer signal from alarm(2)
SIGTERM 15 Term Termination signal
SIGUSR1 30,10,16 Term User-defined signal 1
SIGUSR2 31,12,17 Term User-defined signal 2
SIGCHLD 20,17,18 Ign Child stopped or terminated
SIGCONT 19,18,25 Cont Continue if stopped
SIGSTOP 17,19,23 Stop Stop process
SIGTSTP 18,20,24 Stop Stop typed at tty
SIGTTIN 21,21,26 Stop tty input for background process
SIGTTOU 22,22,27 Stop tty output for background process

 

  • podman restart: This command restarts a stopped container:

The podman restart command creates a new container with the same container ID, reusing the stopped container state and file system.

  • podman rm: This command deletes a container and discards its state and file system:

The -f option of the rm subcommand instructs Podman to remove the container even if not stopped. This option terminates the container forcefully and then removes it. Using -f option is equivalent to podman kill and podman rm commands together. You can delete all containers at the same time. Many podman subcommands accept the -a option. This option indicates using the subcommand on all available containers or images. The following example removes all containers:

Before deleting all containers, all running containers must be in a “stopped” status. You can use the following command to stop all containers:

The inspect, stop, kill, restart, and rm subcommands can use the container ID instead of the container name.

External parameters

Some containers need or can use external parameters provided at startup. The most common approach for providing and consuming those parameters is through environment variables. Podman can inject environment variables into containers at startup by adding the -e flag to the run subcommand:

 

Attaching Persistent Storage to Containers

Create a directory with owner and group root:

The user running processes in the container must be capable of writing files to the directory. If the host machine does not have exactly the same user defined, the permission should be defined with the numeric user ID (UID) from the container. In the case of the Red Hatprovided MySQL service, the UID is 27:

If you use SELinux you should apply the container_file_t context to the directory (and all subdirectories) to allow containers access to all of its contents.

Apply the SELinux container policy that you set up in the first step to the newly created directory:

Verify that the SELinux context type for the /var/local/mysql directory is container_file_t.

After creating and configuring the host directory, the next step is to mount this directory to a container. To bind mount a host directory to a container, add the -v option to the podman run command, specifying the host directory path and the container storage path, separated by a colon (:).

Let’s see the logs:

Connect to the database:

Loading the database:

 

Open a Bash shell inside the container.

Verify that the mysql command is installed in the container:

Verify that the database contains data:

Exit from the Bash shell inside the container:

Inject the mysql query inside the container.

The mysql command is not in the PATH variable and, for this reason, you must use an absolute path.