Apple ContainerのDNS機能
「Apple ContainerでLAMP環境を作る」の記事でコンテナにコンテナ(ホスト)名でアクセスできるようにするにはDNSドメインの設定が必要と書きました。
以下のように設定します。
% sudo container system dns create box % container system property set dns.domain box
公式のチュートリアルにもさらっと説明されています。 上記コマンドをおまじないとして実行しておくだけでも問題なく使えるのですが、 なぜドメインを作成する必要があるのか?どういう仕組みで名前解決されているのかを理解しておくと応用が効きます。
今回はDNSドメインの作成とはなにか、デフォルトドメインを設定するとどうなるのか、どういった仕組みでコンテナの名前解決がされているのかを解説します。
Container CLIはv0.5.0を使用します。
DNSドメイン
まずはDNSドメインです。DNSドメインは以下のようにして作成できます。
% container system dns create <domain name>
DNSドメインを作成すると、そのドメイン内のコンテナ名(例えばfoo.<domain name>)で名前解決(ホスト名をIPアドレスに変換)できるようになります。 これによりコンテナ名で疎通できるようになります。
例えば、boxというドメインが作成済みとして、container run --name foo.box --rm -it somethingのようにfoo.boxという名前のコンテナを作成するとping foo.box のようにコンテナに疎通できるようになります。 ドメイン名を省略して、ping fooのようにunqualified name で疎通することもできます。
DNSドメインを作成すると具体的に何が起こり、名前解決できるようになるのかをこれから説明していきます。そのためにはまずmacOSのリゾルバー(*1)の動作を理解する必要があります。
macOSのリゾルバーの動作
一旦話の腰を折って、macOSでリゾルバーの仕様を説明します。 ここで説明する内容は、man 5 resolver のSEARCH STRATEGYで説明されていますのでそちらも参照するとよいでしょう。
DNSリゾルバの設定ファイルはUNIX系OSなら一般的に/etc/resolv.confになりますが、macOSではドメインごとに複数のリゾルバ設定を持つことができるようになっています。 これらのドメインごとのリゾルバ設定は /etc/resolver/* に置かれます。
Qualified name(*2)でホスト名を名前解決しようとする際、マッチするドメインのリゾルバ設定に従って名前解決をしようとします。 マッチするものがなければ通常どおり/etc/resolv.confの設定に従います。
/etc/resolver/*のファイルもresolv.confと同じ形式で記述します。 基本的にファイル名がドメイン名として扱われるので、例えばprivateドメインの設定は以下のようになります。
/etc/resolver/private
domain private search private nameserver 192.168.10.10
ホスト名xxx.privateの名前解決は本設定にしたがって行われます。このようにして、VPN等、ネットワークに応じて個別のネームサーバーを使うようにすることができます。
ちなみにファイル名がドメイン名として扱われるためdomainの指定は省略できます。 同一ドメインに複数のリゾルバ設定を行いたい場合は、ファイルを二種類作成してdomainを指定します。
/etc/resolver/private-a
domain private search private nameserver x.x.x.x
/etc/resolver/private-b
domain private search private nameserver y.y.y.y
このようにすることでprivateドメインに二つのネームサーバー(x.x.x.x, y.y.y.y)を指定できます。 名前解決したいドメインに対して複数のリゾルバ設定があった場合は、それぞれのリゾルバを使って順番に名前解決が試みられます。順序はsearch_orderで指定することができます。
図1に名前解決時にどのようにリゾルバが選択されるかの動作を示します。

この図ではprivate, vpn の2つのドメインのリゾルバ設定が存在します。
www.bit-hive.comのようにprivate, vpnにマッチしないドメインの場合は、通常どおり、resolv.confの設定に従って名前解決を行います。
foo.privateを名前解決する場合は、privateドメインの設定にマッチするので、/etc/resolver/private のリゾルバ設定に従って名前解決を行います。 このためy.y.y.yのネームサーバーに問い合わせることになります。
barのようにunqualified nameで名前解決する場合はどうなるでしょうか?
この場合は、/etc/resolver/にあるリゾルバ設定で順番に名前解決を試みる形になります。
まず、y.y.y.y にbar.privateの問い合わせをし、名前解決できなければz.z.z.z にbar.vpnの問い合わせをする形になります(*3)。
以上が、今回知っておくべきmacOSのリゾルバ動作になります。
あらためてコンテナのDNSドメイン
ここで、コンテナのDNSドメインに話を戻します。
container system dns createでDNSドメインを作成すると /etc/resolver/ 配下にcontainerization.<domain name>というファイルが作成されます(*4)。
内部は/etc/resolv.confと同じフォーマットで以下のようになっています。
domain <domain name> search <domain name> nameserver 127.0.0.1 port 2053
先のmacOSのリゾルバ動作の説明からわかると思いますが、指定ドメインのリゾルバ設定が追加されたということです。
設定ファイルのnameserverは127.0.0.1のport 2053が指定されています。 127.0.0.1 の UDP port 2053 は、Apple ContainerのAPIサーバーである container-apiserver がListenしており、このドメインに名前解決があった場合は、 container-apiserverに名前解決のクエリが送られ、 コンテナのIPアドレスが返されるようになっています。 container-apiserverはおそらくContainer CLIとやりとりするAPIサーバーだと思いますが、コンテナのDNS機能も担っているわけですね。
名前解決を行う際の流れを図2にまとめます。

この図では、box, privateの2つのコンテナ用ドメインが作成済みの状態です。
ホスト(macOS)上からping foo.boxなどしてfoo.boxの名前解決が発生したとします。この場合、boxドメインはcontainerization.boxのリゾルバにマッチするので、container-apiserver (127.0.0.1:2053)にDNSクエリを送信し、container-apiserverはfoo.boxが存在するので、そのIPアドレスを返します。
ping fooのようにしてunqualified nameで名前解決が発生した場合は、containerization.box, containerization.private両方のリゾルバを使って順番に名前解決を行おうとするので、 foo.boxとfoo.privateをcontainer-apiserverに問い合わせる形になります。この場合、foo.boxのIPアドレスが返されます。
上記はホスト(macOS)からコンテナ名で名前解決する例でしたが、コンテナ内ではどのような動作になるのでしょうか? コンテナ内のresolv.confでは以下のようにホスト(macOS)のリソルバを使うように設定されています。
コンテナ内の/etc/resolv.conf
nameserver 192.168.64.1 ← これはホスト(macOS)のIPアドレス domain <domain name>
macOSがコンテナ内からの名前解決要求を受け取り、ホスト上での名前解決と同じように処理してくれるため、コンテナ内からも同様にコンテナ名で名前解決ができるようになります(図2の右側部分)。
デフォルトドメインの設定はまだしていませんが、DNSドメインを作成することでコンテナ名を使ってコンテナとの通信ができるようになることが理解できたと思います。
まとめ
DNSドメインを作成すると、macOSにそのドメインのリゾルバ設定を追加して、container-apiserverがそのドメイン内の名前解決要求に応答できるようにします。
デフォルトドメイン
ここまでで、DNSドメインを作成してコンテナ名をそのドメインに所属させておけば、コンテナ名で疎通できるようになることは理解できたと思います。
また、コンテナ起動時にコンテナ名(--name)にドメイン名を忘れてunqualified nameで指定してしまうと、名前解決できないこともまた理解できると思います。 コンテナ名を指定するのに、一々ドメイン名を指定するのは面倒ですし、環境依存(*5)も発生してしまいます。 これを解決するのが、デフォルトドメイン設定です。
container system property set dns.domain ...で設定するデフォルトドメインとは、
container runで コンテナ名(--name)がunqualified nameで指定された時に自動的に付与されるドメイン名
です。ただ、それだけです。名前解決の動作には影響しません。
例えば、container system property set dns.domain box とデフォルトドメインをboxに設定しておけば、container run --name foo... としてもコンテナ名はfoo.boxとなり、自動的にboxドメインに所属することになります。 これにより、foo.boxでもfooでも名前解決できるようになります。
長々と説明しましたが、チュートリアルにあるように 1ドメインだけ作成してデフォルト設定しておけば、コンテナを作成したり参照(名前解決)時にドメインを意識する必要はなくなります(すべてunqualified nameでOK)。ただ、裏でこのようなことが起こっていることを理解しておくとトラブル時などに有用かもしれません。
まとめ
(1) DNSドメインを作成すると、macOSにそのドメインのリゾルバ設定を追加して、container-apiserverがそのドメイン内の名前解決要求に応答できるようにする。
(2) デフォルトドメインはcontainer run時に指定する名前の指定に影響する。名前解決処理自体には関係ない。
(3) デフォルトドメインを指定しておけば、あとはDNSドメインを意識せず運用可能。
(*1) DNSを使って名前解決を行うクライアント(ライブラリ)のこと。
(*2) foo.boxのようなドメイン名付きのホスト名のこと。
(*3) 実際にはどういった順番でリゾルバが参照されるのかは不明。search_orderで制御できるのかもしれない。
(*4) 作成されるファイル名がドメイン名ではなく、containerization.<domain name>となっているのは、既に同名ドメインのリゾルバ設定があった際に競合しないようにするためでしょう。
(*5) 他の環境でも同じDNSドメインが作成されていないと正常に動作できない。
投稿日:2025/10/10 17:45