Podman 曾經是 CRI-O project 中的一部分,後來被分離出成為一個獨立 project, libpod。Podman (Pod Manager) 的目標是提供一個跟 Docker 相似體驗的 container CLI,提供給使用者創立和運行 container。
Table of Contents
開始之前
我們先來唸一段 All System Go Replacing Docker with Podman 中演講的一段宣言
I promise
To say container registries rather than docker registries
I promise
To say container images rather than docker images
I promise
To say containers or OCI containers rather than docker containers
安裝 Podman
Fedora
Podman 目前已經在 Fedora 的 Repo 中了,只要用內建的 package manager 安裝即可。
sudo dnf install podman
Ubuntu
Ubuntu 的話就會需要自己 build from source 了,首先先安裝一些需要的套件:
sudo apt-get update
sudo apt-get install libdevmapper-dev libglib2.0-dev libgpgme11-dev golang libseccomp-dev \
go-md2man libprotobuf-dev libprotobuf-c0-dev libseccomp-dev python3-setuptools
接下來要 build conmon:
export GOPATH=~/go
mkdir -p $GOPATH
git clone https://github.com/kubernetes-sigs/cri-o $GOPATH/src/github.com/kubernetes-sigs/cri-o
cd $GOPATH/src/github.com/kubernetes-sigs/cri-o
mkdir bin
make bin/conmon
sudo install -D -m 755 bin/conmon /usr/libexec/podman/conmon
建立一些需要的設定檔:
sudo mkdir -p /etc/containers
sudo curl https://raw.githubusercontent.com/projectatomic/registries/master/registries.fedora -o /etc/containers/registries.conf
sudo curl https://raw.githubusercontent.com/containers/skopeo/master/default-policy.json -o /etc/containers/policy.json
安裝 CNI plugin:
git clone https://github.com/containernetworking/plugins.git $GOPATH/src/github.com/containernetworking/plugins
cd $GOPATH/src/github.com/containernetworking/plugins
./build.sh
sudo mkdir -p /usr/libexec/cni
sudo cp bin/* /usr/libexec/cni
安裝 runc:
git clone https://github.com/opencontainers/runc.git $GOPATH/src/github.com/opencontainers/runc
cd $GOPATH/src/github.com/opencontainers/runc
make BUILDTAGS="seccomp"
sudo cp runc /usr/bin/runc
最後安裝 podman
git clone https://github.com/containers/libpod/ $GOPATH/src/github.com/containers/libpod
cd $GOPATH/src/github.com/containers/libpod
make
sudo make install PREFIX=/usr
Project Atomic PPA
當然也有更簡單的,直接使用 Project Atomic 的 PPA:
sudo add-apt-repository ppa:projectatomic/ppa
sudo apt update
sudo apt install podman
使用 Podman
使用 podman 非常的簡單,只需要在你的
下加入這行即可:.bashrc
alias docker=podman
這不是開玩笑,podman 的指令跟 docker 有 87% 相同,加入這行基本上可以無痛轉移,不過有一些小部分要注意的在接下來會再說明。
Why Podman?
沒有肥大的 Daemons
Podman 不像 Docker Engine 一樣有一個 daemon。
在使用 Docker CLI 的時候,Docker CLI 會透過 API 去跟 Docker Engine 説 「我要開一個 container」,這時 Docker Engine 才會透過 OCI Container runtime(預設是 runc)來啟動一個 container。這代表 Container 的 process 不會是 Docker CLI 的 child process,而是 Docker Engine 的 child process。
Podman 就不使用 daemon,而是直接透過 OCI runtime(預設也是 runc)來開啟 container,所以 container process 會直接是 podman 的 child process。這比較像傳統 Linux 的 fork/exec 的模式。這也代表系統管理員可以知道那個 container process 到底是誰啟動的,同時,如果利用 cgroups 對 podman command 做一些限制,同樣的所有 container 也會被這些限制做侷限。
這個模式也使 podman 可以透過把 podman 放進 systemd unit file 來利用 systemd 的一些進階功能。例如,systemd 中可以透過 notify 去實現service 的啟動順序,當有 container 中的 service 需要在其他 service 之前先啟動的話,後續的 service 會等待 container 送一個 notify signal 給 systemd,確認 container 已經啟動完成之後才會開始運行。透過 Docker CLI 這件事是沒辦法去實現的,但是 Podman 會 forward systemd 的資訊給 child process,所以 container process 在啟動完成後可以 notify systemd 它已經準備運作了。
Restart 消失了?
大部分人在一開始使用 Podman 的時候可能會發現 docker 指令中的
flag 被拿掉了。這是因為 Podman 不使用 Daemon,所以沒辦法透過 Daemon 去實現 auto restart 的功能。--restart
那該如何在系統重啟之後自動開啟 container 呢?
很簡單,同樣利用 systemd 就可以達成。
用 nginx 來當例子的話:
首先我們先跑一個 nginx container
sudo podman run -t -d -p 80:80 --name nginx nginx
會用 root 跑的原因是因為 rootless container 現在還不支援 port binding。
之後在 /etc/systemd/system
<code> 下建立一個 </code>
nginx_container.service
[Unit]
Description=Podman Nginx Service
After=network.target
After=network-online.target
[Service]
Type=simple
ExecStart=/usr/bin/podman start -a nginx
ExecStop=/usr/bin/podman stop -t 10 nginx
Restart=always
[Install]
WantedBy=multi-user.target
接下來啟用這個 service
sudo systemctl daemon-reload
sudo systemctl enable nginx_container.service
sudo systemctl start nginx_container.service
可以透過 staus 查看這個 service 的狀況
sudo systemctl status nginx_container.service
● nginx_container.service - Podman Nginx Service
Loaded: loaded (/etc/systemd/system/nginx_container.service; enabled; vendor preset: disabled)
Active: active (running) since Sat 2018-10-20 05:59:24 UTC; 1min 41s ago
Main PID: 845 (podman)
Tasks: 16 (limit: 4915)
Memory: 37.6M
CGroup: /system.slice/nginx_container.service
└─845 /usr/bin/podman start -a nginx
Oct 20 05:59:24 fedora-dev.novalocal systemd[1]: Started Podman Nginx Service.
之後每次系統重啟後 systemd 都會自動啟動這個 service(也就是 container)。
結論
Podman 是目前 container 生態系中的其中一個元件,其他的還有 CRI-O, Buildah 跟 Skopeo。之後有機會會寫一篇關於 Buildah 的介紹,至於 Skopeo 可以參考這篇 Skopeo: 管理 Container 映像檔及倉庫的方式
Reference
- Reintroduction of Podman
- libpod GitHub
- Using Systemd with Podman containers
- All System Go — Replacing Docker with Podman
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.
版主寫得真清楚明瞭, 不過裡面有一段不太懂,
如果 podman 不依賴於 container runtime daemon, ex: docker engine, crio 等等
他是怎去和 runc 溝通的? 不好意思不太熟 runc, 看起來 runc 不是一個 daemon,
很好奇例如 `sudo podman ps` 時, 它去哪邊得到目前正在跑的 containers?