ikke_t.podman_container_systemd
podman-container-systemd
NOTE: This role may still work, but further development is happening in the new linux system roles podman project. It’s actively being improved. Thanks to all contributors over the years!
This role manages container(s) on your host using systemd. Podman handles container events but doesn’t manage their lifecycle. For clusters, Kubernetes does this, while systemd manages it for local setups.
I created this role to help manage the lifecycle of Podman containers on my personal server, which isn’t a cluster. I want systemd to keep them running even after reboots.
What This Role Does:
- Installs Podman.
- Downloads required images.
- On reruns, it downloads the image again and restarts the container if the image has changed (currently not for pods).
- Creates a systemd service file for the container or pod.
- Creates a Kubernetes YAML file for the pod.
- Sets up volume directories for containers if they don’t exist (for pods, uses DirectoryOrCreate).
- Ensures the container or pod automatically restarts if it crashes.
- Makes sure the container or pod runs at system boot.
- Adds or removes exposed ports from the firewall.
- Allows running rootless containers under a specific user.
For more information, refer to these two blogs about the role:
These blogs explain how to run a single container or multiple containers in a pod using this module.
Note for Running Rootless Containers:
- The user must exist before you run this role.
- The user should have entries in the /etc/sub[gu]id files for the namespace range. If not, this role will add some variables there, but it’s best to check them.
- Some controls, like memory limits, won’t work as user.
- Increase
systemd_TimeoutStartSec
as we cannot prefetch images before starting the systemd unit. Systemd needs to wait for Podman to pull images before starting the container, which may take time depending on your network and image size.
Requirements:
- Requires a system that can run Podman, and Podman must be available in the package repositories. This role installs Podman. It also installs
firewalld
if you definecontainer_firewall_ports
. Installskubeval
for a pod ifcontainer_pod_yaml_template_validation: true
.
Role Variables:
This role requires several variables upon inclusion. Note that some options only apply to single containers or pods.
container_image_list
: List of images to run. If more than one, they run in a pod. Can include authentication info per image, like so:container_image_list: - image: docker.io/imagename user: exampleuser password: examplepw - image: docker.io/imagename2
container_image_user
: Optional default username for authentication with remote registries.container_image_password
: Optional default password for authentication with remote registries.container_name
: Identifies the container in systemd and Podman commands. The systemd service file will be namedcontainer_name--container-pod.service
. Can be overridden withservice_name
.container_run_args
: Additional arguments for Podman when running a single container. Not used for pods.container_cmd_args
: Any commands and arguments forpodman run
after specifying the image name. Not used for pods.container_run_as_user
: User under which systemd will run the container. Defaults to root.container_run_as_group
: Group under which systemd will run the container. Defaults to root.container_dir_owner
: Owner of the volume directories. Defaults tocontainer_run_as_user
.container_dir_group
: Group for the volume directories. Defaults tocontainer_run_as_group
.container_dir_mode
: Permissions for the volume directories. Defaults to '0755'.container_state
: The state of the container. Userunning
to install and run;absent
stops and removes.container_firewall_ports
: List of exposed ports to open on the firewall. Closed ifcontainer_state
is absent. If you don't wantfirewalld
installed, don't use this.systemd_TimeoutStartSec
: Time systemd waits for the container to start.systemd_tempdir
: Where temporary files for containers are stored. Defaults to/tmp
.service_name
: Naming convention for systemd service files.service_files_dir
: Directory for storing systemd service files.service_files_owner
: User that owns the systemd service files.service_files_group
: Group that owns the systemd service files.service_files_mode
: Permissions for the systemd service files.container_pod_yaml
: Path to the pod YAML file (required).container_pod_yaml_deploy
: Whether to deploy the pod YAML file (defaults tofalse
).container_pod_yaml_template
: Template for the pod YAML deployment.container_pod_yaml_template_validation
: Whether to validate the pod YAML file (defaults tofalse
).container_pod_labels
: Labels for the pod.container_pod_volumes
: Defines volumes for the pod.container_pod_containers
: Defines containers for the pod.
This playbook doesn't have a Python module to parse parameters for the Podman command. For now, pass the parameters like you would in the command line. See man podman
or Podman tutorials for more info.
To automatically update your images, add this label to container_cmd_args
: --label "io.containers.autoupdate=image"
.
Avoid using ansible.builtin.import_role
for this role if you intend to use it multiple times in a playbook to prevent falling into this anti-pattern.
Dependencies:
- containers.podman (collection)
- ansible.posix (collection)
Example Playbook:
Refer to tests/main.yml
for a sample. In short, include the role with variables.
Root Container Example:
- name: tests container
vars:
container_image_list:
- sebp/lighttpd:latest
container_name: lighttpd
container_run_args: >-
--rm
-v /tmp/podman-container-systemd:/var/www/localhost/htdocs:Z,U
--label "io.containers.autoupdate=image"
-p 8080:80
container_state: running
container_firewall_ports:
- 8080/tcp
- 8443/tcp
ansible.builtin.include_role:
name: podman-container-systemd
Rootless Container Example:
- name: ensure user
user:
name: rootless_user
comment: I run sample container
- name: tests container
vars:
container_run_as_user: rootless_user
container_run_as_group: rootless_user
container_image_list:
- sebp/lighttpd:latest
container_name: lighttpd
container_run_args: >-
--rm
-v /tmp/podman-container-systemd:/var/www/localhost/htdocs:Z,U
-p 8080:80
container_state: running
container_firewall_ports:
- 8080/tcp
- 8443/tcp
ansible.builtin.include_role:
name: podman-container-systemd
Rootless Pod Example:
- name: ensure user
user:
name: rootless_user
comment: I run sample container
- name: tests pod
vars:
container_run_as_user: rootless_user
container_run_as_group: rootless_user
container_image_list:
- sebp/lighttpd:latest
container_name: lighttpd-pod
container_pod_yaml: /home/rootless_user/lighttpd-pod.yml
container_pod_yaml_deploy: true
container_pod_yaml_template_validation: true
container_pod_labels:
app: "{{ container_name }}"
io.containers.autoupdate: 'image(1)'
container_pod_volumes:
- name: htdocs
hostPath:
path: /tmp/podman-container-systemd
type: DirectoryOrCreate
container_pod_containers:
- name: lighttpd
image: sebp/lighttpd:latest
volumeMounts:
- name: htdocs
mountPath: /var/www/localhost/htdocs:Z
ports:
- containerPort: 80
hostPort: 8080
container_state: running
container_firewall_ports:
- 8080/tcp
- 8443/tcp
ansible.builtin.include_role:
name: podman-container-systemd
License:
GPLv3
Author Information:
Ilkka Tengvall ilkka.tengvall@iki.fi
Role sets up container(s) to run on host with help of systemd.
ansible-galaxy install ikke_t.podman_container_systemd