【 docker入門 】 docker コンテナ の ネットワーク 概要と設定方法をご紹介

2022年2月19日コンテナ

docker入門 コンテナのネットワーク設定方法

docker入門 第三弾です。

過去に投稿した2つのコンテナ関連の記事では、コンテナ単体を作るところまでをゴールにしていました。

しかし、実際は複数のコンテナ間で通信をさせてサービスや機能を提供したりシステムを構築します。

今回は、コンテナ同士をどのように通信させるのか基礎的な設定から説明していきます。

docker のネットワークの種類

現状、自分のdockerでどのようなネットワークが管理されているかはdocker network ls コマンドで確認することができます。

$ docker network ls
NETWORK ID     NAME              DRIVER    SCOPE
c23cba88ae63   bridge            bridge    local
56a710f51861   docker_gwbridge   bridge    local
0bbee5e422cd   host              host      local
d900789f82bd   none              null      local

上から、

  • bridgeネットワーク
  • hostネットワーク
  • noneネットワーク

と呼ばれるネットワークになっております。

dockerではこれに加えてユーザー定義ネットワークというものが存在し、大きく分けると4種類のネットワークが存在します。

そもそもネットワークがわからんという方

今回はネットワークに関する話になるので、コンテナの知識だけでは少々きついです。

過去に、ネットワークの超基礎的なところを記事にしているので合わせてご確認ください。

hostネットワーク

このネットワークに接続されているコンテナは、dockerデーモンが動作しているホスト(以下dockerホスト)と同じIPが割り当てられます。

例えば、192.168.1.1/24のIPアドレスが割り当てられたPCにdockerをインストールして使っている場合は、PCと同じアドレス、すなわち192.168.1.1というIPがhostネットワークに接続しているコンテナにも割り当てられます。

図にするとこんな感じです。

docker入門 ネットワーク通信のテスト

bridgeネットワーク

特にネットワークを指定しなかったコンテナはデフォルトでこのネットワークに接続されます。

このネットワークに接続されているコンテナには、dockerによって自動採番されたIPアドレスが割り当てられコンテナ同士はL2の通信で他のコンテナと通信します。

bridgeとついていることからもL2の通信であることがイメージしやすいかと思います。

例えば、192.168.1.1/24のIPアドレスが割り当てられたPCにdockerをインストールして使っている場合は、PCの内部に仮想的なネットワーク172.16.1.1/24が作成されており、bridgeネットワークに接続されたコンテナには172.16.1.XのIPが自動で付与されるというような感じです。

このネットワークでは、コンテナ同士の名前解決ができません。

コンテナ作成時に$ docker run --name web1 などとしていても他のコンテナから$ ping web1と実行しても通信できません。

$ docker network ls の結果でbridgeネットワークが2つ出力されていますが、docker_gwbridgeは複数のdockerホスト間でネットワークを構築するオーバーレイネットワークのためのネットワークです。
今回は、詳しく書きませんが言葉は覚えておいた方が良いかと思います。

先程の図にbridgeネットワークを追加するとこうです。

ユーザー定義ネットワーク

冒頭にある$ docker network ls の結果には乗っていませんが、ユーザー定義ネットワークというものも存在します。

このネットワークはほとんどbridgeネットワークと同じなのですが、名前解決ができるという特徴があります。

noneネットワーク

このネットワークに接続されているコンテナはループバックアドレス(127.0.0.1)のためのインターフェースしか持たず、他のコンテナと通信できないスタンドアロンなネットワークです。

noneネットワークに接続しているコンテナは他のネットワークに接続できないという制約があります。

これら4つのネットワークはそれぞれ以下の図のようになります。

ざっくりとそれぞれのネットワークについてご紹介しましたので、次は実際に設定してみましょう。

bridgeネットワークに作成したコンテナ同士で通信させる

まずは、デフォルトで接続されるbridgeネットワークにコンテナを作成して通信させてみます。

こんなイメージです。※IPなどは出鱈目です。

まずは、docker runコマンドでnginxのコンテナを作成します。

$ docker run --name web1 -d -p 8080:80 nginx                                                                                                                                                                                     171ms  日  2/13 21:55:10 2022
8fb090e27e7d35c32bf4a0aedcff522eae775275fda4c4994948ca3d398ff7ee
docker ps -a                                                                                                                                                                                                                  2340ms  日  2/13 21:55:19 2022
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS         PORTS                                   NAMES
8fb090e27e7d   nginx     "/docker-entrypoint.…"   12 seconds ago   Up 9 seconds   0.0.0.0:8080->80/tcp, :::8080->80/tcp   web1

この状態で、dockerのネットワークを確認するdocker network inspectコマンドを実行しbridgeネットワークに所属しているコンテナを確認してみます。

$ docker network inspect bridge
・・・省略・・・
"Containers": {
            "8fb090e27e7d35c32bf4a0aedcff522eae775275fda4c4994948ca3d398ff7ee": {
                "Name": "web1",
                "EndpointID": "1635540f0f10aad340484e6c9c4d4d8f5a79fc68a07a8f5f2c597b0e290c7369",
                "MacAddress": "02:42:ac:11:00:02",
                "IPv4Address": "172.17.0.2/16",
                "IPv6Address": ""
            }
        },
・・・省略・・・

ネットワークの情報も一緒に出てくるのでちょっと長いですが、Containersのところで先程作成したweb1というコンテナとそのネットワーク情報が確認できます。

dockerホストがmacの場合、172.17.0.2にpingを打っても通信できません。
bridgeなので通信できても良さそうなのですが、ifconfigなどで自身のインターフェースを確認するとbridgeネットワークのインターフェースがありません。
Docker ドキュメント日本語化プロジェクトの記述によると、macからは見えないようになっているようです。
dockerホストからbridgeネットワークのコンテナに通信する場合はLinuxの仮想マシンを使うかdocker-machineコマンドで仮想ホストを作成してその上で実行してみましょう。

次に、作成したweb1に対して通信を行うコンテナを作成します。

web1はwebサーバとして稼働しているので、curlを実行するコンテナを作成します。

Dockerfileは以下の通り。

FROM alpine:3.7
RUN apk update
RUN apk add curl
CMD curl http://172.17.0.2

ベースイメージのalpine:3.7は軽量のLinuxです。

curlをインストールして使えるようにしているだけのイメージになります。

早速ビルドして実行します。

$ docker build -t my-curl  .                                                                                                                                                                                                     40.9s  日  2/13 22:13:26 2022
[+] Building 10.0s (8/8) FINISHED
 => [internal] load build definition from Dockerfile                                                                                                                                                                                                                     0.0s
 => => transferring dockerfile: 117B                                                                                                                                                                                                                                     0.0s
 => [internal] load .dockerignore                                                                                                                                                                                                                                        0.0s
 => => transferring context: 2B                                                                                                                                                                                                                                          0.0s
 => [internal] load metadata for docker.io/library/alpine:3.7                                                                                                                                                                                                            4.0s
 => [auth] library/alpine:pull token for registry-1.docker.io                                                                                                                                                                                                            0.0s
 => [1/3] FROM docker.io/library/alpine:3.7@sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10                                                                                                                                                      2.5s
 => => resolve docker.io/library/alpine:3.7@sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10                                                                                                                                                      0.0s
 => => sha256:6d1ef012b5674ad8a127ecfa9b5e6f5178d171b90ee462846974177fd9bdd39f 1.51kB / 1.51kB                                                                                                                                                                           0.0s
 => => sha256:5d20c808ce198565ff70b3ed23a991dd49afac45dece63474b27ce6ed036adc6 2.11MB / 2.11MB                                                                                                                                                                           2.0s
 => => sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 1.41kB / 1.41kB                                                                                                                                                                           0.0s
 => => sha256:92251458088c638061cda8fd8b403b76d661a4dc6b7ee71b6affcf1872557b2b 528B / 528B                                                                                                                                                                               0.0s
 => => extracting sha256:5d20c808ce198565ff70b3ed23a991dd49afac45dece63474b27ce6ed036adc6                                                                                                                                                                                0.3s
 => [2/3] RUN apk update                                                                                                                                                                                                                                                 2.1s
 => [3/3] RUN apk add curl                                                                                                                                                                                                                                               1.1s
 => exporting to image                                                                                                                                                                                                                                                   0.2s
 => => exporting layers                                                                                                                                                                                                                                                  0.1s
 => => writing image sha256:412011fdb2f5b62be1a3235fa51aaf3e2c1d0010fedad212f194440361e793e1                                                                                                                                                                             0.0s
 => => naming to docker.io/library/my-curl                                                                                                                                                                                                                               0.0s

Use 'docker scan' to run Snyk tests against images to find vulnerabilities and learn how to fix them
$ docker run --name my-curl my-curl                                                                                                                                                                                                20s  日  2/13 22:14:40 2022
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   615  100   615    0     0   100k      0 --:--:-- --:--:-- --:--:--  300k
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

はい!OK!

ご覧の通り、172.17.0.2に対してcurlを実行し、htmlのレスポンスを取得することができていますね。

内容も、nginxのデフォルトページなので問題なさそうです。

試しに、名前解決をしてみる

名前解決はできないとお伝えしていますが、実際どうなのかやってみます。

Dockerfileを以下のように書き換えてビルドし直します。

  FROM alpine:3.7
  RUN apk update
  RUN apk add curl
  CMD curl http://web1

実行結果は以下の通り。

$ docker run --name my-curl my-curl                                                                                                                                                                                              221ms  日  2/13 22:23:43 2022
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0curl: (6) Could not resolve host: web1

まあ、予想通り「Could not resolve host: web1」ですね。。

ユーザー定義ネットワークを作成して、コンテナのネットワークを切り替える

ユーザー定義とあるように、このネットワークはdocker network createコマンドを実行して新規ネットワークを作成。自分で作成する必要があります。

$ dockera network create my-network
2bced8ebef523ac0471e730e33279a54bd5d97241a61869ef8de188d062bc08f
$ docker network ls
NETWORK ID     NAME              DRIVER    SCOPE
c23cba88ae63   bridge            bridge    local
56a710f51861   docker_gwbridge   bridge    local
0bbee5e422cd   host              host      local
2bced8ebef52   my-network        bridge    local
d900789f82bd   none              null      local

したから2番目に作成した「my-network」が確認できました。これでネットワーク作成は完了です。

次に、先程作成したweb1の接続されているネットワークを切り替えます。

$ docker network disconnect web1 
# 特に何も出力されません。

$ docker network inspect bridge
・・・省略・・・
 "Containers": {}, 
・・・省略・・・

bridgeネットワークの詳細からweb1のコンテナがなくなっていることが確認できます。

つぎに、先程作成した「my-network」に接続します。

$ docker network connect my-network  web1
#特に何も出力されません。

$ docker network inspect my-network 
・・・省略・・・
"Containers": {
            "8fb090e27e7d35c32bf4a0aedcff522eae775275fda4c4994948ca3d398ff7ee": {
                "Name": "web1",
                "EndpointID": "890a78a864bf914ab0ad1050de9b0ca3c44e70048d84ef5403ec822eaced8017",
                "MacAddress": "02:42:ac:13:00:02",
                "IPv4Address": "172.19.0.2/16",
                "IPv6Address": ""
            }
・・・省略・・・

これでweb1を作成したユーザー定義ネットワークに接続することができました。

再び、curlを実行するコンテナを起動してみます。

ただし、今回は起動時に接続するネットワークを指定して起動します。

$ docker run --name my-curl --net my-network my-curl
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
100   615  100   615    0     0  13977      0 --:--:-- --:--:-- --:--:-- 13977

はい!OK!

今度は、http://web1に対しても名前解決して通信することができました!

参考

コンテナ

Posted by kotaro