How to Start Containers Automatically, with Podman and Systemd

Podman is the super handy tool for running containers on Linux. Whatever you’re using containers for, you can handle it with Podman.

But did you know that Podman also has a really cool feature to help you manage your container apps with Systemd (the system and service manager for Linux)?

When you add your containers as units into Systemd, you can treat them just like any other service.

This means that you can control containers using systemctl start and stop commands. And this also means that you can ensure that the containers are started whenever your server reboots.

This is mega-handy for containers which you want to run, and ensure that they keep running.

So how do you set it up? Let’s take a look.

Starting a container

Let’s start with a container. I’m going to run MongoDB, because a database is a good example of the kind of service that you want to keep running all the time, and restart it if it crashes.

By the way, this tutorial assumes that you’ve got SELinux enabled (which you should!):

$ getenforce 
Enforcing

So let’s first create a directory, so that Mongo can store its data:

mkdir /var/lib/mongo

Your application might not need storage, but I’m showing this step here, so you can see how you can run containers which store persistent data.

Next, we’ll start a container from the Mongodb image.

We also tell the container where it should store its data. In this case, we mount a volume which points to /var/lib/mongo:

podman run --rm --detach \
    --name toms-mongo \
    --volume /var/lib/mongo:/data/db:Z \
    docker.io/library/mongo

Did you notice the :Z label? It tells SELinux to label the directory, so that the container user can write to it.

Now the container should be running. Check it with podman ps:

$ podman ps
CONTAINER ID  IMAGE                    COMMAND  CREATED        STATUS            PORTS   NAMES
d3c69e928bf8  docker.io/library/mongo  mongod   4 seconds ago  Up 4 seconds ago          toms-mongo

This all seems good so far!

So now how do we make sure that the container restarts automatically, whenever the server reboots? To do that, we add it to systemd.

Adding the container to systemd

Next, we want to create a systemd service for the container.

Systemd is the brain that works in the background. It takes care of the things that you want to run in the background on a server.

Podman includes a podman generate systemd command, which outputs a valid systemd configuration file (called a unit) for the container.

So when you run podman generate systemd... it will produce something like this:

$ podman generate systemd --new --name toms-mongo 
# container-toms-mongo.service
# autogenerated by Podman 3.0.0-dev
# Mon Mar  8 17:59:37 UTC 2021

[Unit]
Description=Podman container-toms-mongo.service
Documentation=man:podman-generate-systemd(1)
Wants=network.target
After=network-online.target

[Service]
Environment=PODMAN_SYSTEMD_UNIT=%n
Restart=on-failure
TimeoutStopSec=70
ExecStartPre=/bin/rm -f %t/container-toms-mongo.pid %t/container-toms-mongo.ctr-id
ExecStart=/usr/bin/podman run --conmon-pidfile %t/container-toms-mongo.pid --cidfile %t/container-toms-mongo.ctr-id --cgroups=no-conmon --replace --rm --name toms-mongo -v /var/lib/mongo:/data/db:Z --detach docker.io/library/mongo
ExecStop=/usr/bin/podman stop --ignore --cidfile %t/container-toms-mongo.ctr-id -t 10
ExecStopPost=/usr/bin/podman rm --ignore -f --cidfile %t/container-toms-mongo.ctr-id
PIDFile=%t/container-toms-mongo.pid
Type=forking

[Install]
WantedBy=multi-user.target default.target

To register a unit with systemd, this file needs to go in /etc/systemd/system/.

So let’s run the podman generate systemd command, give it the name of our mongo container, and pipe the output from this command to the /etc/systemd/system directory:

podman generate systemd \
    --new --name toms-mongo \
    > /etc/systemd/system/toms-mongo.service

This should create the file. Let’s check:

$ ls -al /etc/systemd/system/toms-mongo.service
-rw-r--r--. 1 root root 918 Mar  8 18:16 /etc/systemd/system/toms-mongo.service

We can also use the command systemctl list-unit-files. This will show all the unit files that systemd is aware of:

$ systemctl list-unit-files | grep tom
proc-sys-fs-binfmt_misc.automount                                static         
toms-mongo.service                                               disabled       

The final step is to enable the service, and start it:

systemctl enable toms-mongo
systemctl start toms-mongo

Enabling the service ensures that it will start on the next boot. Starting the service starts it immediately.

And now our container should be running as a system service, with Podman and Systemd!

We can check, using systemctl status toms-mongo:

$ systemctl status toms-mongo
● toms-mongo.service - Podman container-toms-mongo.service
  Loaded: loaded (/etc/systemd/system/toms-mongo.service; enabled; vendor preset: disabled)
  Active: active (running) since Mon 2021-03-08 18:16:32 UTC; 3s ago
    Docs: man:podman-generate-systemd(1)
 Process: 17683 ExecStart=/usr/bin/podman run --conmon-pidfile /run/container-toms-mongo.pid --cidfile /run/container-toms-mongo.ctr-id --cgr>
 Process: 17681 ExecStartPre=/bin/rm -f /run/container-toms-mongo.pid /run/container-toms-mongo.ctr-id (code=exited, status=0/SUCCESS)
Main PID: 17817 (conmon)
   Tasks: 2 (limit: 11401)
   Memory: 1.8M
   CGroup: /system.slice/toms-mongo.service
           └─17817 /usr/bin/conmon --api-version 1 -c 79bf80ca6176aa84d5d577d01f9fed17bea7e042b81ed11373a726fa27e11b76 -u 79bf80ca6176aa84d5d5>

Mar 08 18:16:31 li1513-130.members.linode.com systemd[1]: Starting Podman container-toms-mongo.service...
Mar 08 18:16:31 li1513-130.members.linode.com podman[17683]: d3c69e928bf8c1c5b469c7a931eb0cd023712834cceb024fa2e56346cb766dd7
Mar 08 18:16:32 li1513-130.members.linode.com podman[17683]: 79bf80ca6176aa84d5d577d01f9fed17bea7e042b81ed11373a726fa27e11b76
Mar 08 18:16:32 li1513-130.members.linode.com systemd[1]: Started Podman container-toms-mongo.service.

Yaaasssssss.

Will it survive a reboot of the server?

Here’s…. the Moment of Truth.

Let’s see if systemd will restart the container, when the server gets rebooted.

Let’s reboot nooowww……..

shutdown -r now

And a few minutes later, I log in again…. (Look at all those pesky h4ck3rs trying to get into my box)

Last failed login: Mon Mar  8 18:20:01 UTC 2021 from 149.19.6.147 on ssh:notty
There were 17 failed login attempts since the last successful login.
Last login: Mon Mar  8 18:09:53 2021 from 51.4.51.52

Is the container running again? Let’s check it with podman ps:

# podman ps
CONTAINER ID  IMAGE                    COMMAND  CREATED             STATUS                 PORTS   NAMES
ff31eeddf640  docker.io/library/mongo  mongod   About a minute ago  Up About a minute ago          toms-mongo

That’s a yes! Woohoo!

And now you know how to use Podman and Systemd to run and manage containers on your Linux server.

Now it’s over to you. Try creating and running containers with systemd on your own Linux server. And if you don’t have a server to play with, then you can sign up with Linode today, and get some free cloud credits to get you started.

Happy container fun times!

Comments

Got any thoughts on what you've just read? Anything wrong, or no longer correct? Sign in with your GitHub account to leave a comment.

(All comments get added as Issues in our GitHub repo here, using the comments tool Utterances)