RHCSA Rapid Track
Podman provides a set of subcommands to create and manage containers. You can use those subcommands to manage the container and container image lifecycle.
The following figure shows the most commonly used Podman subcommands that change the container and image state:
Podman also provides a set of subcommands to obtain information about running and stopped containers.
You can use these subcommands to extract information from containers and images for debugging, updating, or reporting purposes. The following figure shows the most commonly used subcommands that query information from containers and images:
This lecture covers the basic operations that you can use to manage containers. Commands that are explained in this lecture accept either a container ID or the container name.
You can list running containers with the podman ps command.
[user@host ~]$ podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
0ae7be593698 ...server /bin/sh -c python... ...ago Up... ...8000/tcp httpd
c42e7dca12d9 ...helloworld /bin/sh -c nginx... ...ago Up... ...8080/tcp nginxEach row describes information about the container, such as the image that is used to start the container, the command executed when the container started, and the container uptime.
You can include stopped containers in the output by adding the --all or -a flag to the podman ps command.
[user@host ~]$ podman ps --all
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
0ae7be593698 ...server /bin/sh -c python... ...ago Up... ...8000/tcp httpd
bd5ada1b6321 ...httpd-24 /usr/bin/run-http... ...ago Exited... ...8080/tcp upbeat...
c42e7dca12d9 ...helloworld /bin/sh -c nginx ... ...ago Up... ...8080/tcp nginxIn the context of Podman, inspecting a container means retrieving the full information of the container. The podman inspect command returns a JSON array with information about different aspects of the container, such as networking settings, CPU usage, environment variables, status, port mapping, or volumes. The following snippet is a sample output of the podman inspect command.
[user@host ~]$ podman inspect 7763097d11ab
[
{
"Id": "7763...cbc0",
"Created": "2022-05-04T10:00:32.988377257-03:00",
"Path": "container-entrypoint",
"Args": [
"/usr/bin/run-httpd"
],
"State": {
"OciVersion": "1.0.2-dev",
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 9746,
...output omitted...
"Image": "d2b9...fa0a",
"ImageName": "registry.access.redhat.com/ubi8/httpd-24:latest",
"Rootfs": "",
...output omitted...
"Env": [
"PATH=/opt/app-root/src/bin:/opt/app-root/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"TERM=xterm",
"container=oci",
"HTTPD_VERSION=2.4",
...output omitted...
"CpuCount": 0,
"CpuPercent": 0,
"IOMaximumIOps": 0,
"IOMaximumBandwidth": 0,
"CgroupConf": null
}
}
]The previous JSON output omits most fields.
Because the full JSON output is long, you might find it difficult to find the specific fields that you want to retrieve.
You can pass a --format flag to the podman inspect command to filter the command output. The --format flag expects a Go template expression as a parameter, which you can use to select specific fields in the JSON output.
Go template expressions use annotations, which are delimited by double curly braces ({{ and }}), to refer to elements, such as fields or keys, in a data structure. The data structure elements are separated by a dot (.) and must start in uppercase.
In the following command, the Status field of the State object is retrieved for a container called redhat.
[user@host ~]$ podman inspect \
--format='{{.State.Status}}' redhat
runningIn the preceding example, the podman inspect command uses the supplied Go template to navigate the JSON array of the redhat container.
The template returns the Status field value of the State object from the JSON array.
Refer to the references section for more information about the Go templating language.
You can stop a container gracefully by using the podman stop command.
When you execute the podman stop command, Podman sends a SIGTERM signal to the container.
Processes use the SIGTERM signal to implement clean-up procedures before stopping.
The following command stops a container with a container ID 1b982aeb75dd.
[user@host ~]$ podman stop 1b982aeb75dd
1b982aeb75ddYou can stop all the running containers by using the --all or -a flag. In the following example, the command stops three containers.
[user@host ~]$ podman stop --all
4aea...0c2a
6b18...54ea
7763...cbc0If a container does not respond to the SIGTERM signal, then Podman sends a SIGKILL signal to forcefully stop the container.
Podman waits 10 seconds by default before sending the SIGKILL signal.
You can change the default behavior by using the --time flag.
[user@host ~]$ podman stop --time=100In the previous example, Podman gives the container a grace period of 100 seconds before sending the killing signal.
Stopping a container differs from removing a container.
Stopped containers are present on the host machine and can be listed by using the podman ps --all command.
Additionally, when the containerized process finishes, the container enters the exited state. Such a process might finish for a number of reasons, such as an error, OOM (out-of-memory) state, or successfully finishing. Podman lists exited containers with other stopped containers.
You can send the SIGKILL signal to the container by using the podman kill command.
In the following example, a container called httpd is stopped forcefully.
[user@host ~]$ podman kill httpd
httpdBoth podman stop and podman kill commands eventually send a SIGKILL signal to the container.
The podman pause command suspends all processes in the container by sending the SIGSTOP signal.
[user@host ~]$ podman pause 4f2038c05b8c
4f2038c05b8cThe podman unpause command resumes a paused container.
[user@host ~]$ podman unpause 4f2038c05b8c
4f2038c05b8cExecute the podman restart command to restart a running container.
You can also use the command to start stopped containers.
The following command restarts a container called nginx.
[user@host ~]$ podman restart nginx
1b98...75ddUse the podman rm command to remove a stopped container. The following command removes a stopped container with the container ID c58cfd4b90df.
[user@host ~]$ podman rm c58cfd4b90df
c58c...90dfYou cannot remove running containers by default. You must stop the running container first and then remove it. The following command tries to remove a running container.
[user@host ~]$ podman rm c58cfd4b90df
Error: cannot remove container c58c...90df as it is running - running or paused containers cannot be removed without force: container state improperYou can add the --force (or -f) flag to remove the container forcefully.
[user@host ~]$ podman rm c58cfd4b90df --force
c58c...90dfYou can also add the --all (or -a) flag to remove all stopped containers.
This flag fails to remove running containers.
The following command removes two containers.
[user@host ~]$ podman rm --all
6b18...54ea
6c0d...a6fbYou can combine the --force and --all flags to remove all containers, including running containers.
By default, when you run a container, all of the content uses the container-based image. Given the ephemeral nature of container images, all of the new data that the user or the application writes is lost after removing the container.
To make data persistent, you can use host file-system content in the container with the --volume (-v) option. You must consider file-system level permissions when you use this volume type in a container.
In the MariaDB container image, the mysql user must own the /var/lib/mysql directory, the same as if MariaDB was running on the host machine. The directory to mount into the container must have mysql as the user and group owner (or the UID and GID of the mysql user, if MariaDB is not installed on the host machine). If you run a container as the root user, then the UIDs and GIDs on your host machine match the UIDs and GIDs inside the container.
The UID and GID matching configuration does not occur the same way in a rootless container. In a rootless container, the user has root access from within the container, because Podman launches a container inside the user namespace.
You can use the podman unshare command to run a command inside the user namespace. To obtain the UID mapping for your user namespace, use the podman unshare cat command.
[user@host ~]$podman unshare cat /proc/self/uid_map0 1000 1 1 100000 65536 [user@host ~]$podman unshare cat /proc/self/gid_map0 1000 1 1 100000 65536
The preceding output shows that in the container, the root user (UID and GID of 0) maps to your user (UID and GID of 1000) on the host machine. In the container, the UID and GID of 1 maps to the UID and GID of 100000 on the host machine. Every UID and GID after 1 increments by 1. For example, the UID and GID of 30 inside a container maps to the UID and GID of 100029 on the host machine.
You use the podman exec command to view the mysql user UID and GID inside the container that is running with ephemeral storage.
[user@host ~]$podman exec -it db01 grep mysql /etc/passwdmysql:x:27:27:MySQL Server:/var/lib/mysql:/sbin/nologin
You decide to mount the /home/user/db_data directory into the db01 container to provide persistent storage on the /var/lib/mysql directory of the container. You then create the /home/user/db_data directory, and use the podman unshare command to set the user namespace UID and GID of 27 as the owner of the directory.
[user@host ~]$mkdir /home/user/db_data[user@host ~]$podman unshare chown 27:27 /home/user/db_data
The UID and GID of 27 in the container maps to the UID and GID of 100026 on the host machine. You can verify the mapping by viewing the ownership of the /home/user/db_data directory with the ls command.
[user@host ~]$ ls -l /home/user/
total 0
drwxrwxr-x. 3 100026 100026 18 May 5 14:37 db_data
...output omitted...Now that the correct file-system level permissions are set, you use the podman run command -v option to mount the directory.
[user@host ~]$podman run -d --name db01 \-e MYSQL_USER=student \-e MYSQL_PASSWORD=student \-e MYSQL_DATABASE=dev_data \-e MYSQL_ROOT_PASSWORD=redhat \-v /home/user/db_data:/var/lib/mysql \registry.lab.example.com/rhel8/mariadb-105
You notice that the db01 container is not running.
[user@host ~]$ podman ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
dfdc20cf9a7e registry.lab.example.com/rhel8/mariadb-105:latest run-mysqld 29 seconds ago Exited (1) 29 seconds ago db01The podman container logs command shows a permission error for the /var/lib/mysql/db_data directory.
[user@host ~]$ podman container logs db01
...output omitted...
---> 16:41:25 Initializing database ...
---> 16:41:25 Running mysql_install_db ...
mkdir: cannot create directory '/var/lib/mysql/db_data': Permission denied
Fatal error Can't create database directory '/var/lib/mysql/db_data'This error happens because of the incorrect SELinux context that is set on the /home/user/db_data directory on the host machine.
You must set the container_file_t SELinux context type before you can mount the directory as persistent storage to a container. If the directory does not have the container_file_t SELinux context, then the container cannot access the directory. You can append the Z option to the argument of the podman run command -v option to automatically set the SELinux context on the directory.
So you use the podman run -v /home/user/db_data:/var/lib/mysql:Z command to set the SELinux context for the /home/user/db_data directory when you mount it as persistent storage for the /var/lib/mysql directory.
[user@host ~]$podman run -d --name db01 \-e MYSQL_USER=student \-e MYSQL_PASSWORD=student \-e MYSQL_DATABASE=dev_data \-e MYSQL_ROOT_PASSWORD=redhat \-v /home/user/db_data:/var/lib/mysql:Z \registry.lab.example.com/rhel8/mariadb-105
You then verify that the correct SELinux context is set on the /home/user/db_data directory with the ls command -Z option.
[user@host ~]$ ls -Z /home/user/
system_u:object_r:container_file_t:s0:c81,c1009 db_data
...output omitted...In a traditional environment, administrators configure applications such as web servers or databases to start at boot time, and run indefinitely as a systemd service.
Systemd is a system and service management tool for Linux operating systems.
Systemd uses service unit files to start and stop applications, or to enable them to start at boot time.
Typically, an administrator manages these applications with the systemctl command.
As a regular user, you can create systemd unit files to manage your rootless containers.
You can use this configuration to manage your container as a regular systemd service with the systemctl command.
To create a systemd unit file for a specified service container, use the podman generate systemd command.
Use the --name option to specify the container's name.
The --files option generates files instead of printing to standard output (STDOUT).
[user@host ~]$ podman generate systemd --name web --files
/home/user/container-web.serviceThe preceding command creates the container-web.service unit file for a container called web.
After reviewing and adapting the generated service configuration to your requirements, store the unit file in the user's systemd configuration directory (~/.config/systemd/user/).
After adding or modifying unit files, you must use the systemctl command to reload the systemd configuration.
[user@host ~]$ systemctl --user daemon-reloadTo manage a containerized service, use the systemctl command.
[user@host ~]$ systemctl --user [start, stop, status, enable, disable] container-web.serviceWhen you use the --user option, by default, systemd starts the service when you log in, and stops it when you log out.
You can start your enabled services at the operating system boot, and stop them on shutdown, by running the loginctl enable-linger command.
[user@host ~]$ loginctl enable-lingerTo revert the operation, use the loginctl disable-linger command.
References
podman-inspect(1), podman-stop(1), podman-restart(1), podman-rm(1),podman-run(1), and podman-unshare(1) man pages
For more information, refer to the Porting Containers to systemd Using Podman chapter in the Red Hat Enterprise Linux 9 Building, Running, and Managing Containers guide at https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/9/html-single/building_running_and_managing_containers/index#assembly_porting-containers-to-systemd-using-podman_building-running-and-managing-containers