跳转到内容
搜索 Rocky Linux 文档

    浏览当前文档目录

    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 的翻译是否正确。

    podman generate systemd 已被上游弃用,它生成的是「快照式」unit:容器参数一变,unit 就得重新生成。Quadlet 反过来——你写声明式的 .container 文件,systemd 启动时现生成 unit,参数改了只需重启服务。

    [Unit]
    Description=web
    After=network-online.target
    [Container]
    Image=docker.io/library/nginx:alpine
    ContainerName=web
    PublishPort=8080:80
    Volume=webdata:/usr/share/nginx/html:Z
    Environment=NGINX_ENTRYPOINT_QUIET_LOGS=1
    [Service]
    Restart=always
    [Install]
    WantedBy=multi-user.target

    放在 /etc/containers/systemd/(root)或 ~/.config/containers/systemd/(rootless)。

    Terminal window
    sudo /usr/libexec/podman/quadlet -dryrun -v
    [Unit]
    Wants=network-online.target
    After=network-online.target
    Description=web
    SourcePath=/etc/containers/systemd/web.container
    RequiresMountsFor=%t/containers
    [Service]
    Restart=always
    ExecStop=/usr/bin/podman rm -v -f -i web
    Type=notify
    ExecStart=/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:alpine

    ExecStart 就是翻译结果:PublishPort → --publish 8080:80、Volume → -v、Environment → --env。dryrun 不创建 unit,也不会启动容器,适合在改配置前验证。

    Terminal window
    sudo systemctl daemon-reload
    sudo systemctl start web.service
    systemctl status web.service

    Quadlet 生成的 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”
    Terminal window
    sudo mkdir -p /etc/containers/systemd
    sudo tee /etc/containers/systemd/demo.container >/dev/null <<'EOF'
    [Unit]
    Description=demo
    [Container]
    Image=docker.io/library/nginx:alpine
    PublishPort=8081:80
    [Install]
    WantedBy=multi-user.target
    EOF
    sudo /usr/libexec/podman/quadlet -dryrun -v | grep ExecStart
    sudo systemctl daemon-reload
    sudo systemctl start demo.service
    systemctl is-active demo.service

    检查:

    1. grep ExecStart 里出现 --publish 8081:80
    2. systemctl start 后 is-active 返回 active
    3. podman 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/。