Mac で Podman を動かす。docker コマンドも使えるようにする
環境構築
Podman Desktop
Podman Desktop を入れておくと環境を簡単に作成できる。
Homebrew でもインストール可能。
brew install podman-desktop
アプリを起動し「Initialize and Start」をクリックすると環境を作成できる。Docker Desktop などで docker 環境を立ち上げてる場合は停止しておくことをおすすめする。
Lima
Podman Desktop 上から作成できる環境は現時点で x86_64 のエミュレーションに rosetta が利用できない。
→ 2024-06-02 Podman v5.0.1 から rosetta が利用できるようになりました 🎉
また qemu によるマシン構築の都合でファイル共有は virtio-9p を使って行われ、その関係で bind mount 利用時にファイルのモード変更で問題が起きたり、パフォーマンスがあまりよくなかったりする。
ので、仮想マシンを Lima ベースにするのが個人的なおすすめ。
Lima も Homebrew でインストールできる。
brew install lima
Lima マシンで virtiofs や rosetta を利用できるような設定を以下に紹介しておく。
~/.lima/_config/default.yaml
を次のように作成する。[1]
# VirtualizationFramework を利用
vmType: "vz"
# virtiofsを使う
mountType: "virtiofs"
# inotifyを使う(hostのファイル変更を検知させる)
mountInotify: true
# 割当メモリの設定。未指定ならホストのメモリ量の半分
memory: "8GiB"
# ディスクサイズ。未指定なら 100 GiB に
disk: null
# x86_64 のエミュレーションに rosetta を利用する
rosetta:
enabled: true
binfmt: true
# ホームディレクトリを書き込み可能でマウントする(Docker Desktopと同様)
mounts:
- location: "~"
writable: true
# VirtualizationFramework有効なら以下も有効化できる。ゲストマシンとの疎通が速くなる
networks:
- vzNAT: true
provision:
- mode: system
script: |
#!/bin/bash
set -Eeux -o pipefail
# ログを見られるように
# see: https://github.com/containers/podman/issues/15159#issuecomment-1203851953
sudo usermod -a -G systemd-journal {{.User}}
- mode: system
script: |
#!/bin/bash
set -Eeux -o pipefail
if [[ -e /etc/binfmt.d/qemu-x86_64-static.conf ]] ; then
exit 0
fi
# fedora アップデート時に rosetta が使えなくなる問題を防ぐ
# https://github.com/containers/podman/pull/21670#issuecomment-2014694173
ln -s /dev/null /etc/binfmt.d/qemu-x86_64-static.conf
本当はホームディレクトリ(~
) のwritable(書き込み可能)なマウントはテストされてないのでやるべきではない のだが、8ヶ月くらい使っていて特に問題が起きたことはない。
また上記サンプルでは podman の network 設定 の pasta は rootless コンテナを立ち上げるときのネットワークをいい感じにやってくれるツールである。network.default_rootless_network_cmd
へ pasta をセットした。
少し補足すると、インターネットへの疎通が可能な veth(4)(仮想イーサネットデバイス)を作成するには特権が必要なので、このあたりをルートレスのまま上手く取り回すためにこれまで slirp4netns が使われてきた。
ただ slirp4netns はパフォーマンスや疎通元の IP アドレスが取れないなどの課題があり、それらの課題を一定解消したのが pasta である。(かなりざっくりした説明なので詳しくはドキュメントを参照されたい)
network.default_rootless_network_cmd="pasta"
を設定することで、ルートレスネットワークを作成するデフォルトのプログラムに pasta が使われるようになる。
→ 2024-06-02 追記: podman v5.0.0 からデフォルトで pasta が利用されるようになったため削除した
Lima の起動・停止など
Lima には仮想マシンのテンプレートがいくつかある。Podman 用のテンプレートでは(仮想マシン上で)root 権限を使わない rootless なものと root 権限ありの rootful なものとがある。
以下は Lima のコマンド例。
# rootless 環境の作成
# マシン名が「podman」になる
limactl create template://podman
# rootful 環境の作成
# そのままだとマシン名が podman-rootful になるので `--name=podman` で名称変更している
limactl create --name=podman template://podman-rootful
# 仮想マシン起動
limactl start podman
# 仮想マシンにアクセス
limactl shell podman
# 仮想マシンは fedora ベースなので、dnf で環境のアップデートができる
limactl shell podman -- sudo dnf update -y
マシンが起動したらメッセージが現れるので、それに従って
podman system connection add lima-<マシン名> "unix://<マシンの場所>/sock/podman.sock"
podman system connection default lima-<マシン名>
のコマンドを実行すると、podman から利用できるようになる。
Lima マシンを Podman Desktop に認識させる
Lima のマシン名を podman
にしておくと、Podman Desktop の Lima 拡張で認識してくれるようになる。
(コンテナやボリュームを Podman Desktop 上で確認できるようになる)
もし Podman Desktop に認識させるマシン名を変更したい場合は、Extention: Lima
の設定から変更できる。
docker クライアントの利用
Podman は Docker 互換の REST API を提供しているため、Docker CLI も利用できる。[2]
Podman Desktop をインストールすると docker コマンドもインストールされる。
もしインストールされてないようなら設定の Extentions からインストールできるはず。
(Docker Desktop をインストールしている場合 docker コマンドもインストール済のため、あまり意識する必要はなさそう)
Podman Desktop で環境を構築していればそのまま docker コマンドを使ってコンテナを作成できるはずだが、Lima で環境を構築した場合、先程のマシン起動時のメッセージ
podman system connection add lima-<マシン名> "unix://<マシンの場所>/sock/podman.sock"
podman system connection default lima-<マシン名>
を確認し "unix://<マシンの場所>/sock/podman.sock"
を DOCKER_HOST
環境変数に指定することで、docker コマンドで利用できるようになる。
export DOCKER_HOST=unix://<マシンの場所>/sock/podman.sock
もしくは /var/run/docker.sock
にシンボリックを作成してもよい[3] が、再起動すると消えるので、やるなら自動化した方がいいかも。
# もし既にあるなら削除
sudo rm /var/run/docker.sock
# シンボリックリンクを作成
sudo ln -s /<マシンの場所>/sock/podman.sock /var/run/docker.sock
もちろん docker context
に設定する形でも可能。こちらの場合、Docker Desktop の環境を残しながら切り替えて使える。
docker context create lima-<マシン名> --docker "host=unix://<マシンの場所>/sock/podman.sock"
docker context use lima-<マシン名>
# context 一覧を確認
docker context list
# 利用する context の切り替え(default に切り替えている)
docker context use default
buildkit の無効化
docker がイメージのビルドにデフォルトで使う buildkit はサポートされていない。ので無効化しておかないと、イメージをビルドするときに失敗する。buildkit は環境変数で無効化できる。
# buildkit の無効化
export DOCKER_BUILDKIT=0
-
詳しくは デフォルトテンプレート のコメントを参照されたい ↩︎
-
docker compose も利用できる ↩︎
-
Podman Desktop 上から環境を作成するとシンボリックは自動で作成される ↩︎
Virtualization.Framework に対応した podman machine で rosetta を利用できるようにする手順について Shion さん がリポジトリにまとめてくださっていた。感謝。
Shion さんにアドバイスいただいていた applehv + rosetta な手順を自分で試したときのメモを整理しておいておく。
仮想マシン設定
~/.config/containers/containers.conf
に以下を追加。環境変数 CONTAINERS_MACHINE_PROVIDER=applehv
を設定するのと同様の設定になる。
[machine]
provider = "applehv"
↑の設定は podman v5 でデフォルトになるらしい
マシン作成
podman machine init
↑必要なら CPU コア数(--cpus
)やメモリ(--memory
)などを設定する
起動設定
仮想マシン起動前に、vfkit に渡すフラグを追加し、rosetta を利用できるようにする。
ドキュメント:
具体的には、
~/.config/containers/podman/machine/applehv/podman-machine-default.json
(仮想マシンの設定ファイル)の .Vfkit.VirtualMachine.devices
に以下を追加する。
{
"kind": "rosetta",
"MountTag": "rosetta",
"InstallRosetta": true
}
マシン起動
podman machine start
マシン内の設定
仮想マシンが起動したら podman machine ssh
でログインする
rosetta のマウント
/etc/systemd/system/var-mnt.mount
に以下を作成し、マシン起動時に rosetta をマウントするようにする。
[Unit]
Description=Mount Rosetta
Before=systemd-binfmt.service
[Mount]
What=rosetta
Where=/var/mnt
Type=virtiofs
Options=context=system_u:object_r:container_runtime_exec_t:s0
[Install]
WantedBy=multi-user.target
systemd unit 追加直後は手動でマウント
sudo systemctl daemon-reload
sudo systemctl enable --now var-mnt.mount
rosetta を binfmt (エミュレーションに使う)に登録。
sudo sh -c "echo ':rosetta:M::\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x3e\x00:\xff\xff\xff\xff\xff\xfe\xfe\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/mnt/rosetta:F' > /etc/binfmt.d/rosetta.conf"
# qemu による x86_64 エミュレーションは無効化しておく
sudo ln -s /dev/null /etc/binfmt.d/qemu-x86_64-static.conf
# binfmt 再起動
sudo systemctl restart systemd-binfmt.service
以下はおまけ
ルートレスコンテナでポート番号 80 まで公開可能にする
sudo sh -c "echo 'net.ipv4.ip_unprivileged_port_start=80' > /etc/sysctl.d/00-port-80.conf"
sudo sysctl --system
rootless コンテナで pasta ネットワークを使う
~/.config/containers/containers.conf.d/pasta.conf
に以下を設定
[network]
default_rootless_network_cmd = "pasta"
ちなみに applehv な環境では v4.9.2 時点で bind mount 時に :Z
や :z
のフラグがないとエラーになった。
# 例
podman run -v ./hoge:foo:z
ただ、2024/2/7 時点の main HEAD のコミット 6b592bd4e46b では :Z
や :z
のフラグなしでも動作した。(以下修正によるものと思われる)
v5.0.0 がリリースされ、rosetta も標準で有効になれば macOS 上の podman の使いやすさが格段に上がりそう。布教を本格化したい(?)
v5.0.0 がリリースされ、rosetta も標準で有効になれば macOS 上の podman の使いやすさが格段に上がりそう。
ついに v5.1.0 で rosetta がデフォルト有効に 🎉