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

Docker Desktop for Mac には、使いやすくするための複数のネットワーク機能があります。

機能

VPN パススルー

Docker Desktop のネットワーク構築は、VPN 接続時も動作します。そのためには、あたかも Docker アプリケーションが発信しているかのように、Docker Desktop がコンテナからのトラフィックを取り込み、Mac へ投入します。

ポート 割り当て(mapping)

コンテナに -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 の構文は ホスト側ポート:クライアント側ポート です。

SSH エージェント転送(agent forwarding)

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
    
  1. コンテナ内に 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 アドレスは、設定( Windows の場合は Settings、 Mac の場合は Preferences)で変更できます。 IP アドレスの変更後は、 Kubernetes クラスタのリセットか、アクティブな Swarm から離脱する必要があります。

macOS に docker0 ブリッジがありません

ネットワーク構築機能の実装が、Docker Desktop for Mac 用のため、ホスト側では docker0 インターフェースは見えません。このインターフェースは、実際には仮想マシン内にあります。

コンテナに ping できません

Docker Desktop for Mac は Linux コンテナに対してトラフィックを経路付け(ルーティング)できません。

コンテナごとに IP アドレスを割り当てられません

docker (Linux) ブリッジ・ネットワークは macOS ホストから到達できません。

利用例と回避方法

前述の制限に対応する、2つのシナリオがあります。

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

ホストの IP アドレスは変動します(ネットワークへの接続がなければ、割り当てられません)。ホストからアクセスするには、内部 IP アドレスを名前解決するために、特別な DNS 名 host.docker.internal の利用を推奨します。これは開発用途であり、Docker Desktop forMac 外の本番環境では動作しません。

また、ゲートウェイに対しては gateway.docker.internal で到達可能です。

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

  1. 以下のコマンドを使い、サーバ上のポート 8080 でシンプルな HTTP サーバを起動します。

    $ python -m http.server 8000

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

  1. 次は、コンテナを実行し、 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 からのポート公開(露出)は、ホスト側に転送されます。

現時点で推奨するのは、ポートの公開か、他のコンテナからの接続です。これは Linux 上でも同様ですが、ブリッジ・ネットワークではなくオーバレイ・ネットワーク上にコンテナがある場合、到達(経路付け)できません。

たとえば、 nginx ウェブサーバを起動します。

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

構文を明確にしましょう。以下の2つのコマンドは、いずれも同じコンテナのポート 80 をホスト側のポート 8080 に公開するものです。

$ 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 で公開するオプションに関する詳細は docker run コマンドを御覧ください。

参考

Networking features in Docker Desktop for Mac
https://docs.docker.com/docker-for-mac/networking/