Rocky 9:用 Quadlet 把容器交给 systemd(替代 generate systemd)
在 Rocky Linux 9.8 特权容器(宿主内核 5.14.0-687.54.1.el9_8,podman 5.8.2)中实际执行:写 /etc/containers/systemd/web.container、运行 /usr/libexec/podman/quadlet -dryrun -v 查看生成的 unit。日志:plans/content-expansion/evidence/logs/rocky-quadlet-services.log。
容器没有运行中的 systemd,systemctl start <unit> 未验证;本页验证的是 Quadlet 的生成结果,即配置到 unit 的翻译是否正确。
为什么不用 generate systemd 了
Section titled “为什么不用 generate systemd 了”podman generate systemd 已被上游弃用,它生成的是「快照式」unit:容器参数一变,unit 就得重新生成。Quadlet 反过来——你写声明式的 .container 文件,systemd 启动时现生成 unit,参数改了只需重启服务。
写一个 .container 文件
Section titled “写一个 .container 文件”[Unit]Description=webAfter=network-online.target
[Container]Image=docker.io/library/nginx:alpineContainerName=webPublishPort=8080:80Volume=webdata:/usr/share/nginx/html:ZEnvironment=NGINX_ENTRYPOINT_QUIET_LOGS=1
[Service]Restart=always
[Install]WantedBy=multi-user.target放在 /etc/containers/systemd/(root)或 ~/.config/containers/systemd/(rootless)。
先看它生成什么
Section titled “先看它生成什么”sudo /usr/libexec/podman/quadlet -dryrun -v[Unit]Wants=network-online.targetAfter=network-online.targetDescription=webSourcePath=/etc/containers/systemd/web.containerRequiresMountsFor=%t/containers
[Service]Restart=alwaysExecStop=/usr/bin/podman rm -v -f -i webType=notifyExecStart=/usr/bin/podman run --name web --replace --rm --cgroups=split \ --sdnotify=conmon -d -v webdata:/usr/share/nginx/html:Z \ --publish 8080:80 --env NGINX_ENTRYPOINT_QUIET_LOGS=1 \ docker.io/library/nginx:alpineExecStart 就是翻译结果:PublishPort → --publish 8080:80、Volume → -v、Environment → --env。dryrun 不创建 unit,也不会启动容器,适合在改配置前验证。
sudo systemctl daemon-reloadsudo systemctl start web.servicesystemctl status web.serviceQuadlet 生成的 unit 名为 <文件名>.service(如 web.container → web.service)。改了 .container 之后必须 daemon-reload 再重启服务才会重新生成。
- 改了文件不 daemon-reload:systemd 还持有旧 unit;
[Install]段缺失:systemctl enable无法生效(Quadlet 用WantedBy决定开机自启);- rootless 放错目录:rootless 的 Quadlet 目录是
~/.config/containers/systemd/,放/etc不会生效。
练习:写一个 .container 并查看生成的 unit
Section titled “练习:写一个 .container 并查看生成的 unit”sudo mkdir -p /etc/containers/systemdsudo tee /etc/containers/systemd/demo.container >/dev/null <<'EOF'[Unit]Description=demo[Container]Image=docker.io/library/nginx:alpinePublishPort=8081:80[Install]WantedBy=multi-user.targetEOFsudo /usr/libexec/podman/quadlet -dryrun -v | grep ExecStartsudo systemctl daemon-reloadsudo systemctl start demo.servicesystemctl is-active demo.service检查:
grep ExecStart里出现--publish 8081:80systemctl start后is-active返回activepodman ps里能看到该容器
常见问题
Quadlet 和 generate systemd 有什么区别?
generate systemd 生成静态 unit,参数变了要重新生成;Quadlet 从 .container 文件在启动时生成 unit,改文件后 daemon-reload 再重启即可。
为什么 systemctl enable 说找不到 unit?
Quadlet 的 unit 是动态生成的,enable 依赖 [Install] 段的 WantedBy;缺这段或没 daemon-reload 都会失败。
rootless 容器怎么用 Quadlet?
把 .container 放到 ~/.config/containers/systemd/,用 systemctl --user daemon-reload 与 systemctl --user start;root 的目录是 /etc/containers/systemd/。
- 容器与镜像:容器与镜像
- 日志轮转:logrotate 实战
- 安装后核对:安装后 7 项核对