Chapter 14. Porting containers to systemd using Podman
Podman (Pod Manager) is a fully featured container engine that is a simple daemonless tool. Podman provides a Docker-CLI comparable command line that makes the transition from other container engines easier and allows the management of pods, containers and images.
Podman was not originally designed to bring up an entire Linux system or manage services for such things as start-up order, dependency checking, and failed service recovery. That is the job of a full-blown initialization system like systemd
. Red Hat has become a leader in integrating containers with systemd
, so that OCI and Docker-formatted containers built by Podman can be managed in the same way that other services and features are managed in a Linux system. You can use the systemd
initialization service to work with pods and containers. You can use the podman generate systemd
command to generate a systemd
unit file for containers and pods.
With systemd
unit files, you can:
-
Set up a container or pod to start as a
systemd
service. - Define the order in which the containerized service runs and check for dependencies (for example making sure another service is running, a file is available or a resource is mounted).
-
Control the state of the
systemd
system using thesystemctl
command.
You can generate portable descriptions of containers and pods by using systemd
unit files.
14.1. Enabling systemd services
When enabling the service, you have different options.
Procedure
Enable the service:
To enable a service at system start, no matter if user is logged in or not, enter:
# systemctl enable <service>
You have to copy the
systemd
unit files to the/etc/systemd/system
directory.To start a service at user login and stop it at user logout, enter:
$ systemctl --user enable <service>
You have to copy the
systemd
unit files to the$HOME/.config/systemd/user
directory.To enable users to start a service at system start and persist over logouts, enter:
In root mode:
# loginctl enable-linger <username>
In rootless mode:
$ loginctl enable-linger
Additional resources
-
systemctl
man page -
loginctl
man page - Making systemd services start at boot time
14.2. Generating a systemd unit file using Podman
Podman allows systemd
to control and manage container processes. You can generate a systemd
unit file for the existing containers and pods using podman generate systemd
command. It is recommended to use podman generate systemd
because the generated units files change frequently (via updates to Podman) and the podman generate systemd
ensures that you get the latest version of unit files.
Prerequisites
-
The
containers-tool
meta-package is installed.
Procedure
Create a container (for example
myubi
):$ podman create --name myubi registry.access.redhat.com/ubi9:latest sleep infinity 0280afe98bb75a5c5e713b28de4b7c5cb49f156f1cce4a208f13fee2f75cb453
Use the container name or ID to generate the
systemd
unit file and direct it into the~/.config/systemd/user/container-myubi.service
file:$ podman generate systemd --name myubi > ~/.config/systemd/user/container-myubi.service
Verification steps
Display the content of generated
systemd
unit file:$ cat ~/.config/systemd/user/container-myubi.service # container-myubi.service # autogenerated by Podman 3.3.1 # Wed Sep 8 20:34:46 CEST 2021 [Unit] Description=Podman container-myubi.service Documentation=man:podman-generate-systemd(1) Wants=network-online.target After=network-online.target RequiresMountsFor=/run/user/1000/containers [Service] Environment=PODMAN_SYSTEMD_UNIT=%n Restart=on-failure TimeoutStopSec=70 ExecStart=/usr/bin/podman start myubi ExecStop=/usr/bin/podman stop -t 10 myubi ExecStopPost=/usr/bin/podman stop -t 10 myubi PIDFile=/run/user/1000/containers/overlay-containers/9683103f58a32192c84801f0be93446cb33c1ee7d9cdda225b78049d7c5deea4/userdata/conmon.pid Type=forking [Install] WantedBy=multi-user.target default.target
-
The
Restart=on-failure
line sets the restart policy and instructssystemd
to restart when the service cannot be started or stopped cleanly, or when the process exits non-zero. -
The
ExecStart
line describes how we start the container. -
The
ExecStop
line describes how we stop and remove the container.
-
The
Additional resources
14.3. Auto-generating a systemd unit file using Podman
By default, Podman generates a unit file for existing containers or pods. You can generate more portable systemd
unit files using the podman generate systemd --new
. The --new
flag instructs Podman to generate unit files that create, start and remove containers.
Prerequisites
-
The
containers-tool
meta-package is installed.
Procedure
Pull the image you want to use on your system. For example, to pull the
httpd-24
image:# podman pull registry.access.redhat.com/ubi9/httpd-24
Optional. List all images available on your system:
# podman images REPOSITORY TAG IMAGE ID CREATED SIZE registry.access.redhat.com/ubi9/httpd-24 latest 8594be0a0b57 2 weeks ago 462 MB
Create the
httpd
container:# podman create --name httpd -p 8080:8080 registry.access.redhat.com/ubi9/httpd-24 cdb9f981cf143021b1679599d860026b13a77187f75e46cc0eac85293710a4b1
Optional. Verify the container has been created:
# podman ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES cdb9f981cf14 registry.access.redhat.com/ubi9/httpd-24:latest /usr/bin/run-http... 5 minutes ago Created 0.0.0.0:8080->8080/tcp httpd
Generate a
systemd
unit file for thehttpd
container:# podman generate systemd --new --files --name httpd /root/container-httpd.service
Display the content of the generated
container-httpd.service
systemd
unit file:# cat /root/container-httpd.service # container-httpd.service # autogenerated by Podman 3.3.1 # Wed Sep 8 20:41:44 CEST 2021 [Unit] Description=Podman container-httpd.service Documentation=man:podman-generate-systemd(1) Wants=network-online.target After=network-online.target RequiresMountsFor=%t/containers [Service] Environment=PODMAN_SYSTEMD_UNIT=%n Restart=on-failure TimeoutStopSec=70 ExecStartPre=/bin/rm -f %t/%n.ctr-id ExecStart=/usr/bin/podman run --cidfile=%t/%n.ctr-id --sdnotify=conmon --cgroups=no-conmon --rm -d --replace --name httpd -p 8080:8080 registry.access.redhat.com/ubi9/httpd-24 ExecStop=/usr/bin/podman stop --ignore --cidfile=%t/%n.ctr-id ExecStopPost=/usr/bin/podman rm -f --ignore --cidfile=%t/%n.ctr-id Type=notify NotifyAccess=all [Install] WantedBy=multi-user.target default.target
Unit files generated using the --new
option do not expect containers and pods to exist. Therefore, they perform the podman run
command when starting the service (see the ExecStart
line) instead of the podman start
command. For example, see section Generating a systemd unit file using Podman.
The
podman run
command uses the following command-line options:-
The
--conmon-pidfile
option points to a path to store the process ID for theconmon
process running on the host. Theconmon
process terminates with the same exit status as the container, which allowssystemd
to report the correct service status and restart the container if needed. -
The
--cidfile
option points to the path that stores the container ID. -
The
%t
is the path to the run time directory root, for example/run/user/$UserID
. The
%n
is the full name of the service.Copy unit files to
/etc/systemd/system
for installing them as a root user:# cp -Z container-httpd.service /etc/systemd/system
Enable and start the
container-httpd.service
:# systemctl daemon-reload # systemctl enable --now container-httpd.service Created symlink /etc/systemd/system/multi-user.target.wants/container-httpd.service → /etc/systemd/system/container-httpd.service. Created symlink /etc/systemd/system/default.target.wants/container-httpd.service → /etc/systemd/system/container-httpd.service.
-
The
Verification steps
Check the status of the
container-httpd.service
:# systemctl status container-httpd.service ● container-httpd.service - Podman container-httpd.service Loaded: loaded (/etc/systemd/system/container-httpd.service; enabled; vendor preset: disabled) Active: active (running) since Tue 2021-08-24 09:53:40 EDT; 1min 5s ago Docs: man:podman-generate-systemd(1) Process: 493317 ExecStart=/usr/bin/podman run --conmon-pidfile /run/container-httpd.pid --cidfile /run/container-httpd.ctr-id --cgroups=no-conmon -d --repla> Process: 493315 ExecStartPre=/bin/rm -f /run/container-httpd.pid /run/container-httpd.ctr-id (code=exited, status=0/SUCCESS) Main PID: 493435 (conmon) ...
Additional resources
14.4. Auto-starting containers using systemd
You can control the state of the systemd
system and service manager using the systemctl
command. You can enable, start, stop the service as a non-root user. To install the service as a root user, omit the --user
option.
Prerequisites
-
The
containers-tool
meta-package is installed.
Procedure
Reload
systemd
manager configuration:# systemctl --user daemon-reload
Enable the service
container.service
and start it at boot time:# systemctl --user enable container.service
Start the service immediately:
# systemctl --user start container.service
Check the status of the service:
$ systemctl --user status container.service ● container.service - Podman container.service Loaded: loaded (/home/user/.config/systemd/user/container.service; enabled; vendor preset: enabled) Active: active (running) since Wed 2020-09-16 11:56:57 CEST; 8s ago Docs: man:podman-generate-systemd(1) Process: 80602 ExecStart=/usr/bin/podman run --conmon-pidfile //run/user/1000/container.service-pid --cidfile //run/user/1000/container.service-cid -d ubi9-minimal:> Process: 80601 ExecStartPre=/usr/bin/rm -f //run/user/1000/container.service-pid //run/user/1000/container.service-cid (code=exited, status=0/SUCCESS) Main PID: 80617 (conmon) CGroup: /user.slice/user-1000.slice/user@1000.service/container.service ├─ 2870 /usr/bin/podman ├─80612 /usr/bin/slirp4netns --disable-host-loopback --mtu 65520 --enable-sandbox --enable-seccomp -c -e 3 -r 4 --netns-type=path /run/user/1000/netns/cni-> ├─80614 /usr/bin/fuse-overlayfs -o lowerdir=/home/user/.local/share/containers/storage/overlay/l/YJSPGXM2OCDZPLMLXJOW3NRF6Q:/home/user/.local/share/contain> ├─80617 /usr/bin/conmon --api-version 1 -c cbc75d6031508dfd3d78a74a03e4ace1732b51223e72a2ce4aa3bfe10a78e4fa -u cbc75d6031508dfd3d78a74a03e4ace1732b51223e72> └─cbc75d6031508dfd3d78a74a03e4ace1732b51223e72a2ce4aa3bfe10a78e4fa └─80626 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 1d
You can check if the service is enabled using the
systemctl is-enabled container.service
command.
Verification steps
List containers that are running or have exited:
# podman ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES f20988d59920 registry.access.redhat.com/ubi9-minimal:latest top 12 seconds ago Up 11 seconds ago funny_zhukovsky
To stop container.service
, enter:
# systemctl --user stop container.service
Additional resources
14.5. Auto-starting pods using systemd
You can start multiple containers as systemd
services. Note that the systemctl
command should only be used on the pod and you should not start or stop containers individually via systemctl
, as they are managed by the pod service along with the internal infra-container.
Prerequisites
-
The
containers-tool
meta-package is installed.
Procedure
Create an empty pod, for example named
systemd-pod
:$ podman pod create --name systemd-pod 11d4646ba41b1fffa51c108cbdf97cfab3213f7bd9b3e1ca52fe81b90fed5577
Optional. List all pods:
$ podman pod ps POD ID NAME STATUS CREATED # OF CONTAINERS INFRA ID 11d4646ba41b systemd-pod Created 40 seconds ago 1 8a428b257111 11d4646ba41b1fffa51c108cbdf97cfab3213f7bd9b3e1ca52fe81b90fed5577
Create two containers in the empty pod. For example, to create
container0
andcontainer1
insystemd-pod
:$ podman create --pod systemd-pod --name container0 registry.access.redhat.com/ubi9 top $ podman create --pod systemd-pod --name container1 registry.access.redhat.com/ubi9 top
Optional. List all pods and containers associated with them:
$ podman ps -a --pod CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES POD ID PODNAME 24666f47d9b2 registry.access.redhat.com/ubi9:latest top 3 minutes ago Created container0 3130f724e229 systemd-pod 56eb1bf0cdfe k8s.gcr.io/pause:3.2 4 minutes ago Created 3130f724e229-infra 3130f724e229 systemd-pod 62118d170e43 registry.access.redhat.com/ubi9:latest top 3 seconds ago Created container1 3130f724e229 systemd-pod
Generate the
systemd
unit file for the new pod:$ podman generate systemd --files --name systemd-pod /home/user1/pod-systemd-pod.service /home/user1/container-container0.service /home/user1/container-container1.service
Note that three
systemd
unit files are generated, one for thesystemd-pod
pod and two for the containerscontainer0
andcontainer1
.Display
pod-systemd-pod.service
unit file:$ cat pod-systemd-pod.service # pod-systemd-pod.service # autogenerated by Podman 3.3.1 # Wed Sep 8 20:49:17 CEST 2021 [Unit] Description=Podman pod-systemd-pod.service Documentation=man:podman-generate-systemd(1) Wants=network-online.target After=network-online.target RequiresMountsFor= Requires=container-container0.service container-container1.service Before=container-container0.service container-container1.service [Service] Environment=PODMAN_SYSTEMD_UNIT=%n Restart=on-failure TimeoutStopSec=70 ExecStart=/usr/bin/podman start bcb128965b8e-infra ExecStop=/usr/bin/podman stop -t 10 bcb128965b8e-infra ExecStopPost=/usr/bin/podman stop -t 10 bcb128965b8e-infra PIDFile=/run/user/1000/containers/overlay-containers/1dfdcf20e35043939ea3f80f002c65c00d560e47223685dbc3230e26fe001b29/userdata/conmon.pid Type=forking [Install] WantedBy=multi-user.target default.target
-
The
Requires
line in the[Unit]
section defines dependencies oncontainer-container0.service
andcontainer-container1.service
unit files. Both unit files will be activated. -
The
ExecStart
andExecStop
lines in the[Service]
section start and stop the infra-container, respectively.
-
The
Display
container-container0.service
unit file:$ cat container-container0.service # container-container0.service # autogenerated by Podman 3.3.1 # Wed Sep 8 20:49:17 CEST 2021 [Unit] Description=Podman container-container0.service Documentation=man:podman-generate-systemd(1) Wants=network-online.target After=network-online.target RequiresMountsFor=/run/user/1000/containers BindsTo=pod-systemd-pod.service After=pod-systemd-pod.service [Service] Environment=PODMAN_SYSTEMD_UNIT=%n Restart=on-failure TimeoutStopSec=70 ExecStart=/usr/bin/podman start container0 ExecStop=/usr/bin/podman stop -t 10 container0 ExecStopPost=/usr/bin/podman stop -t 10 container0 PIDFile=/run/user/1000/containers/overlay-containers/4bccd7c8616ae5909b05317df4066fa90a64a067375af5996fdef9152f6d51f5/userdata/conmon.pid Type=forking [Install] WantedBy=multi-user.target default.target
-
The
BindsTo
line line in the[Unit]
section defines the dependency on thepod-systemd-pod.service
unit file -
The
ExecStart
andExecStop
lines in the[Service]
section start and stop thecontainer0
respectively.
-
The
Display
container-container1.service
unit file:$ cat container-container1.service
Copy all the generated files to
$HOME/.config/systemd/user
for installing as a non-root user:$ cp pod-systemd-pod.service container-container0.service container-container1.service $HOME/.config/systemd/user
Enable the service and start at user login:
$ systemctl enable --user pod-systemd-pod.service Created symlink /home/user1/.config/systemd/user/multi-user.target.wants/pod-systemd-pod.service → /home/user1/.config/systemd/user/pod-systemd-pod.service. Created symlink /home/user1/.config/systemd/user/default.target.wants/pod-systemd-pod.service → /home/user1/.config/systemd/user/pod-systemd-pod.service.
Note that the service stops at user logout.
Verification steps
Check if the service is enabled:
$ systemctl is-enabled pod-systemd-pod.service enabled
Additional resources
-
podman-create
man page -
podman-generate-systemd
man page -
systemctl
man page - Running containers with Podman and shareable systemd services
- Making systemd services start at boot time
14.6. Auto-updating containers using Podman
The podman auto-update
command allows you to automatically update containers according to their auto-update policy. The podman auto-update
command updates services when the container image is updated on the registry. To use auto-updates, containers must be created with the --label "io.containers.autoupdate=image"
label and run in a systemd
unit generated by podman generate systemd --new
command.
Podman searches for running containers with the "io.containers.autoupdate"
label set to "image"
and communicates to the container registry. If the image has changed, Podman restarts the corresponding systemd
unit to stop the old container and create a new one with the new image. As a result, the container, its environment, and all dependencies, are restarted.
Prerequisites
-
The
containers-tool
meta-package is installed.
Procedure
Start a
myubi
container based on theregistry.access.redhat.com/ubi9/ubi-init
image:# podman run --label "io.containers.autoupdate=image" \ --name myubi -dt registry.access.redhat.com/ubi9/ubi-init top bc219740a210455fa27deacc96d50a9e20516492f1417507c13ce1533dbdcd9d
Optional: List containers that are running or have exited:
# podman ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 76465a5e2933 registry.access.redhat.com/9/ubi-init:latest top 24 seconds ago Up 23 seconds ago myubi
Generate a
systemd
unit file for themyubi
container:# podman generate systemd --new --files --name myubi /root/container-myubi.service
Copy unit files to
/usr/lib/systemd/system
for installing it as a root user:# cp -Z ~/container-myubi.service /usr/lib/systemd/system
Reload
systemd
manager configuration:# systemctl daemon-reload
Start and check the status of a container:
# systemctl start container-myubi.service # systemctl status container-myubi.service
Auto-update the container:
# podman auto-update
14.7. Auto-updating containers using systemd
As mentioned in section Auto-updating containers using Podman,
you can update the container using the podman auto-update
command. It integrates into custom scripts and can be invoked when needed. Another way to auto update the containers is to use the pre-installed podman-auto-update.timer
and podman-auto-update.service
systemd
service. The podman-auto-update.timer
can be configured to trigger auto updates at a specific date or time. The podman-auto-update.service
can further be started by the systemctl
command or be used as a dependency by other systemd
services. As a result, auto updates based on time and events can be triggered in various ways to meet individual needs and use cases.
Prerequisites
-
The
containers-tool
meta-package is installed.
Procedure
Display the
podman-auto-update.service
unit file:# cat /usr/lib/systemd/system/podman-auto-update.service [Unit] Description=Podman auto-update service Documentation=man:podman-auto-update(1) Wants=network.target After=network-online.target [Service] Type=oneshot ExecStart=/usr/bin/podman auto-update [Install] WantedBy=multi-user.target default.target
Display the
podman-auto-update.timer
unit file:# cat /usr/lib/systemd/system/podman-auto-update.timer [Unit] Description=Podman auto-update timer [Timer] OnCalendar=daily Persistent=true [Install] WantedBy=timers.target
In this example, the
podman auto-update
command is launched daily at midnight.Enable the
podman-auto-update.timer
service at system start:# systemctl enable podman-auto-update.timer
Start the
systemd
service:# systemctl start podman-auto-update.timer
Optional: List all timers:
# systemctl list-timers --all NEXT LEFT LAST PASSED UNIT ACTIVATES Wed 2020-12-09 00:00:00 CET 9h left n/a n/a podman-auto-update.timer podman-auto-update.service
You can see that
podman-auto-update.timer
activates thepodman-auto-update.service
.