How to start a Podman Container at system startup
In my article about containers, I had a few lines regarding Podman. In fact, I use this container tool since more than a year after discovering it on Fedora while searching for installing Docker on it (because, you know, habits).
I’ll maybe write something about Podman one day, but if you wonder why I heavily prefer it instead of Docker, here is a few reasons :
- Daemonless : there are no daemon for Podman, the tool communicates directly with the required APIs.
- Totally Docker CLI compatible, just put
alias docker=podman
and you should not have to change anything. - A non root user can run a container without any supplementary requirement
- Directly available on Red Hat-based systems (so with Fedora, CentOS 8, Rocky Linux 8, etc)
- Has a module for the Cockpit system management web GUI
- Compatible with the
docker-compose
specification thanks to thepodman-compose
tool
Anyway, let’s go back to the main topic : how to startup a Podman container at system boot ?
In fact, I’ve already answered to this question in my article How to automatically maintain a Linux Server. But let’s get a little more verbose. To resolve this issue, I’ll use systemd to startup the Container as a service.
How systemd services works
I won’t go in the details because systemd is a big software stack (and I won’t go into its controversies, that’s not the topic). Has you may know, systemd has replaced the former SysV init daemon on various Linux distros. The init service is the first started daemon that’s bring up everything else at startup, and will be the last to die when the system shutdown itself.
Unless the former init system, systemd relies on descriptive service files to specify how the daemon should start, stop and its behavior in case of failure or success. Systemd calls these services “Units”.
These service files can be located at various place :
- /etc/systemd/system (I usually use this one)
- /usr/lib/systemd/system
The services file are INI configuration files, here is for example Apache HTTPD service file on Rocky Linux 8 :
[Unit]
Description=The Apache HTTP Server
Wants=httpd-init.service
After=network.target remote-fs.target nss-lookup.target httpd-init.service
Documentation=man:httpd.service(8)
[Service]
Type=notify
Environment=LANG=C
ExecStart=/usr/sbin/httpd $OPTIONS -DFOREGROUND
ExecReload=/usr/sbin/httpd $OPTIONS -k graceful
# Send SIGWINCH for graceful stop
KillSignal=SIGWINCH
KillMode=mixed
PrivateTmp=true
[Install]
WantedBy=multi-user.target
You manage these service with systemctl
commands :
systemctl status <service>
: display the status of the servicesystemctl start <service>
: start the servicesystemctl stop <service>
: stop the servicesystemctl restart <service>
: restart the servicesystemctl enable <service>
: enable service at system bootsystemctl disable <service>
: disable service at system boot
You can query the logs with the command journalctl
.
journalctl -u <servicename> --follow
will display the service output intail -f
wayjournalctl --follow
will display all units activity
As systemd load these files in memory, when you modify their content you’ll need to reload the daemon. If you forget about it, it’ll complain anyway.
Warning: The unit file, source configuration file or drop-ins of freshrss.service changed on disk. Run ‘systemctl daemon-reload’ to reload units.
systemctl daemon-reload
Create a service file for a Container
podman
is able to generate systemd
services files for a container. By executing the following command on a started container :
$ podman generate systemd --new --name mycontainer
This will return a ready to use service file. You can use by writing it directly into a file :
$ podman generate systemd --new --name mycontainer >> /etc/systemd/system/mycontainer.service
With that, you can start your container at boot with systemctl enable mycontainer.service
Let’s do an example, I’ve run the Fedora image on a container.
$ podman run --rm -it fedora:latest /bin/bash
$ podman container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3d32ed3f2391 registry.fedoraproject.org/fedora:latest /bin/bash 6 seconds ago Up 6 seconds ago confident_liskov
By using the podman generate systemd
command I have a service file as a result :
podman generate systemd --new --name 3d32ed3f2391
# container-confident_liskov.service
# autogenerated by Podman 3.4.2
# Wed Jan 12 11:13:31 CET 2022
[Unit]
Description=Podman container-confident_liskov.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 --cgroups=no-conmon --rm --sdnotify=conmon -d -it fedora:latest /bin/bash
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
I’ve pasted the content to a dummy service file.
sudo vi /etc/systemd/system/test.service
Then, started this container that’s won’t do anything else to stop itself.
$ systemctl start test
## hanging a little then, nothing
## let's check in the journal
$ sudo journalctl -u test
-- Journal begins at Sun 2020-08-23 08:49:32 CEST, ends at Wed 2022-01-12 11:16:56 CET. --
janv. 12 11:16:36 vidar systemd[1]: /etc/systemd/system/test.service:1: Assignment outside of section. Ignoring.
janv. 12 11:16:39 vidar systemd[1]: /etc/systemd/system/test.service:1: Assignment outside of section. Ignoring.
janv. 12 11:16:39 vidar systemd[1]: Starting Podman container-confident_liskov.service...
janv. 12 11:16:39 vidar podman[826000]: 2022-01-12 11:16:39.806749097 +0100 CET m=+0.311249421 system refresh
janv. 12 11:16:39 vidar podman[826000]: time="2022-01-12T11:16:39+01:00" level=warning msg="The input device is not a TTY. The --tty and --interactive flags might not work properly"
janv. 12 11:16:39 vidar podman[826000]: Resolved "fedora" as an alias (/etc/containers/registries.conf.d/000-shortnames.conf)
janv. 12 11:16:39 vidar podman[826000]: Trying to pull registry.fedoraproject.org/fedora:latest...
janv. 12 11:16:41 vidar podman[826000]: Getting image source signatures
janv. 12 11:16:41 vidar podman[826000]: Copying blob sha256:4545346f2a492b62d5a82682efe19b0e8e7583d5c19f75a74c81d62ec536c32d
janv. 12 11:16:41 vidar podman[826000]: Copying blob sha256:4545346f2a492b62d5a82682efe19b0e8e7583d5c19f75a74c81d62ec536c32d
janv. 12 11:16:44 vidar podman[826000]: Copying config sha256:3059bef432ebb91a6a51d8f5cf20b033041dbddb3cab79628c1eb3412cbde0ae
janv. 12 11:16:44 vidar podman[826000]: Writing manifest to image destination
janv. 12 11:16:44 vidar podman[826000]: Storing signatures
janv. 12 11:16:45 vidar podman[826000]: 2022-01-12 11:16:45.024115071 +0100 CET m=+5.528615355 container create be6d44eedd9658b49d9b32e1a1ce4f7682ecd7b97b5c0af5391489893eccaed4 (image=registry.fedoraproject.org/f>
janv. 12 11:16:45 vidar podman[826000]: 2022-01-12 11:16:39.807474988 +0100 CET m=+0.311975282 image pull fedora:latest
janv. 12 11:16:45 vidar podman[826000]: 2022-01-12 11:16:45.623079986 +0100 CET m=+6.127580260 container init be6d44eedd9658b49d9b32e1a1ce4f7682ecd7b97b5c0af5391489893eccaed4 (image=registry.fedoraproject.org/fed>
janv. 12 11:16:45 vidar systemd[1]: Started Podman container-confident_liskov.service.
janv. 12 11:16:45 vidar podman[826000]: 2022-01-12 11:16:45.632440572 +0100 CET m=+6.136940846 container start be6d44eedd9658b49d9b32e1a1ce4f7682ecd7b97b5c0af5391489893eccaed4 (image=registry.fedoraproject.org/fe>
janv. 12 11:16:45 vidar podman[826000]: be6d44eedd9658b49d9b32e1a1ce4f7682ecd7b97b5c0af5391489893eccaed4
Yep, the service file did its job !
As I’ve put the --rm
argument in the command, the container won’t show itself when running podman container ls -a
.
Create a service file for a Container Compose
If you use podman-compose
, the previous method won’t work with it because the containers are removed when stopping the deployment. So the service file will try to start non existing containers and fail.
However, the following service file can start a podman-compose
service and is usually working for me :
[Unit]
Description=MyContainer
After=network-online.target
Wants=network-online.target
[Service]
Type=oneshot
RemainAfterExit=true
ExecStart=/usr/bin/podman-compose -f /path/to/docker-compose.yml up -d
ExecStop=/usr/bin/podman-compose -f /path/to/docker-compose.yml down
[Install]
WantedBy=multi-user.target
In the same way, just enable the service with systemd.
Just like any other service, you can check it running with the status command.
Enjoy !