快轉到主要內容

Podlet:將docker-compose轉成Podman Quadlets,以Systemd管理容器

· 民國114年乙巳年
·
切換繁體/簡體
分類   資訊科技 虛擬機與容器技術
標籤   Systemd Podman Docker
目錄

要同時跑多個容器服務,我們通常會寫一個docker-compose.yml,將每個服務的屬性都定義好,然後透過docker compose up指令啟動。

在Podman,要達成這個作法,有兩種方式:

  1. podman-compose:相容docker-compose的指令,用法類似,幾乎是一條podman compose up就能轉換過來。
  2. Podman Quadlets:將docker-compose的內容修改為符合Systemd服務檔,將Pomand容器服務變成Systemd服務的概念。這已經跟原本的docke-compose的yaml是不同語言了,需要自行改寫成Systemd語法。

本文Ivon討論第二種,以Podman Quadlets來跑多個服務的作法,將docker-compose.yml轉換到Podman Quadlets。

這張圖片使用ComfyUI + illustriousXL生成並做一些修改

據說Podman Quadlets的名字來源是將Kubernetes切成兩半,由8變成4,也就是扁平化後的Kubelet。意思是試圖用Systemd簡化管理容器的程序。

RedHat公司在官網部落格介紹了許多Podman Quadlets的好處,不過沒有很詳細的文件說明,因此Ivon決定研究一番。

Docker compose的另一種形式概念就是Podman Quadlets,跳脫了從單一yaml啟動全部服務的作法,而非全部交由一個Docker的daemon去管,透過daemonless的特性迴避單點故障。Quadlets讓Podman容器與Linux系統融合,方便以systemctl指令管理,這樣能夠更靈活的處理服務之間的依賴關係,還能設定開機自動在特定的target之後跟著啟動Podman容器服務。

依照Quadlets的概念,如果一個docker-compose.yml檔案有多個容器服務,則他們會被拆分成多個Systemd的服務檔(servcie unit)。一個服務檔裡面定義該容器的配置還有網路設定,還有依賴哪個容器才能啟動的關係。

yaml跟Systemd的格式根本不同,要將規則手動轉換感覺好麻煩喔?所幸我們有一個叫做「Podlet」的工具能夠自動轉換。它會讀取docker-compose.yml,並生成Systemd服務檔。這對於遷移現有的docker-compose十分有幫助。

1. 安裝Podlet
#

以Ubuntu來說,尚未收錄Podlet安裝套件,所以就直接從Github下載二進位檔,解壓縮放到/usr/bin/local/

wget https://github.com/containers/podlet/releases/download/v0.3.0/podlet-x86_64-unknown-linux-gnu.tar.xz

tar -xvf podlet-x86_64-unknown-linux-gnu.tar.xz

chmod +x podlet-x86_64-unknown-linux-gnu/podlet

sudo mv podlet-x86_64-unknown-linux-gnu/podlet /usr/bin/local/podlet

2. 將docker-compose.yml轉成Quadlets
#

  1. 指令用法:
podlet [選項] [指令]
  1. podlet允許根據映像檔、容器、容器網路,還有docker-compose.yml產生對應的Systemd service unit。

  2. 這裡我們只使用轉換docker-compose.yml的指令。將一份docker-compose.yml放置到目前的工作目錄:

mkdir -p ~/apache/html

vim docker-compose.yml
  1. 填入一個簡單的Apache容器服務範本
services:
  web: # 這個名稱將會成為.container服務檔名稱
    image: docker.io/library/httpd:latest
    ports:
      - "80:80"
    volumes:
      - /home/user/apache/html:/usr/local/apache2/htdocs/
  1. 開始轉換,Podlet會檢查不相容的部份並給出警告。如果只有一個容器,就只會建立一個.container檔案。多個服務就會自動拆成多個。
# 自動建立.container的服務檔,並允許開機自動啟動
podlet -u -i compose 

# 只輸出服務檔寫法,不建立檔案
podlet compose 
  1. Podman預設應該會將.container檔案放到~/.config/containers/systemd/,所以要重新載入Systemd
systemctl --user daemon-reload
  1. 然後,以systemctl啟動Podman容器。Podman Quadlet沒辦法用docker compose pull拉取容器,所以得讓它自動拉。
systemctl --user start web
  1. 要設定開機自動啟動就是這樣:
systemctl --user enable web
  1. 我們可以同時用podman以及systemctl的相關指令來操控這個容器。
systemctl --user status web

podman ps

3. 一些Quadlets的注意事項
#

  1. 在轉換docker-comose.yml前需要注意:使用的映像檔鍵值image:要寫出完整網址。例如image: docker.io/library/httpd:latest。不然Podmand會不知道從哪裡拉取映像檔。

  2. 關於Quadlets的服務檔,應該要放在/etc/containers/systemd/還是~/.config/containers/systemd/?Podlet預設是選擇後者,加強安全性,不過rootless容器可能會有一些權限問題,需要特權容器的話在.container檔加入PodmanArgs=--privileged。預設rootful的容器才放到/etc/containers/systemd/

  3. 使用者登出的時候,Podman容器可能會跟著被停止。要登出後仍繼續執行容器服務,使用這個指令:

loginctl enable-linger <使用者名稱>
  1. 對於rootless的Podman容器來說,需要使用net.ipv4.ip_unprivileged_port_start才可以存取1024以下的通訊埠:
echo "net.ipv4.ip_unprivileged_port_start=80" | sudo tee -a /etc/sysctl.conf

sudo sysctl -p
  1. Podman每個容器之間的網路是彼此隔離的,如果兩個容器之間依賴Docker內部的DNS通訊(例如需要存取資料庫),你可能要寫一個Pod,或者建立一個Podman Network,將兩個容器使用同一個Network Namespace,容器之間才能連線。

  2. 有時候你會覺得與其依賴Podlet轉換,還不如自己根據docker-compose.yml的邏輯,自行重寫Systemd服務檔。

4. 多容器實際操作案例:將Immich以Quadlets部署
#

目前Immich官方尚未有關於Podman的安裝指示,只有docker-compose.yml。它定義了4個容器服務,這正好適合測試一下Quadlets。

以下內容參考自jbtrystram/immich-podman-systemd,測試當下版本是v137.3。注意我是手動轉的,不想知道原理的可以直接用上面的版本。

  1. 放置.container的目錄可以針對每個Quadlets新增一個目錄,這樣就能放環境變數檔案。
mkdir ~/.config/containers/systemd/immich

cd ~/.config/containers/systemd/immich
  1. 將Immich官方提供的docker-compose.yml轉換為Quadlets,存在目前目錄。因為Immich的docker-compose.yml使用了環境變數,所以會轉換失敗,要手動刪掉$開頭的環境變數的部份。
wget -O docker-compose.yml https://github.com/immich-app/immich/releases/latest/download/docker-compose.yml

podlet -f -i compose
  1. 新增環境變數檔案,在immich.env裡面填入偏好的設定
wget -O immich.env https://github.com/immich-app/immich/releases/latest/download/example.env
  1. 因為容器之間需要通訊,得共享網路,新增一個Pod檔案~/.config/containers/systemd/immich/immich.pod,填入以下內容
[Pod]
PodName=immich
PublishPort=2283:2283
  1. 環境變數是含有Immich主服務的容器要讀取的,故編輯~/.config/containers/systemd/immich/immich-server.container,填入EnvironmentFile=immich.env

  2. 在所有的.container檔案裡面填入[Containers]Pod=immich.pod代表它們從屬於Immich Pod。

  3. 修正剩下.container檔案裡面的volume路徑。

  4. 透過Pod啟動全部的Immich服務,它應該會將依賴的服務一併拉起來

systemctl --user start immich-pod

systemctl --user start immich-server

5. 用圖形界面管理Quadlets服務
#

這樣講有點怪,應該沒有人想用圖形介面管理Linux的Systemd服務的吧?大部分都是用指令編輯,但就是有這種需求。桌面方案有Systemd Pilot,網頁有Cockpit的方案,OpenSUSE用戶可以嘗試YaST。

專門為Podman設計的Podman Desktop更是有專門的編輯選項。安裝完Quadlets的擴充套件後,就能列出Linux系統上的各個Pod狀況。

這樣一來,Podman Desktop圖形介面就能協助管理系統上的容器服務。只不過Quadlets的作法就變成更Linux-orientedㄌ,畢竟需要Systemd,對在其他作業系統跑容器服務的用戶來說可能會多一些學習成本。

相關文章

使用鏡像網路模式(Mirrored Mode),讓WSL的服務能從外網連線
分類   資訊科技 虛擬機與容器技術
標籤   WSL Docker
Nvidia Container Toolkit優點:不想裝CUDA但是想跑CUDA,那就改在Docker容器裡跑吧
分類   資訊科技 虛擬機與容器技術
標籤   Nvidia CUDA Docker
不只Ubuntu!Windows WSL用Distrobox裝多重Linux容器
分類   資訊科技 虛擬機與容器技術
標籤   Distrobox WSL Docker

此處提供二種留言板。點選按鈕,選擇您覺得方便的留言板。

(留言板載入中)這是Giscus留言板,需要Github帳號才能留言。支援Markdown語法,若要上傳圖片請善用外部圖床。您的留言會在Github Discussions向所有人公開。

Click here to edit your comments.

(留言板載入中)這是Disqus留言板,您可能會看到Disqus強制投放的廣告。為防止垃圾內容,有時留言可能會被系統判定需審核,導致延遲顯示,請見諒。若要上傳圖片請善用外部圖床網站。