Docker Desktop for Mac のネットワーク機能

読む時間の目安: 2 分

Docker Desktop for Mac では、より簡単に利用できるネットワーク機能をいくつも提供しています。

機能

VPN パススルー

Docker Desktop for Mac のネットワークは VPN に接続して利用することができます。 このとき Docker Desktop for Mac は、コンテナーからのトラフィックを捕捉し Mac へ受け渡します。 まるで Docker アプリケーションから発信されたかのように扱います。

ポートマッピング

コンテナーの起動時に、たとえば以下のように-p引数をつけたとします。

$ docker run -p 80:80 -d nginx

Docker Desktop for Mac は、コンテナー上のポート 80 を使って稼動するものすべて(この場合はnginx)、localhost のポート 80 から利用できるようにします。 この例では、ホストとコンテナーのそれぞれのポート番号は同一にしています。 ホストのポートを別のものに指定する必要があるとしたら、どうなるでしょう。 つまり、ホストマシン上においてすでにポート 80 を利用して起動しているアプリケーションがあるなら、コンテナーのポートを別のものに接続したらよいことになります。

$ docker run -p 8000:80 -d nginx

こうするとlocalhost:8000への接続が、コンテナー内のポート 80 へ接続されます。 -p の文法はホストポート:クライアントポートです。

HTTP/HTTPS プロキシーサポート

Proxies タブ を参照してください。

SSH エージェント転送

Docker Desktop for Mac では、コンテナー内部からホストの SSH エージェントを利用することができます。 これは以下のようにして実現します。

  1. docker runコマンドのパラメーターに以下を追加することで、SSH エージェントソケットをバインドマウントします。

    --mount type=bind,src=/run/host-services/ssh-auth.sock,target=/run/host-services/ssh-auth.sock

  2. コンテナー内において環境変数SSH_AUTH_SOCKを追加します。

    -e SSH_AUTH_SOCK="/run/host-services/ssh-auth.sock"

Docker Compose において SSH エージェントを有効にするために、サービスに以下のフラグを追加します。

services:
  web:
    image: nginx:alpine
    volumes:
      - type: bind
        source: /run/host-services/ssh-auth.sock
        target: /run/host-services/ssh-auth.sock
    environment:
      - SSH_AUTH_SOCK=/run/host-services/ssh-auth.sock

既知の制約、利用状況、回避策

以下では、Docker Desktop for Mac の現状のネットワーク機能における制約と回避方法についてまとめます。

内部 IP アドレスの変更

Docker が利用する内部 IP アドレスは Settings (Windows の場合)、Preferences (Mac の場合) を通じて変更することができます。 IP を変更したときは Kubernetes クラスターのリセットが必要であり、アクティブな Swarm はそのままとしておくことが必要です。

macOS 上に docker0 ブリッジがない

Docker Desktop for Mac におけるネットワーク機能の実装方法により、ホスト上からdocker0インターフェースを見ることはできません。 このインターフェースは仮想マシン内にあります。

コンテナーに ping ができない

Docker Desktop for Mac がコンテナーに対して、トラフィックをルーティングできません。

コンテナー単位の IP アドレス割り当てができない

Docker の(Linux における)ブリッジネットワークが、macOS ホストからアクセスできません。

利用状況と回避策

上記の制約から影響を受ける利用状況が 2 つあります。

コンテナーからホスト上のサービスに接続したい

ホストには可変の IP アドレスがあります(もっともネットワークを利用しなければ何もありません)。 推奨されるのは、特別な DNS 名host.docker.internalに接続することです。 この DNS は、ホストが利用する内部 IP アドレスを名前解決します。 これは開発環境において用いられるものであり、Docker Desktop for Mac の範囲外にある本番環境では動作しません。

ゲートウェイもgateway.docker.internalを利用してアクセス可能です。

マシン上に Python をインストールしている場合は、例として以下の手順に従い、コンテナーからホスト上のサービスに接続します。

  1. 以下のコマンドを実行して、単純の HTTP サーバーをポート 8000 で起動します。

    python -m http.server 8000

    Python 2.x をインストールしている場合は、python -m SimpleHTTPServer 8000 を実行します。

  2. そしてコンテナーの実行とcurlのインストールを行って、以下のコマンドのようにホストへの接続を試してみます。

     $ docker run --rm -it alpine sh
     # apk add curl
     # curl http://host.docker.internal:8000
     # exit
    

Mac からコンテナーに接続したい

localhost に対するポート転送(port forwarding)が動作します。 つまり--publish-p-Pはすべて動きます。 Linux コンテナーから公開されたポートは、ホストに転送されます。

今のところ推奨される方法は、ポートを公開するか、あるいはもう 1 つ別のコンテナーから接続することです。 Linux 上であっても、コンテナーがブリッジネットワーク上ではなく、オーバーレイネットワーク上にある場合には、こういった方法が必要になります。 その場合にはルートが解決されないからです。

たとえばnginxウェブサーバーは以下のように実行します。

$ docker run -d -p 80:80 --name webserver nginx

文法を明確にする目的で、以下の 2 つのコマンドを実行します。 両方ともコンテナー上のポート80を、ホスト上のポート8000に向けて公開するものです。

$ docker run --publish 8000:80 --name webserver nginx

$ docker run -p 8000:80 --name webserver nginx

ポートをすべて公開するには-Pフラグを使います。 たとえば以下のコマンドは(デタッチモードで)コンテナーを起動し、-P フラグによってコンテナー上の全ポートを、ホスト上のランダムなポートとして公開します。

$ docker run -d -P --name webserver nginx

docker run コマンドにて利用できる、ポート公開に関するオプションの詳細については run コマンド を参照してください。

mac, networking