Podman with Quadlet

Podman with Quadlet

This guide will help you get started with Podman and Quadlet in a simple, non-technical way. Scroll down for templates for .container, .network, and .env files.

Did you know? You can use Cockpit or Portainer with Podman for easier container management.

What is Quadlet?

Quadlet is a way to manage containers in Podman using systemd. You write .container files, and systemd runs and manages the container for you. This makes it easier to start, stop, and update containers without needing complex scripts.

Rootless Setup

Rootless means you don't need admin (root) permissions to run containers. If something breaks out of the container, it won't cause too much damage.

Step-by-Step Guide

Set up the directories:

mkdir -p ~/.config/containers/systemd/

Later, put your .container, .network, and .env files in this directory.

Create or modify a .container file:

nano ~/.config/containers/systemd/myapp.container

This is where you define your container. Example template below.

Reload systemd:

systemctl --user daemon-reload

Prepare persistent storage:

mkdir -p /path/to/storage/containerfolder

Before starting the container, create the directories for persistent storage.

Start the container:

systemctl --user start myapp.service

Troubleshooting:

journalctl --user -u myapp.service --no-pager -n 50

If something goes wrong, check logs.

Rootful Setup (Admin Access)

In rootful mode, you need admin (root) permissions.

Use sudo: Prefix every command with sudo.

Change directory for container files: Put your .container files in /etc/containers/systemd/.

Run commands:
Same as rootless, but without the --user flag:

sudo systemctl start myapp.service

Updates

Auto-updating Containers
To automatically update your containers: Add AutoUpdate=registry in your .container file.

Enable the Podman auto-update service:

systemctl --user enable podman-auto-update

Manual Updates
Pull the latest image:

podman pull docker.io/my-image:latest

Restart the container:

systemctl --user restart myapp.service

Example Templates

.container file template

[Unit]
# (Optional) A brief description of the service
Description=
# (Optional) Services you want to run with this one
Wants=
# (Optional) Services that need to start before this one
After=

[Container]
# (Mandatory) The container's name
ContainerName=
# (Mandatory) The container image to use (e.g., docker.io/library/alpine)
Image=
# (Optional) Path to an .env file
EnvironmentFile=
# (Optional) Key=value pairs for environment variables
Environment=
# (Optional) Persistent storage paths (host:container)
Volume=
# (Optional) Custom network for the container
Network=
# (Optional) Ports to expose (host:container)
PublishPort=
# (Optional) Custom command to run in the container
Exec=
# (Optional) Additional Podman arguments
PodmanArgs=
# (Optional) Extra capabilities to add to the container
AddCapability=
# (Optional) Add host devices to the container
AddDevice=
# (Optional) Disable SELinux labels
SecurityLabelDisable=
# (Optional) Run as a specific user inside the container
User=
# (Optional) Autoupdate (also needs to be enabled systemctl --user enable podman-auto-update)
AutoUpdate=registry
# (Optional) Add metadata labels to the container
Label=
# (Optional) User ID mapping. Example: 0:10000:10 (Inside:Outside:Range)
UIDMap=
# (Optional) Group ID mapping Example: 0:10000:10 (Inside:Outside:Range)
GIDMap=

[Service]
# (Optional) Set to 'always' or 'on-failure' to restart on failure
Restart=
# (Optional) Time to wait before considering a failure
TimeoutStartSec=

[Install]
# (Optional) Target to start with (default: multi-user.target)
WantedBy=

.network file template

The gateway and subnet cannot be the same as other containers or your home network. Make sure to check that if you have dependency errors and container not starting.

[Network]
# (Mandatory) Subnet for the network
Subnet=192.168.99.0/24  
# (Mandatory) Gateway IP address
Gateway=192.168.99.1    
# (Optional) Custom label for the network
Label=    

.env file template

Define environment variables:

# Example: PGID=200
ENVIRONMENT_FIELD=your_secret_value 

That's it! You're ready to manage containers with Quadlet.