Check out my blog for guides on podman, fedora core os, SELinux in containers and more: https://blog.nerdon.eu/tag/containers-virtualization/
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
.
Did you know? You can use Cockpit or Portainer with podman
Quadlet is a way to run and manage containers in Podman using systemd services. You write .container
files, and systemd takes care of running and managing the container.
Rootless means you don't need admin (root) permissions to run containers. If something malicious break out of the container, it won't do so much damage.
-
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 (important): Before starting the container, create the directories for persistent storage.
mkdir -p /path/to/storage/containerfolder
-
Start the container:
systemctl --user start myapp.service
-
Troubleshooting: If something goes wrong, you can try to use this command to check logs:
journalctl --user -u myapp.service --no-pager -n 50
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
- Same as rootless, but without the
To automatically update your containers:
-
Add the line
AutoUpdate=registry
in your.container
file. -
Enable the Podman auto-update service:
systemctl enable --now podman-auto-update.timer
That will make podman periodically check for new images. If you want to run a check for updates run
podman auto-update
You can check if the timer is active with
systemctl list-timers | grep podman-auto-update
- Pull the latest image:
podman pull docker.io/my-image:latest
- Restart the container:
systemctl --user restart myapp.service
Another way is follow the Auto-update instructions, but don't activate the auto-update timer, instead run podman auto-update
[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) 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). For graphical user interface systems default.target
WantedBy=
For setting up custom container networks:
[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=
Define environment variables:
ENVIROMENT_FIELD=your_secret_value # Add your custom variables here. Such as PGID=200
That's it! You're ready to manage containers with Quadlet.