第二天,就用一張圖講Podman Quadlet如何將容器變成systemd的服務,之後幾天再講實務面操作。
在Linux,uid(User Identifier,使用者識別碼)在0到1000歸root權限使用,編號1001起,才是rootless的uid,沒特別指定的話,通常在Linux建立的第一個帳號的uid就是從1001開始編起。本專案所建立的rootless帳號名為appuser,uid正是1001。
以下這張圖就是如何把Podman的容器轉成systemd的服務的流程:
上圖的a2a-xx的命名方式,是指a2a這個專案的xx模組,比如a2a-web、a2a-api等。
[Network]
# 內部隔離網路
# 用途:Backend APIs 之間的內部通訊
NetworkName=a2a-net
[Unit]
Description=React static site on SUSE NGINX
After=network-online.target
Wants=network-online.target
[Container]
Image=localhost/a2a-web:20260705-01
ContainerName=a2a-web
PublishPort=8080:80
Network=a2a-net.network
VolatileTmp=true
[Service]
Restart=no
TimeoutStartSec=900
[Install]
WantedBy=default.target
容器之間要能互相通訊,通常會建立一個.network檔,只有命名NetworkName,本例是a2a-network。而其它容器則需指定Network的值為a2a-network便能互相溝通。
而在.container檔裡,在[Container]標籤下指定什麼Image、ContainerName及PublishPort會對應到步驟五的.service內容。
4. 編輯完$HOME/.config/containers/systemd下的.container及.network檔後,需執行systemctl --user daemon-reload,它會更新步驟五下的所有.service檔,可以在執行後看步驟五的目錄最後修改日期。最後再用systemctl --user restart a2a-*.service重啟所有服務。加--user的參數是以appuser帳號下執行,若是root權限則可省略。
5. 以下就看執行systemctl --user daemon-reload過後的.service檔內容
# Automatically generated by /usr/lib/systemd/user-generators/podman-user-generator
#
[X-Network]
# 內部隔離網路
# 用途:Backend APIs 之間的內部通訊
NetworkName=a2a-net
[Unit]
Wants=podman-user-wait-network-online.service
After=podman-user-wait-network-online.service
SourcePath=/home/appuser/.config/containers/systemd/a2a-net.network
RequiresMountsFor=%t/containers
[Service]
ExecStart=/usr/bin/podman network create --ignore a2a-net
SyslogIdentifier=%N
Type=oneshot
RemainAfterExit=yes
# Automatically generated by /usr/lib/systemd/user-generators/podman-user-generator
#
[Unit]
Wants=podman-user-wait-network-online.service
After=podman-user-wait-network-online.service
Description=React static site on SUSE NGINX
After=network-online.target
Wants=network-online.target
SourcePath=/home/appuser/.config/containers/systemd/a2a-web.container
RequiresMountsFor=%t/containers
Requires=a2a-net-network.service
After=a2a-net-network.service
[X-Container]
Image=localhost/a2a-web:20260705-01
ContainerName=a2a-web
PublishPort=8080:80
Network=a2a-net.network
VolatileTmp=true
[Service]
Restart=no
TimeoutStartSec=900
Environment=PODMAN_SYSTEMD_UNIT=%n
KillMode=mixed
ExecStop=/usr/bin/podman rm -v -f -i a2a-web
ExecStopPost=-/usr/bin/podman rm -v -f -i a2a-web
Delegate=yes
Type=notify
NotifyAccess=all
SyslogIdentifier=%N
ExecStart=/usr/bin/podman run --name a2a-web --replace --rm --cgroups=split --network a2a-net --sdnotify=conmon -d --tmpfs /tmp:rw,size=512M,mode=1777 --publish 8080:80 localhost/a2a-web:20260705-01
[Install]
WantedBy=default.target
從上述.service內容看,就會看到直接編寫.service檔內容有多少,在執行systemctl --user daemon-reload後,.container沒寫到的值由quadlet代填入預設值。
6. 最後可以用systemctl --user [start|stop|status|restart|cat] a2a-xx.service來控制服務生命週期,活脫就是一日維運IT的工作內容。