Podman
- Opensource.com - Podman and user namespaces: A marriage made in heaven (opens in a new tab)
- Red Hat - Enable Sysadmin - What happens behind the scenes of a rootless Podman container? (opens in a new tab)
- From Podman to Kubernetes: A Practical Integration Guide | Better Stack Community (opens in a new tab)
Run a container as a systemd service
-
Podman before 4.4
- Provision a running container
podman run -d --name $container_name $image_name- Generate a systemd service unit file for the container
podman generate systemd --new --name $container_name > "$service_name.service"- Verify and tweak the unit file if needed, and the deploy
cp "$service_name.service" $HOME/.config/systemd/user- Start and enable the service
# Verify by running: > systemctl --user cat "$service_name.service" > systemctl --user start "$service_name.service" # Verify it runs correctly > systemctl --user enable "$service_name.service" # Auto start at login -
Podman 4.4+
-
Create a container unit file
1.1 Manually
# $HOME/.config/containers/systemd/$service_name.container # The container unit file has an extension of `.container` # It also has a dedicated section `Container` [Unit] Description=$container_description After=local-fs.target # The dedicated container section [Container] Image=$image Exec=$image_start_command [Install] # Start by default on boot WantedBy=multi-user.target default.target1.2 Using Podlet
# Install Podlet brew install podlet# Generate a systemd container unit file podlet $podman_command_to_run_a_container # e.g. podlet podman run -d --publish 8080:8080 --name $container_name $image_name -
Create a systemd service unit file based on the container unit file
systemctl --user daemon-reload -
Check the generated service unit file
/usr/libexec/podman/quadlet -dryrun -user -
Check the service status
systemctl --user status "$service_name.service" -
Start and enable the service
systemctl --user start "$service_name.service"
-
Use rootless Podman
-
All rootless containers are run inside the same user namespace.
-
When the container runs, any volumes which are shared with it, will appear inside the user namespace as owned by root/root.
-
Resources
Convert running container(s) / pod(s) / volume(s) -> Kubernetes manifest
Podman will always generate the specification as a Pod, as the smallest deployable unit in Kubernetes.
podman generate kube [$container_name... | $pod_name... | $volume_name...] > $kubernetes_yaml_fileRun a Pod using an existing Kubernetes YAML
podman kube play $kubernetes_yaml_fileHealth Check
Quadlet (systemd)
Quadlets allow you to manage containers declaratively using systemd.
Since version 4.4, Podman can create, start, and manage containers (including pulling images, creating volumes, and managing pods) through systemd.
Quadlets are simplified systemd unit files, recognized by their specific extensions, such as *.container, *.pod, or *.image that are processed during startup or when you reload the daemon using the systemctl daemon-reload command.
Quadlets generate the equivalent systemd unit files, streamlining the container management process.
Quadlet supports these unit file types:
-
Container units: Used to manage containers by running thepodman runcommand.- File extension:
.container - Section name:
[Container] - Required fields:
Imagedescribing the container image the service runs
- File extension:
-
Kube units: Used to manage containers defined in Kubernetes YAML files by running thepodman kube playcommand.- File extension:
.kube - Section name:
[Kube] - Required fields:
Yamldefining the path to the Kubernetes YAML file
- File extension:
-
Network units: Used to create Podman networks that may be referenced in .container or .kube files.- File extension:
.network - Section name:
[Network] - Required fields: None
- File extension:
-
Volume units: Used to create Podman volumes that may be referenced in .container files.- File extension:
.volume - Section name:
[Volume] - Required fields: None
- File extension:
-
Resources
-
GitHub - containers/podlet (opens in a new tab)
CLI tool to generate
Podman Quadletfiles -
podman-systemd.unit - systemd units using Podman Quadlet (opens in a new tab)
man podman-systemd.unit -
Podman Quadlets with Podman Desktop (opens in a new tab)
Need to install
Podman DesktopextensionPodman Quadlet
-
Convert a Podman container / pod / network / volume / image -> Quadlet (systemd unit file)
podlet generate [$container_name... | $pod_name... | $network_name... | $volume_name... | $image_name...] > $quadlet_fileConvert a Docker Compose spec file -> Quadlet
Generate Podman Quadlet files from a compose file
Creates a `.container` file for each service, a `.volume` file for each volume (if it has additional options set), and a `.network` file for each network.
The `--file` option must be a directory if used.
Some compose options are not supported, such as `build`.
When Podlet encounters an unsupported option, an error will be returned. Modify the compose file to resolve the error.
Usage: podlet compose [OPTIONS] [COMPOSE_FILE]
Arguments:
[COMPOSE_FILE]
The compose file to convert
If `-` or not provided and stdin is not a terminal, the compose file will be read from stdin.
If not provided, and stdin is a terminal, Podlet will look for (in order) `compose.yaml`, `compose.yml`, `docker-compose.yaml`, and `docker-compose.yml`, in the current working directory.
Options:
--pod
Create a `.pod` file and link it with each `.container` file.
The top-level `name` field in the compose file is required when using this option. It is used for the name of the pod and in the filenames of the created files.
Each container becomes a part of the pod and is renamed to "{pod}-{container}".
Published ports are taken from each container and applied to the pod.
--kube
Create a Kubernetes YAML file for a pod instead of separate containers
A `.kube` file using the generated Kubernetes YAML file is also created.
The top-level `name` field in the compose file is required when using this option. It is used for the name of the pod and in the filenames of the created files.
-h, --help
Print help (see a summary with '-h')Create a .pod unit file and link it with each .container unit file
podlet compose --pod ${docker_compose_file} > ${quadlet_file}Example:
# compose.yml
name: paperless-postgres
services:
postgres:
image: docker.io/postgres:16
container_name: db-postgres
environment:
POSTGRES_DB: paperless
POSTGRES_USER: paperless
POSTGRES_PASSWORD: paperless
PGDATA: /var/lib/postgresql/data/pgdata
ports:
- "5432:5432"
restart: on-failure
healthcheck:
test: ["CMD", "pg_isready", "-U", "paperless"]
interval: 30s
timeout: 30s
retries: 3# Need to extract file content from the genrated output, and save it to each unit file respectively
❯ podlet compose --pod compose.yml
# paperless-postgres-postgres.container
[Container]
ContainerName=db-postgres
Environment=POSTGRES_DB=paperless POSTGRES_USER=paperless POSTGRES_PASSWORD=paperless PGDATA=/var/lib/postgresql/data/pgdata
HealthCmd=["pg_isready","-U","paperless"]
HealthInterval=30s
HealthRetries=3
HealthTimeout=30s
Image=docker.io/postgres:16
Pod=paperless-postgres.pod
[Service]
Restart=on-failure
---
# paperless-postgres.pod
[Pod]
PublishPort=5432:5432Create a single Kubernetes YAML file for all resources involved
podlet compose --kube ${docker_compose_file} > ${kubernetes_manifest_file}Use [Kube] section in the systemd unit file (by convention, use .kube) to reference the generated Kubernetes manifest.
# service_name.kube
[Unit]
Description=Podman Pod Name
[Kube]
Yaml=/path/to/kubernetes_manifest.yaml
[Service]
Restart=always
[Install]
WantedBy=multi-user.target default.target