[Mac] 使用 Podman 取代 Docker
在 Mac 上我一直都是使用 Docker Desktop 來跑 Docker Engine,
不過它的效能總覺得不甚理想,
常常 CPU 吃很高 (不過也許這就是要在 Mac 上開 Linux VM 的宿命)…
最近聽到同事在說 Podman 這個工具,
可以不用一直常駐跑一個 daemon,與 docker 相容性也不錯,
那就來試試看吧~
1. 安裝 Podman
在 Mac 上用 Homebrew 來安裝 Podman:
brew install podman
裝好後執行 podman info ,目前是不行的,
因為我們還沒有 Linux VM:
$ podman info Cannot connect to Podman. Please verify your connection to the Linux system using `podman system connection list`, or try `podman machine init` and `podman machine start` to manage a new Linux VM Error: unable to connect to Podman socket: Get "http://d/v4.7.2/libpod/_ping": dial unix ///var/folders/tc/h5mk5_ts4278q5r3bk_1vxc00000gp/T/podman-run--1/podman/podman.sock: connect: no such file or directory
2. 安裝 Podman Machine
先看一下 podman machine 有哪些參數可用:
$ podman machine Manage a virtual machine Description: Manage a virtual machine. Virtual machines are used to run Podman. Usage: podman machine [command] Available Commands: info Display machine host info init Initialize a virtual machine inspect Inspect an existing machine list List machines os Manage a Podman virtual machine's OS rm Remove an existing machine set Set a virtual machine setting ssh SSH into an existing machine start Start an existing machine stop Stop an existing machine
接著就可以先執行 podman machine init 來建立一台 Linux VM,
它看起來是會抓一個 CoreOS 的 QEMU 映像檔下來,
所以應該是用 QEMU 來跑這 VM 的:
$ podman machine init
Downloading VM image: fedora-coreos-39.20231101.2.1-qemu.x86_64.qcow2.xz: done
Extracting compressed file: podman-machine-default_fedora-coreos-39.20231101.2.1-qemu.x86_64.qcow2 [==================>---] 544.9MiB / 620.5M
Extracting compressed file: podman-machine-default_fedora-coreos-39.20231101.2.1-qemu.x86_64.qcow2: done
Image resized.
Machine init complete
To start your machine run:
podman machine start
執行 podman machine start 來啟動 VM:
$ podman machine start
Starting machine "podman-machine-default"
Waiting for VM ...
Mounting volume... /Users:/Users
Mounting volume... /private:/private
Mounting volume... /var/folders:/var/folders
This machine is currently configured in rootless mode. If your containers
require root permissions (e.g. ports < 1024), or if you run into compatibility
issues with non-podman clients, you can switch using the following command:
podman machine set --rootful
API forwarding listening on: /Users/testuser/.local/share/containers/podman/machine/qemu/podman.sock
The system helper service is not installed; the default Docker API socket
address can't be used by podman. If you would like to install it run the following commands:
sudo /usr/local/Cellar/podman/4.7.2/bin/podman-mac-helper install
podman machine stop/usr/local/Cellar/podman/4.7.2/bin/podman-mac-helper; podman machine start/usr/local/Cellar/podman/4.7.2/bin/podman-mac-helper
You can still connect Docker API clients by setting DOCKER_HOST using the
following command in your terminal session:
export DOCKER_HOST='unix:///Users/testuser/.local/share/containers/podman/machine/qemu/podman.sock'
Machine "podman-machine-default" started successfully
我想要容易直接有 root 權限,減少一些未來的麻煩,
所以要先把 VM 停下來、設定成 rootful、再重新啟動 VM:
podman machine stop podman machine set --rootful podman machine start
跑 podman info 看一下目前的狀態:
$ podman info
host:
arch: amd64
buildahVersion: 1.32.0
cgroupControllers:
- cpuset
- cpu
- io
- memory
- hugetlb
- pids
- rdma
- misc
cgroupManager: systemd
cgroupVersion: v2
conmon:
package: conmon-2.1.7-3.fc39.x86_64
path: /usr/bin/conmon
version: 'conmon version 2.1.7, commit: '
cpuUtilization:
idlePercent: 77.24
systemPercent: 14.31
userPercent: 8.45
cpus: 1
databaseBackend: boltdb
distribution:
distribution: fedora
variant: coreos
version: "39"
eventLogger: journald
freeLocks: 2048
hostname: localhost.localdomain
idMappings:
gidmap: null
uidmap: null
kernel: 6.5.9-300.fc39.x86_64
linkmode: dynamic
logDriver: journald
memFree: 1592528896
memTotal: 2048520192
networkBackend: netavark
networkBackendInfo:
backend: netavark
dns:
package: aardvark-dns-1.8.0-1.fc39.x86_64
path: /usr/libexec/podman/aardvark-dns
version: aardvark-dns 1.8.0
package: netavark-1.8.0-2.fc39.x86_64
path: /usr/libexec/podman/netavark
version: netavark 1.8.0
ociRuntime:
name: crun
package: crun-1.11-1.fc39.x86_64
path: /usr/bin/crun
version: |-
crun version 1.11
commit: 11f8d3dc9fc4bb8a0adcff5ba8bd340f24612701
rundir: /run/crun
spec: 1.0.0
+SYSTEMD +SELINUX +APPARMOR +CAP +SECCOMP +EBPF +CRIU +LIBKRUN +WASM:wasmedge +YAJL
os: linux
pasta:
executable: /usr/bin/pasta
package: passt-0^20231004.gf851084-1.fc39.x86_64
version: |
pasta 0^20231004.gf851084-1.fc39.x86_64
Copyright Red Hat
GNU General Public License, version 2 or later
<https://www.gnu.org/licenses/old-licenses/gpl-2.0.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
remoteSocket:
exists: true
path: /run/podman/podman.sock
security:
apparmorEnabled: false
capabilities: CAP_CHOWN,CAP_DAC_OVERRIDE,CAP_FOWNER,CAP_FSETID,CAP_KILL,CAP_NET_BIND_SERVICE,CAP_SETFCAP,CAP_SETGID,CAP_SETPCAP,CAP_SETUID,CAP_SYS_CHROOT
rootless: false
seccompEnabled: true
seccompProfilePath: /usr/share/containers/seccomp.json
selinuxEnabled: true
serviceIsRemote: true
slirp4netns:
executable: /usr/bin/slirp4netns
package: slirp4netns-1.2.2-1.fc39.x86_64
version: |-
slirp4netns version 1.2.2
commit: 0ee2d87523e906518d34a6b423271e4826f71faf
libslirp: 4.7.0
SLIRP_CONFIG_VERSION_MAX: 4
libseccomp: 2.5.3
swapFree: 0
swapTotal: 0
uptime: 0h 1m 56.00s
plugins:
authorization: null
log:
- k8s-file
- none
- passthrough
- journald
network:
- bridge
- macvlan
- ipvlan
volume:
- local
registries:
search:
- docker.io
store:
configFile: /usr/share/containers/storage.conf
containerStore:
number: 0
paused: 0
running: 0
stopped: 0
graphDriverName: overlay
graphOptions:
overlay.mountopt: nodev,metacopy=on
graphRoot: /var/lib/containers/storage
graphRootAllocated: 106769133568
graphRootUsed: 2324676608
graphStatus:
Backing Filesystem: xfs
Native Overlay Diff: "false"
Supports d_type: "true"
Supports shifting: "true"
Supports volatile: "true"
Using metacopy: "true"
imageCopyTmpDir: /var/tmp
imageStore:
number: 0
runRoot: /run/containers/storage
transientStore: false
volumePath: /var/lib/containers/storage/volumes
version:
APIVersion: 4.7.0
Built: 1695838680
BuiltTime: Thu Sep 28 02:18:00 2023
GitCommit: ""
GoVersion: go1.21.1
Os: linux
OsArch: linux/amd64
Version: 4.7.0
3. 使用 Podman 啟動容器
Podman 的用法和 Docker 差不多,
下面指令是在背景跑一個 httpd 的容器,並且將本機的 8080 port 映射到容器的 80 port:
$ podman run -dt -p 8080:80/tcp docker.io/library/httpd Trying to pull docker.io/library/httpd:latest... Getting image source signatures Copying blob sha256:6a3b76b70f7385a99e72877fac4d1e00f4466859ed3ea50891bab80908e22c0b Copying blob sha256:578acb154839e9d0034432e8f53756d6f53ba62cf8c7ea5218a2476bf5b58fc9 Copying blob sha256:c1a8c8567b78fc222c60d83831081d5578fd80e6c30ee0bcf8a79019824301a1 Copying blob sha256:10b9ab03bf458e12adc435ae235b1f58f473fea23c2cdf6d88407d92a4a51c41 Copying blob sha256:74dbedf7ddc012b3398b2c645974f1f6e30a9592fef541d02faf456e40b67bc4 Copying config sha256:7f6a969e81a54d01e2fc08fd45025badf8f2418d3530a3a484b77ab826a1b4a7 Writing manifest to image destination cc6028fb57848297da81b80a8f9bd784ff6b9770399f7da6f5715bd764c51a1c
執行 podman ps 可以查看執行中的容器:
$ podman ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES cc6028fb5784 docker.io/library/httpd:latest httpd-foreground 18 seconds ago Up 17 seconds 0.0.0.0:8080->80/tcp xenodochial_merkle
4. 使用 Docker 指令操控 Podman 容器
剛剛跑起來的 Podman 容器,直接跑 docker ps 是看不到的,
因為 docker 指令會去連結它預設的一個 Unix socket,和 Podman 用的不是同一個:
$ docker ps Cannot connect to the Docker daemon at unix:///Users/testuser/.docker/run/docker.sock. Is the docker daemon running?
記得剛剛在 podman machine start 的訊息中,有看到一個 DOCKER_HOST 的環境變數。
把它拿來設定後,再執行 docker ps ,就可以成功連線看到容器囉:
$ export DOCKER_HOST='unix:///Users/testuser/.local/share/containers/podman/machine/qemu/podman.sock' $ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES cc6028fb5784 httpd:latest "httpd-foreground" 14 minutes ago Up 14 minutes 80/tcp xenodochial_merkle
以上就是簡單的 Podman 安裝與使用方法,
之後會盡量使用 Podman 來取代 Docker 看看,
再觀察看是不是有哪些異同之處呢?~
參考資料:Podman Installation