Quadlet | 结合Systemd优雅启动容器(containers)
在Quadlet还未出现之前
我一直使用generate systemd生成systemd单元文件以便启动Podman容器
但现在看来
还可以更优雅
示例环境
OS

Podman Version

Quadlet小知识
什么是Quadlet?
Quadlet 是 Podman 中的一个功能,用于简化容器、Pod 和网络的系统级管理,通过 systemd 配置文件直接定义和管理容器服务。
核心概念
Quadlet 允许使用 .container, .pod, .network 文件直接定义容器或 Pod,这些文件会自动转换为 systemd 单元文件。
- 类似于
docker-compose的功能,但更紧密集成在 systemd 生态中,符合 Linux 原生服务管理方式。 - Quadlet 通过少量配置简化了 Podman 容器的管理和自启动。
优势
- 与 systemd 集成:容器可作为 systemd 服务管理,支持开机启动、自动重启等。
- 简化配置:比手动写复杂的 systemd 服务文件更简单,减少容器管理复杂性。
- 自动生成:Quadlet 会根据
.container文件自动生成标准的 systemd 文件,便于统一管理。 - 模块化:支持容器、Pod、网络独立定义,便于维护和扩展。
工作原理
- 在
/etc/containers/systemd/或~/.config/containers/systemd/目录中创建.container或.pod文件。 - 使用
systemctl启动或管理容器,Podman 会自动解析并运行定义的容器。 - Quadlet 将配置文件自动转化为对应的 systemd 单元文件,位于
/etc/systemd/system/。
总结
Quadlet 是 Podman 提供的 systemd 友好型容器管理工具,特别适合需要将容器作为系统服务运行的场景。
它简化了复杂的 systemd 服务文件编写过程,同时保留了 Podman 的无守护进程优势,非常适合自建服务和自动化部署。
需要安装吗?
自Podman 4.4后
Quadlet合并至Podman
因此不需要安装
Quadlet使用流程
- 编写Quadlet配置文件
- 使用systemd重载新的单元文件(此时systemd会生成相应容器的单元文件,相应容器交予systemd接管)
- 使用 systemctl start/stop/status 管理相应的容器
Quadlet配置文件路径
对于Root用户来说,Quadlet的配置文件位于以下两个目录
- /etc/containers/systemd/
- /usr/share/containers/systemd/
对于其他用户来说则是以下目录
- $XDG_CONFIG_HOME/containers/systemd/ or ~/.config/containers/systemd/
- /etc/containers/systemd/users/$(UID)
- /etc/containers/systemd/users/
Quadlet使用流程
编写Quadlet配置文件
让我们以Scrutiny容器的Quadlet配置文件为例来说明一下
可以看到配置文件以.container结尾且位于/usr/share/containers/systemd/
➜ ~ ll /usr/share/containers/systemd/scrutiny.container
-rw-r--r-- 1 root root 585 May 22 02:31 /usr/share/containers/systemd/scrutiny.container
➜ ~
查看配置文件如下所示
➜ ~ cat /usr/share/containers/systemd/scrutiny.container
[Unit]
Description=WebUI for smartd S.M.A.R.T monitoring
After=network-online.target
Wants=network-online.target
Before=shutdown.target
[Container]
AutoUpdate=registry
AddCapability=SYS_RAWIO
AddDevice=/dev/sda
AddDevice=/dev/sdb
AddDevice=/dev/sdc
AddDevice=/dev/sdd
AddDevice=/dev/sde
ContainerName=scrutiny
Image=ghcr.io/analogj/scrutiny:master-omnibus
PublishPort=10.7.7.7:41523:8080
PublishPort=10.7.7.7:41524:8086
Volume=scrutiny:/opt/scrutiny/config
Volume=scrutiny:/opt/scrutiny/influxdb
Volume=/run/udev:/run/udev:ro
Timezone=Asia/Shanghai
[Install]
WantedBy=multi-user.target default.target
➜ ~
可以看到大致有三部分组成分别为
- Unit
- Container
- Install
除Container外,其余配置将会被同步至Systemd单元文件
以上述配置为例,详解一下各部分配置
Unit
此项共写入了四个参数,分别为
- Description
- 对于此Systemd的描述
- After
- 在哪个单元后启动
- Wants
- 启动此单元需要哪些单元
- Before
- 在哪些单元关闭前关闭此单元
Container
- AutoUpdate=registry
- 是否自动更新此容器
- AddCapability=SYS_RAWIO
- 等效于Podman run 命令行中的 --cap-add SYS_RAWIO
- AddDevice=/dev/sda
- 等效于Podman run 命令行中的 --device /dev/sda
- ContainerName=scrutiny
- 设定容器名称,等效于Podman run 命令行中的 --name scrutiny
- Image=ghcr.io/analogj/scrutiny:master-omnibus
- 启动此容器所需镜像(名称格式需要与Podman Pull命令行中赋予的一致)
- PublishPort=10.7.7.7:41523:8080
- 映射容器端口,等效于我们熟悉的 -p
- Volume=scrutiny:/opt/scrutiny/config
- 卷映射,等效于我们熟悉的-v
- Timezone=Asia/Shanghai
- 时区配置,等效于Podman run 命令行中的--tz Asia/Shanghai
Install
使用Quadlet创建的service单元文件被视为瞬态,所以不能使用传统的 systemctl enable让其自启
但可以在Quadlet配置文件中的[Install]一项添加WantedBy=multi-user.target default.target让其开机自启
配置文件看起来是
[Install]
WantedBy=multi-user.target default.target
如若设定后发现并不可以开机自启,通常是因为容器准备启动时设备网络状态未就绪,容器无法监听对应接口导致启动失败,请正确配置启动顺序(上述演示配置文件已配置完毕)
生成systemd单元文件
使用以下命令生成Systemd单元文件
systemctl daemon-reload
接着我们查看一下生成的单元文件
systemctl cat *.service
若无法查到对应的单元文件,说明Quadlet配置文件有问题,请检查后重试
启动相应容器
systemctl start *.service
Podlet
假如说因我表述能力问题
各位尚未学会如何编写Quadlet配置文件
那么我们可以使用Podlet来自动生成Quadlet配置文件
Github主页
软件版本

使用流程示例
下述操作Copy自Github主页
假如我们有如下命令
podman run \
--restart always \
-p 8000:80 \
-p 8443:443 \
-v ./Caddyfile:/etc/caddy/Caddyfile:Z \
-v caddy_data:/data \
docker.io/library/caddy:latest
可以看到我们现在需要使用caddy:latest镜像生成一个容器
该容器开放80/443端口至host的8000/8443端口,并且映射了相应的主机目录
下面我们使用Podlet来自动生成Quadlet配置文件
$ podlet --file . --install --description Caddy \
podman run \
--restart always \
-p 8000:80 \
-p 8443:443 \
-v ./Caddyfile:/etc/caddy/Caddyfile:Z \
-v caddy_data:/data \
docker.io/library/caddy:latest
Wrote to file: ./caddy.container
$ cat caddy.container
[Unit]
Description=Caddy
[Container]
Image=docker.io/library/caddy:latest
PublishPort=8000:80
PublishPort=8443:443
Volume=./Caddyfile:/etc/caddy/Caddyfile:Z
Volume=caddy_data:/data
[Service]
Restart=always
[Install]
WantedBy=default.target
可以看到我们只需将Podlet Shell置于原有的Podman shell之上
它就可以为我们自动生成Quadlet配置文件 非常之方便
总结
若您在使用Podman
Quadlet和Podlet 是不可多得的优秀辅助工具
这将使我们更加方便优雅的管理我们的容器