私はDockerの初心者です。docker runコマンドでこのオプションが何をするのか、明確な説明が見つからず、少し混乱しています。
このオプションを使って、ポートを指定せずにDockerコンテナ上で動作しているアプリケーションにアクセスできるのでしょうか?例えば、docker runコマンドで-p 8080:8080
オプションを使用して、ポート8080でdockerイメージ経由でデプロイされたウェブアプリケーションを実行する場合、Dockerコンテナのip /theWebAppNameで8080ポートにアクセスしなければならないことは分かっています。しかし、--net=host
オプションがどのように機能するのか、うまく思いつきません。
Dockerのインストール後、デフォルトでは3つのネットワークがあります:
docker network ls
NETWORK ID NAME DRIVER SCOPE
f3be8b1ef7ce bridge bridge local
fbff927877c1 host host local
023bb5940080 none null local
私はこれをシンプルに保とうとしています。そのため、デフォルトでコンテナを起動すると、ブリッジ (docker0) ネットワーク内に作成されます。
$ docker run -d jenkins
1498e581cdba jenkins "/bin/tini -- /usr..." 3 minutes ago Up 3 minutes 8080/tcp, 50000/tcp friendly_bell
jenkinsのdockerfileでは、ポート8080
と50000
が公開されている。これらのポートは、ブリッジネットワーク上のコンテナ用に開放されている。そのため、ブリッジネットワーク内のすべてのものがポート 8080
と 50000
のコンテナにアクセスできる。ブリッジネットワーク内のすべてのものは、"Subnet": "172.17.0.0/16",
のプライベート範囲内にある。もし外部からアクセスしたい場合は、ポートを -p 8080:8080
でマッピングする必要がある。これにより、コンテナのポートが実際のサーバー(ホスト・ネットワーク)のポートにマッピングされる。つまり、8080
のサーバーにアクセスすると、ポート 8080
のブリッジネットワークにルーティングされる。
これでホストネットワークもできた。コンテナのネットワークはコンテナ化されない。そのため、ホストネットワークでコンテナを起動すると、次のようになる(最初のもの):
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1efd834949b2 jenkins "/bin/tini -- /usr..." 6 minutes ago Up 6 minutes eloquent_panini
1498e581cdba jenkins "/bin/tini -- /usr..." 10 minutes ago Up 10 minutes 8080/tcp, 50000/tcp friendly_bell
違いはポートだ。コンテナはホストネットワーク内にある。そのため、ホスト上でポート 8080
を開けば、すぐにコンテナにアクセスできる。
$ sudo iptables -I INPUT 5 -p tcp -m tcp --dport 8080 -j ACCEPT
ファイアウォールでポート 8080
を開き、ポート 8080
でサーバーにアクセスすると、jenkins にアクセスできる。このブログ]1も参考になると思います。
net=host`オプションは、ネットワークの観点から、Dockerコンテナ内のプログラムをホスト自体で実行しているように見せるために使用する。 これにより、コンテナは通常よりも大きなネットワークアクセスができるようになる。
通常、ホストマシンからコンテナにポートを転送する必要があるが、コンテナがホストのネットワークを共有する場合、ネットワーク上のアクティビティはすべてホストマシン上で直接発生する。
これは、ポートを公開してコンテナ・ポートにマッピングする必要がなくなることを意味するが、同じホスト・ポートで2つのコンテナを動作させることはできないため、競合を避けるために、各コンテナがリッスンするポートを調整するためにDockerfileを編集する必要があることを意味する。 しかし、このオプションを使う本当の理由は、ポートレベルでコンテナに転送するのが難しいネットワークアクセスが必要なアプリを実行するためだ。
例えば、DHCPサーバーを実行したい場合、ネットワーク上のブロードキャスト・トラフィックをリッスンし、パケットからMACアドレスを抽出できる必要がある。 この情報はポート転送の過程で失われるため、Docker内でDHCPサーバーを実行するには、コンテナを--net=host
として実行するしかない。
一般的に言えば、--net=host
が必要なのは、非常に特殊で異常なネットワークを必要とするプログラムを実行する場合だけである。
最後に、セキュリティの観点から、Dockerコンテナは単一のポートしかアドバタイズ(公開)しないにもかかわらず、多くのポートをリッスンすることができます。 しかし、--host=net
を使うと、Dockerfileにリストされていないポートも含めて、コンテナがホスト上でリッスンしている全てのポートを取得することになります。 つまり、コンテナ(特にソフトウェアプロジェクトが提供する公式のものなど、あなたのものではない場合)を注意深くチェックし、不注意で余計なサービスをマシンに公開しないようにする必要があります。