Podman Quadlet 入门
适用于 AlmaLinux 9.4+ & 10 / Rocky Linux 9.4+ & 10 / CentOS Stream 9 & 10(Podman 4.4+)
要让容器在开机时自动启动、崩溃后自动重启,过去你得用 podman generate systemd 生成一份服务单元。这个方式已经被官方弃用。从 Podman 4.4 起,Podman 内置了 Quadlet:你只写一份声明式的 .container 文件,systemd 在启动时自动把它转换成服务单元来管理。配置更清晰,改起来也更简单。
- Quadlet 是什么,以及它为什么取代
podman generate systemd - 把单元文件放在哪里(root 与 rootless 的区别)
- 写一个
nginx.container文件并用 systemd 启动它 - 配置 rootless 自动启动与自动更新
- 其它单元类型(
.volume、.network、.pod等)的用途
- 一台运行 EL 9.4+ 或 EL 10 的系统
- 已安装 Podman 4.4 及以上(EL 9.4+/EL 10 默认自带)
- 普通用户的 sudo 权限
Quadlet 是什么
Section titled “Quadlet 是什么”Quadlet 是 Podman 4.4 起内置的一个 systemd 生成器。你把一份描述容器的 .container 文件交给 systemd,systemd 在 daemon-reload 时调用 Quadlet,自动生成对应的 .service 单元。
它的优势在于声明式:你只描述”想要什么”,而不是像 podman generate systemd 那样生成一份”当前状态的快照”。容器参数变化后,旧方式需要重新生成单元文件,而 Quadlet 只需编辑文件再 daemon-reload。
单元文件放在哪里
Section titled “单元文件放在哪里”Quadlet 会扫描固定的目录。放对位置是它能工作的前提:
| 场景 | 目录 |
|---|---|
| 系统级(root) | /etc/containers/systemd/(或发行版自带的 /usr/share/containers/systemd/) |
| 用户级(rootless) | ~/.config/containers/systemd/ |
第一个 .container 文件
Section titled “第一个 .container 文件”下面用一个 Nginx 容器演示完整流程。先创建单元文件:
[Unit]Description=Nginx web server
[Container]Image=docker.io/library/nginx:latestPublishPort=8080:80Volume=/srv/nginx/html:/usr/share/nginx/html:ZEnvironment=TZ=Asia/ShanghaiAutoUpdate=registry
[Service]Restart=always
[Install]WantedBy=default.target几个关键点:
Image=写镜像全路径(docker.io/library/...),避免 short-name 触发交互式仓库选择。PublishPort=等同于podman run -p,这里把宿主 8080 映射到容器 80。Volume=的:Z后缀在 SELinux 系统上自动打上正确标签(私有标签),等同于podman run -v ...:Z。AutoUpdate=registry启用镜像自动更新(见下文)。- 服务名 = 文件名去掉扩展名:
nginx.container→nginx.service。
接着按 root 或 rootless 分别启动。
把文件放进 /etc/containers/systemd/,然后:
-
重新加载,让 systemd 生成对应的
nginx.service:重新加载单元 $ sudo systemctl daemon-reload -
启动服务(注意服务名是
nginx,不是nginx.container):启动并查看状态 $ sudo systemctl start nginx$ sudo systemctl status nginx
把文件放进 ~/.config/containers/systemd/,然后用 --user:
-
重新加载用户实例:
重新加载用户单元 $ systemctl --user daemon-reload -
启动服务:
启动并查看状态 $ systemctl --user start nginx$ systemctl --user status nginx -
让用户服务在你退出登录后也继续运行:
启用 linger $ sudo loginctl enable-linger $(whoami)
自动更新镜像
Section titled “自动更新镜像”在 [Container] 里写 AutoUpdate=registry 后,再启用对应的定时器,Podman 会定期检查上游镜像是否更新并自动滚动:
$ sudo systemctl enable --now podman-auto-update.timer$ systemctl --user enable --now podman-auto-update.timer$ podman auto-update其它单元类型
Section titled “其它单元类型”Quadlet 不止 .container,常见单元类型还有:
| 文件后缀 | 用途 |
|---|---|
.container | 单个容器 |
.volume | 命名卷,可被 .container 的 Volume= 引用 |
.network | 自定义网络,可被 Network= 引用 |
.pod | 一组共享网络命名空间的容器(Pod) |
.kube | 直接运行 Kubernetes YAML(play kube) |
.image | 预先拉取镜像,供其它单元依赖 |
例如先声明一个卷,再在容器里引用它:
[Volume]# 生成名为 systemd-app-data 的卷[Container]Image=docker.io/library/postgres:16Volume=app-data.volume:/var/lib/postgresql/data:Z从旧方式迁移
Section titled “从旧方式迁移”如果你还在用 podman generate systemd 生成的 container-*.service,迁移思路很直接:把 podman run 的参数逐项翻译成 [Container] 段的字段。
podman run 参数 | Quadlet 字段 |
|---|---|
--name(可选) | ContainerName= |
-p 8080:80 | PublishPort=8080:80 |
-v src:dst:Z | Volume=src:dst:Z |
-e KEY=val | Environment=KEY=val |
--restart=always | [Service] 段的 Restart=always |
迁移后停用并删除旧的 container-*.service,避免端口/名称冲突。
改了 .container 文件却没生效?
Quadlet 只在 daemon-reload 时重新生成单元。每次编辑后都要 systemctl daemon-reload(rootless 加 --user),再 restart 服务。
systemctl start nginx.container 报找不到单元?
服务名是文件名去掉扩展名:nginx.container 对应 nginx.service,所以应执行 systemctl start nginx,而不是带 .container。
rootless 容器一退出登录就停了?
没有启用 linger。执行 sudo loginctl enable-linger $(whoami),用户服务才会在你不在线时继续运行。
启动时卡住,提示选择镜像仓库?
Image= 写了 short-name(如 nginx)触发了交互式选择。在单元文件里写镜像全路径 docker.io/library/nginx:latest。
卷挂载后容器读不到文件(权限拒绝)?
SELinux 拦截了。给 Volume= 加 :Z 后缀,例如 Volume=/srv/data:/data:Z,让 Podman 自动打上正确的 SELinux 标签。