Podman v3.3.0からpodman machine内のコンテナに自動的にポートフォワードが行われる機能が追加された。 この機能についてはv3.3.0のリリースノートの一番初めに記載されている。
v3.3.0のリリースノートより抜粋
Containers inside VMs created by podman machine will now automatically handle port forwarding - containers in podman machine VMs that publish ports via --publish or --publish-all will have these ports not just forwarded on the VM, but also on the host system.
(翻訳)podman machine で作成された VM 内のコンテナは、ポートフォワーディングを自動的に処理するようになりました。--publish または --publish-all でポートを公開した podman machine VM 内のコンテナは、これらのポートが VM 上だけでなく、ホストシステム上にも転送されます。
podman machineとgvproxyによる自動ポートフォワードの使い方について解説。
gvproxyについて
自動ポートフォワードの機能の追加によりpodman machineを使うためにはgvproxyが必要になった。 このことはv3.3.0リリースノートのChangesに記載がある
The new port forwarding offered by podman machine requires gvproxy in order to function.
gvproxyはGitHubリポジトリ上ではgvisor-tap-vsockという名前になっている。libslirp と VPNKitを置き換えるものでGoで書かれており、gVisorのネットワークスタックをベースにしている。
gvproxy自体の使い方や詳細はGitHubリポジトリを参照。
rootモード on Linuxで実行する場合
rootモード on Linuxの実行環境
$ cat /proc/version Linux version 5.13.12-200.fc34.x86_64 (mockbuild@bkernel01.iad2.fedoraproject.org) (gcc (GCC) 11.2.1 20210728 (Red Hat 11.2.1-1), GNU ld version 2.35.2-4.fc34) #1 SMP Wed Aug 18 13:27:18 UTC 2021 $ podman -r version Client: Version: 3.3.1 API Version: 3.3.1 Go Version: go1.16.6 Built: Tue Aug 31 05:46:36 2021 OS/Arch: linux/amd64 Server: Version: 3.3.0 API Version: 3.3.0 Go Version: go1.16.6 Built: Sat Aug 21 04:36:14 2021 OS/Arch: linux/amd64
[実行手順]
# podman machine init; podman machine start # podman -r pull docker.io/library/nginx # podman -r run --rm -d --name nginx -p 8888:80 nginx # podman -r ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES b75a5a32c09a docker.io/library/nginx:latest nginx -g daemon o... 30 seconds ago Up 30 seconds ago 0.0.0.0:8888->80/tcp nginx # ss -ltnup | grep 8888 tcp LISTEN 0 4096 *:8888 *:* users:(("gvproxy",pid=8857,fd=31)) # curl http://localhost:8888 <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> ... </html>
gvproxyを使って自動的にポートフォワーディングが行われ、ホスト上からpodman machine VM上のコンテナへ接続ができる
ルートレスモード on LinuxまたはmacOSで実行する場合
ルートレスモード on LinuxまたはmacOSで実行する場合は注意が必要。rootモードと同じ手順では自動的にポートフォワーディングが行われない。 この問題についてはGitHubにIssueを上げている。
Issueを上げてすぐにコメントが付いて、その内容のワークアラウンドを適用することでルートレスモードおよびmacOSで自動ポートフォワードが実行が可能となった。
ワークアラウンド
コンテナ実行時に--network bridge
を付与する
ルートレスモード on Linuxの場合
実行環境はrootモード on Linuxと同じ
[実行手順]
$ podman machine init; podman machine start $ podman -r pull docker.io/library/nginx $ podman -r run --rm -d --name nginx -p 8888:80 --network bridge nginx $ ss -ltnup |grep 8888 tcp LISTEN 0 4096 *:8888 *:* users:(("gvproxy",pid=9725,fd=17)) $ curl http://localhost:8888 <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> ... </html>
macOSの場合
実行環境
- MacBook Pro (13-inch, 2017, Two Thunderbolt 3 ports)
- macOS Big Sur Version 11.5.2
$ podman version Client: Version: 3.3.1 API Version: 3.3.1 Go Version: go1.17 Built: Tue Aug 31 04:15:26 2021 OS/Arch: darwin/amd64 Server: Version: 3.3.0 API Version: 3.3.0 Go Version: go1.16.6 Built: Sat Aug 21 04:36:14 2021 OS/Arch: linux/amd64
[実行手順]
$ podman machine init; podman machine start $ podman pull docker.io/library/nginx $ podman run --rm -d --name nginx -p 8888:80 --network bridge nginx $ ss -ltnup |grep 8888 tcp LISTEN 0 4096 *:8888 *:* users:(("gvproxy",pid=9725,fd=17)) $curl http://localhost:8888 <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> ... </html>
別のワークアラウンド
GitHubのIssueでは議論が進んでおり、別のワークアラウンドとしてcontainers.conf
に設定を書き込む方法が紹介されている。
Just confirming that adding rootless_networking = "cni" under the [containers] section of ~/.config/containers/containers.conf does also fix this on MacOS :)
containers.conf
の[containers]
セクションにrootless_networking = "cni"
を追記する。
$ vi ~/.config/containers/containers.conf [containers] rootless_networking = "cni"
この設定を行うことでコンテナ実行時に--network bridge
を付与しなくても自動的にポートフォワードが行われるようになる。
ルートレスモード on Linuxの場合
$ podman -r run --rm -d --name nginx -p 8888:80 nginx $ ss -ltnup |grep 8888 tcp LISTEN 0 4096 *:8888 *:* users:(("gvproxy",pid=9725,fd=14)) $ curl http://localhost:8888 <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> ... </html>
macOSの場合
$ podman run --rm -d --name nginx -p 8888:80 nginx $ netstat -an|grep 8888 tcp46 0 0 *.8888 *.* LISTEN $ curl http://localhost:8888 <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> ... </html>