If you want to run more than one container in your server you will need some special network and volume so they can talk to each other and save the files safely. Many peoples think making container run together is very hard and needs big scripts but with Podman Quadlet it is not too much hard if you know the trick. Quadlet is a special tool inside Podman that reads simple configuration files and turns them into systemd services so your containers can start automatically when your computer boots up. We will learn how to make a database container that connects to a user defined network and uses a named volume so your data does not disappear when you stop the container.
Step 1: Making the Network Unit File
First thing we must do is making the network file because container need to talk with other containers inside a safe place. If you do not make a special network the containers will use the default network which is not very good if you want to use DNS names to find your database. We need to create a file called app-net.network inside the directory where systemd looks for Quadlet files.
You must open your terminal and write this command to create the file:
sudo vi /etc/containers/systemd/app-net.network
Inside this file we will write some simple lines to define our network. You should write exactly like this:
[Network]
NetworkName=app-net
DisableDNS=false
DNS=1.1.1.1
Let me explain what this file means because it looks simple but it does important things. The [Network] section tells Quadlet that this file is for making a Podman network. The NetworkName option is the name that Podman will show when you run the network commands. We set DisableDNS to false because we want our containers to resolve each other names using the container name which is very helpful when we add an API container later. The DNS option is set to 1.1.1.1 which is Cloudflare DNS so if the container needs to go to the internet to fetch some packages it can find the IP address easily.
Step 2: Making the Volume Unit File
Second thing is we need a place to save our database stuff because if the database container restarts or gets updated we do not want to lose all our users and tables. We can make a named volume using a Quadlet file ending with .volume which is very clean and easy to manage.
You should create the volume file by running this command in your terminal:
sudo vi /etc/containers/systemd/app-db-data.volume
Inside this file you only need to write a few lines to tell Podman that we want a named volume:
[Volume]
VolumeName=app-db-data
This file is very short but it is very powerful. The [Volume] header tells the system this is a volume unit. The VolumeName option gives a name to our volume inside the Podman storage. This makes systemd manage the volume life cycle so it will create the volume before the container tries to start up. If we did not have this file we would have to create the volume manually using commands which is easy to forget when you reboot your server.
Step 3: Creating the Container Unit File
Now we must make the big file for the database container itself which uses the network and the volume we did in the previous steps. We will use Postgres version 17 alpine because it is a very stable database and the alpine image is small so it does not take too much space on your disk.
Create the container file with this command:
sudo vi /etc/containers/systemd/app-db.container
Inside this file we will write the configuration that connects everything together. Please write these lines carefully:
[Container]
ContainerName=app-db
Image=docker.io/library/postgres:17-alpine
Network=app-net.network
Volume=app-db-data.volume:/var/lib/postgresql/data:Z
Environment=POSTGRES_PASSWORD=changeme
Environment=POSTGRES_DB=app
[Service]
Restart=always
[Install]
WantedBy=multi-user.target
This file is a bit longer so I will explain every part for you. In the [Container] section we have ContainerName which is the name of our running container. The Image option tells Podman to download Postgres from Docker Hub. The Network option is very important because we put the name of our network file which is app-net.network and not just the network name. This tells Quadlet that the container depends on that network file.
The Volume option is also very interesting. We write app-db-data.volume to tell the container to use our volume file and then we write a colon and the path inside the container which is /var/lib/postgresql/data. At the end of the volume option we put a colon and capital Z. This Z is very important if you use Fedora or Red Hat because it tells SELinux to change the security label of the volume so the container can write to it without getting permission denied errors.
We also use Environment options to set the database password and the default database name. You should change the password to something more secure if you are not just testing this on your own machine. In the [Service] section we set Restart=always so if the database crashes systemd will start it up again. The [Install] section has WantedBy=multi-user.target which means this service will start automatically when your server boots up to the normal terminal screen.
Step 4: Reloading Systemd and Starting the Service
Now we have three files in our systemd directory but they are not running yet. Quadlet works by generating normal systemd files from our configuration files when systemd reloads. We need to tell systemd to look at our new files and run the generator.
You must run these commands in your terminal:
sudo systemctl daemon-reload
sudo systemctl start app-db.service
The first command systemctl daemon-reload is the most important one. It tells systemd to look at /etc/containers/systemd/ and run the Quadlet generator. The generator looks at our container file and sees that it needs the network and the volume first. It will write normal service files inside a temporary folder and then we can start our database.
When you run systemctl start app-db.service systemd is smart enough to see that the container needs the network and the volume. It will create the app-net network and the app-db-data volume first and then it will pull the Postgres image and start the container. This is very cool because you do not need to start them one by one in the correct order yourself.
Step 5: Verifying Everything works
After you run the start command you should check if everything is running fine and there are no errors in your setup. We can use some Podman commands to see if the network, volume, and container are created.
Run these commands to verify your setup:
sudo podman ps
sudo podman network ls
sudo podman volume ls
The first command podman ps will show you the running containers. You should see app-db in the list and it should show that it is running and listening on the default Postgres port. The second command podman network ls will show you all networks and you should see app-net in that list which means our network file worked. The third command podman volume ls will show you the volumes and you should see app-db-data which means our database files are safe on the host disk.
Step 6: Understanding how to use Pod Unit Files
Sometimes you do not want to use separate networks for your containers because you want them to share the exact same network space. In Podman you can use a Pod to group containers together. Containers inside the same Pod can talk to each other using localhost which is very fast and easy. Quadlet also supports .pod files for this job.
If you want to use a Pod you can create a file called mypod.pod:
sudo vi /etc/containers/systemd/mypod.pod
Inside the pod file you can write:
[Pod]
PodName=mypod
Then inside your container files instead of writing Network=app-net.network you can write:
Pod=mypod.pod
This will make your containers run inside the same pod. It is very useful when you have a frontend container and a backend container that need to talk very fast without exposing ports to the outside world.
In conclusion, Quadlet is a very helpful tool that makes managing containers with systemd much easier than writing old style bash scripts or complex docker-compose files. By using separate files for networks, volumes, and pods, you can make a clean structure that systemd can start and stop in the correct order. This helps keeping your database files safe and your container connections strong even after your server restarts.