Windows11のWSL2へPodman(podman-machine-default)を導入したものの、podman pullでno such hostのエラーが出てしまう

当サイトではアフィリエイト広告を利用しています

Windows11のWSL2において、Podman(Distroはpodman-default-machine)を導入したのですが、podman pullを行った際にno such hostのエラーが出てしまいました。

原因としては複数ネットワークを繋ぎ変える際のネームサーバーの設定問題でした。

導入手順と解決手順を合わせて記録しておきます。

環境

  • OS: Windows11
  • Distro on WSL2: podman-machine-default
  • Podman: 4.5.1

PodmanのWSL2へのインストール手順

WSL2を有効にした後、Winget経由でPodmanのインストールを行います。

基本的には公式の手順に従うのですが、それだけだと不足する内容があったので私の行った手順をまとめておきます。

WSL2の有効化

設定→アプリ→オプション機能→Windowsのその他の機能→「Linux用Windowsサブシステム」と「仮想マシンプラットフォームにチェック」を行い、その後再起動します。

管理者権限のPowerでwsl --installを行うとUbuntuのDistroも同時にインストールされてしまうので、Distro不要なら上記手順を使うと良いかと思います。

WingetでPodmanのインストール

Powerを管理者権限で開いてwingetを実行します。

# 要管理者権限
$ winget install -e --id RedHat.Podman

WSL2へPodman用Distroインストール

WSL2へPodman実行用のDistroであるpodman-machine-defaultをインストールしようとしましたが、カーネルコンポーネントが不足すると表示されました。

$ podman machine init

Downloading VM image: fedora-podman-amd64-v37.0.50.tar.xz: done
Extracting compressed file
Importing operating system into WSL (this may take a few minutes on a new WSL install)...
WSL 2 を実行するには、カーネル コンポーネントの更新が必要です。詳細については https://aka.ms/wsl2kernel を参照してください
Error: the WSL import of guest OS failed: exit status 0xffffffff

MicroSoft公式より、カーネル更新プログラム パッケージをダウンロードしてインストールします(要管理者権限)。

再度podman machine initを実行し、無事にインストールできました。

$ podman machine init

Extracting compressed file
Importing operating system into WSL (this may take a few minutes on a new WSL install)...
Configuring system...
Generating public/private ed25519 key pair.
Your identification has been saved in podman-machine-default
Your public key has been saved in podman-machine-default.pub
The key fingerprint is:
The key's randomart image is:
Machine init complete
To start your machine run:

        podman machine start

導入されたdistroを確認してみます。

# Distro確認
$ wsl --list
Linux 用 Windows サブシステム ディストリビューション:
podman-machine-default (既定)

この時点ですでにVMが起動していましたが、再度起動してみて起動時の情報を確認してみます。

$ podman machine stop
$ podman machine start
Starting machine "podman-machine-default"

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: npipe:////./pipe/docker_engine

Docker API clients default to this address. You do not need to set DOCKER_HOST.
Machine "podman-machine-default" started successfully

これでPodman自体の導入はできました。

Podmanの動作確認

試しにhttpサーバーを起動してみます。こちらは無事にHTTPサーバーへのアクセスが出来る事が確認できました。

# コンテナを起動
$ podman run --rm -d -p 8080:80 --name httpd docker.io/library/httpd
# localhost:8080でHTTPサーバーの動作確認できた。

# コンテナを停止
$ podman stop httpd

問題発生

Podmanをインストールしたネットワーク環境と別のネットワーク環境に接続した際に、podman pullを行うと次のようなエラーが出てしまいました。

$ podman pull busybox
Resolved "busybox" as an alias (/etc/containers/registries.conf.d/000-shortnames.conf)
Trying to pull docker.io/library/busybox:latest...
Error: copying system image from manifest list: parsing image configuration: Get "https://production.cloudflare.docker.com/registry-v2/docker/registry/v2/blobs/sha256/52/5242710cbd55829f6c44b34ff249913bb7cee748889e7e6925285a29f126aa78/data?verify=1689320530-6VflZBDzdhIUa2Zuud23yde7Ayc%3D": dial tcp: lookup production.cloudflare.docker.com: no such host

どうも名前解決が正常に行えないように見えます。色々試して見た結果、解決することが出来た手順を以下にまとめます。

resolv.confの確認

WSL2上のpodman-machine-defaultにアクセスするにはpodman machine sshとすればログインできます。

/etc/resolv.confを確認すると以下のようになっていました。

$ cat /etc/resolv.conf
# This file was automatically generated by WSL. To stop automatic generation of this file, add the following entry to /etc/wsl.conf:
# [network]
# generateResolvConf = false
nameserver xxx.xxx.xxx.xxx

このnameserverのIPアドレスがどのネットワーク環境に接続しても変わっておらず、Podman導入時のネットワーク環境でしか正常なネームサーバーとなっていないようでした。

nameserverの値が変わらないのであればGoogle Public DNSなどを記述することでどのネットワーク環境でも名前解決が行えそうです。

ただ、この値を書き換えただけではmachineの再起動時に設定が元に戻ってしまうので、これを永続化する必要があります。

WSLの設定でresolv.confの自動生成を停止する

WSL2上のDistroは/etc/wsl.confにWSLの設定が記載されています。ここでresolv.confの自動生成を無効にします。

$ cat /etc/wsl.conf
[user]
default=user

$ sudo vi /etc/wsl.conf
[user]
default=user
[network]
generateResolvConf = false

resolv.confの書き換え

次にresolv.confを書き換えます。このファイルはシンボリックリンクなので解除して改めて記述します。

なおunlinkコマンドは実態はrmであるので、リンク元を削除しないように注意です。

$ ls /etc/resolv.conf -al
lrwxrwxrwx 1 root root 39 Jul 18 09:25 /etc/resolv.conf -> ../run/systemd/resolve/stub-resolv.conf
$ sudo unlink /etc/resolv.conf

resolv.confを以下のように設定します。8.8.8.8はGoogle Public DNSで、8.8.4.4はその代替DNSとなっています。

$ sudo vi /etc/resolv.conf
nameserver 8.8.8.8
nameserver 8.8.4.4

ただ、この設定を行っただけではDistroの再起動時に今度はDistro側にresolv.confが上書きされてしまいますので、上書き不可とする設定を行います。

chattrで変更不可属性を付与してやるとよさそうでした。podman-machine-defaultはchattrが入ってないので合わせてインストールしておきます。

$ sudo dnf install e2fsprogs
$ lsattr /etc/resolv.conf
--------------e------- /etc/resolv.conf
$ sudo chattr +i /etc/resolv.conf
$ lsattr /etc/resolv.conf
----i---------e------- /etc/resolv.conf

これでpodman machineを再起動してもresolv.confが上書きされなくなりました。

chattrはext2/ext3/ext4ファイルシステムで利用できる拡張属性の変更コマンドですが、NTFSのWindowwsで動くWSL2でも模擬できているようです。

手順まとめ

  1. WSL側でresolv.confの自動生成を止める
  2. Podman-mahine-defaultで/etc/resolv.conf -> ../run/systemd/resolve/stub-resolv.confのシンボリックリンクを解除する
  3. 手動で/etc/resolv.confをGooglePublicDNS宛に記述する
  4. e2fsprogsをインストールし、resolv.confに変更不可属性を付与する
$ sudo vi /etc/wsl.conf
[user]
default=user
[network]
generateResolvConf = false


$ sudo unlink /etc/resolv.conf

$ sudo vi /etc/resolv.conf
nameserver 8.8.8.8
nameserver 8.8.4.4


$ sudo dnf install e2fsprogs
$ sudo chattr +i /etc/resolv.conf

設定変更後

上記のように名前解決の設定を変更した後、無事に異なるネットワーク環境でpodman pullで名前解決が出来ることが確認できました。

WSL2では名前解決系の問題が出ることがたまにあるようで、Podman以外でも必要になる設定かもしれませんので忘れないようにしておきたいところです。