Deploying the app as a service using systemd and Podman

This short guide is intended as an example of configuration (please note that it is experimental and as such not to be used in production!) for system admins who would like to deploy the Beacon as a service using Linux systemd unit config files.

Prerequisites

  • Linux OS
  • Podman version >= 2.0.4

To run Podman from Windows or MacOS you either use a remote client or run Linux inside a virtual machine.

Creating a common directory for service files

After having installed podman on your linux-like machine, ssh into this machine and create a folder in the user's home directory. This directory will contain all systemd unit config files:

mkdir -p ~/.config/systemd/user

MongoDB service file

First thing to do is choosing a MongoDB image to use as database. You could use either the official MongoDB image or any other MongoDB image you prefer. For the sake of this documentation, let's use the lightweight MongoDB image(mvertes/alpine-mongo). Pull the image from Docker Hub:

podman pull mvertes/alpine-mongo

Assign the image a name, so it will be later used in the systemd service file. In this case the name will be beacon-mongo:

podman run --security-opt=seccomp=unconfined -d --name beacon-mongo -p 27017:27017 alpine-mongo

Create a service file for MongoDB with the following command:

podman generate systemd --name beacon-mongo

The content of this file will look like this:

# container-beacon-mongo.service
# autogenerated by Podman 3.2.3
# Mon Mar 21 08:51:43 UTC 2022

[Unit]
Description=Podman container-beacon-mongo.service
Documentation=man:podman-generate-systemd(1)
Wants=network.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 beacon-mongo
ExecStop=/usr/bin/podman stop -t 10 beacon-mongo
ExecStopPost=/usr/bin/podman stop -t 10 beacon-mongo
PIDFile=/run/user/1000/containers/overlay-containers/2414fc2edfaf56869d7f31367ba23caf5f2a247d2ae88b62fc8d797362232878/userdata/conmon.pid
Type=forking

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

Add the following line to this file, in the [Unit] section:

BindsTo=beacon-mongo.service

Create a service config file under ~/.config/systemd/user:

touch ~/.config/systemd/user/beacon-mongo.service

And copy the generated file content into this service file.

After creating the unit file, to start the container automatically at boot time, type the following:

systemctl --user daemon-reload
systemctl --user enable beacon-mongo.service

Once the service is enabled, it will start at boot time. To start it immediately and check the status of the service, type the following:

systemctl --user start beacon-mongo.service
systemctl --user status beacon-mongo.service

To stop the service type the following command:

systemctl --user stop beacon-mongo.service

Beacon cli service file

podman create --name beacon clinicalgenomics/cgbeacon2

Create the service file under ~/.config/systemd/user:

touch ~/.config/systemd/user/beacon-cli.service

Generate the systemd file content:

podman generate systemd --name beacon

Add the content of the service file to the service file:

vi ~/.config/systemd/user/beacon-cli.service

Don't forget to include this line under the [Unit] section:

Requires= beacon-mongo.service

Reload services and enable beacon-cli

systemctl --user daemon-reload
systemctl --user enable beacon-cli.service

Beacon web service file

Let's create a service config file to start the Beacon web app and keep it running.

podman create --name beacon-web clinicalgenomics/cgbeacon2-server

Create the service file under ~/.config/systemd/user: Let's add the following unit file to the ~/.config/systemd/user folder:

touch ~/.config/systemd/user/beacon-web.service

Let's add the following content to the file

# beacon-web.service

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

[Service]
Environment=PODMAN_SYSTEMD_UNIT=%n
Restart=no # Eventually turn this into on-failure
ExecStart=/usr/bin/podman run \
            --env "MONGODB_HOST=mongodb" \
            --security-opt=seccomp=unconfined \
            --log-driver=journald \
            --name beacon-web \
            --tz local \
            -p 8000:8000 \
            clinicalgenomics/cgbeacon2-server
ExecStop=/usr/bin/podman stop beacon-web
ExecStopPost=/usr/bin/podman rm --ignore -f beacon-web
TimeoutStartSec=1800s
Type=forking

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

Reload services and enable beacon-cli

systemctl --user daemon-reload
systemctl --user enable beacon-web.service

Once the service is enabled, it will start at boot time. To start it immediately and check the status of the service, type the following:

systemctl --user start beacon-web.service
systemctl --user status beacon-web.service

Output from the command above:

● beacon-web.service - Podman beacon-web.service
   Loaded: loaded (/home/vagrant/.config/systemd/user/beacon-web.service; enabled; vendor preset: enabled)
   Active: activating (start) since Mon 2022-03-21 10:48:00 UTC; 3min 23s ago
     Docs: man:podman-generate-systemd(1)
Cntrl PID: 5390 (podman)
   CGroup: /user.slice/user-1000.slice/user@1000.service/beacon-web.service
           ├─5390 /usr/bin/podman run --env MONGODB_HOST=mongodb --security-opt=seccomp=unconfined --log-driver=journald --name beacon-web --tz local -p 8000:>
           ├─5402 /usr/bin/slirp4netns --disable-host-loopback --mtu=65520 --enable-sandbox --enable-seccomp -c -e 3 -r 4 --netns-type=path /run/user/1000/net>
           ├─5404 containers-rootlessport
           ├─5408 /usr/bin/fuse-overlayfs -o ,lowerdir=/home/vagrant/.local/share/containers/storage/overlay/l/UVIOW4TMABJJK5NP2TTAZQXCND:/home/vagrant/.local>
           ├─5412 containers-rootlessport-child
           ├─5419 /usr/bin/conmon --api-version 1 -c 5fc523663bdf26efee7af191ad4c70e184e05c3c1ec43bfd2c8541b23638c599 -u 5fc523663bdf26efee7af191ad4c70e184e05>
           └─5fc523663bdf26efee7af191ad4c70e184e05c3c1ec43bfd2c8541b23638c599
             ├─5427 /bin/sh -c gunicorn     --workers=$GUNICORN_WORKERS     --bind=$GUNICORN_BIND      --threads=$GUNICORN_THREADS     --timeout=$GUNICORN_TIM>
             ├─5438 /venv/bin/python /venv/bin/gunicorn --workers=1 --bind=0.0.0.0:8000 --threads=1 --timeout=400 --proxy-protocol --forwarded-allow-ips=10.0.>
             └─5440 /venv/bin/python /venv/bin/gunicorn --workers=1 --bind=0.0.0.0:8000 --thread

To stop the service type the following command:

systemctl --user stop beacon-web.service