Docker Desktop for Windows のネットワーク機能
Docker Desktop では、より簡単に利用できるネットワーク機能をいくつも提供しています。
機能
VPN パススルー
Docker Desktop のネットワークは VPN に接続して利用することができます。 このとき Docker Desktop は、コンテナーからのトラフィックを捕捉し Windows へ受け渡します。 まるで Docker アプリケーションから発信されたかのように扱います。
ポートマッピング
コンテナーの起動時に、たとえば以下のように-p
引数をつけたとします。
$ docker run -p 80:80 -d nginx
Docker Desktop は、コンテナー上のポート 80 を使って稼動するものすべて(この場合はnginx
)、localhost
のポート 80 から利用できるようにします。
この例では、ホストとコンテナーのそれぞれのポート番号は同一にしています。
ホストのポートを別のものに指定する必要があるとしたら、どうなるでしょう。
つまり、ホストマシン上においてすでにポート 80 を利用して起動しているアプリケーションがあるなら、コンテナーのポートを別のものに接続したらよいことになります。
$ docker run -p 8000:80 -d nginx
こうするとlocalhost:8000
への接続が、コンテナー内のポート 80 へ接続されます。
-p
の文法はホストポート:クライアントポート
です。
HTTP/HTTPS プロキシーサポート
Proxies タブ を参照してください。
既知の制約、利用状況、回避策
以下では、Docker Desktop for Windows の現状のネットワーク機能における制約と回避方法についてまとめます。
Windows 上に docker0 ブリッジがない
Docker Desktop for Windows におけるネットワーク機能の実装方法により、ホスト上からdocker0
インターフェースを見ることはできません。
このインターフェースは仮想マシン内にあります。
コンテナーに ping ができない
Docker Desktop for Windows が Linux コンテナーに対して、トラフィックをルーティングできません。 ただし Windows コンテナーであれば ping を通すことができます。
コンテナー単位の IP アドレス割り当てができない
Docker の(Linux における)ブリッジネットワークが Windows ホストからアクセスできません。 ただし Windows コンテナーでは動作します。
利用状況と回避策
上記の制約から影響を受ける利用状況が 2 つあります。
コンテナーからホスト上のサービスに接続したい
ホストには可変の IP アドレスがあります(もっともネットワークを利用しなければ何もありません)。
推奨されるのは、特別な DNS 名host.docker.internal
に接続することです。
この DNS は、ホストが利用する内部 IP アドレスを名前解決します。
これは開発環境において用いられるものであり、Docker Desktop for Windows の範囲外にある本番環境では動作しません。
ゲートウェイもgateway.docker.internal
を利用してアクセス可能です。
マシン上に Python をインストールしている場合は、例として以下の手順に従い、コンテナーからホスト上のサービスに接続します。
-
以下のコマンドを実行して、単純な HTTP サーバーをポート 8000 で起動します。
python -m http.server 8000
Python 2.x をインストールしている場合は、
python -m SimpleHTTPServer 8000
を実行します。 -
そしてコンテナーの実行と
curl
のインストールを行って、以下のコマンドのようにホストへの接続を試してみます。$ docker run --rm -it alpine sh # apk add curl # curl http://host.docker.internal:8000 # exit
Windows からコンテナーに接続したい
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 コマンド を参照してください。