[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