Docker networkを理解する

Dockerによるシステム開発などの現場においては、Dockerの論理ネットワークに関する理解がとても重要です。
この記事では、コンテナ間の通信を実現するDocker networkに関する基本的な内容と使い方について解説しています。
なお、Dockerの基本的な使い方は、こちらで解説しています。
目次
Docker networkを理解する
Dockerをインストールすると、自動的に3つの種類のDocker networkが作成されます。Dockerのネットワークの一覧を確認する場合は、docker network lsコマンドを使います。
$ docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
b00afd4fd1a0   bridge    bridge    local
6be4541b5f79   host      host      local
894265cd5830   none      null      localそれぞれのネットワークの役割は、以下のとおりです。

| Docker network | 概要 | 
|---|---|
| none | Dockerコンテナにネットワークインターフェースを持たせないため、コンテナは外部やコンテナ間の通信ができない。 | 
| host | Dockerコンテナがホストサーバのネットワークインターフェースを共有する。 ホストサーバと同じIPアドレスを使用して外部ネットワークとの通信が可能となる。 | 
| bridge | ネットワークインターフェースを指定せずにDockerコンテナを起動した場合に、デフォルトで設定されるネットワークインターフェースであり、docker0というLinux Bridgeを介して同一ホスト上のコンテナ間における通信が可能となる。 サブネット172.17.0.0/16がデフォルトとして割り当てられている。 | 
それぞれのDocker networkをコンテナに設定する手順について、以下に解説していきます。
コンテナにnoneを設定する
コンテナにネットワークインターフェースを持たせず、スタンドアローン状態でコンテナを起動する場合は、docker runコマンドの「–net」オプションに「none」を指定します。
Alpine Linuxのコンテナイメージをpullして、コンテナ起動します。
$ docker pull alpine:latest
latest: Pulling from library/alpine
8921db27df28: Pull complete
Digest: sha256:f271e74b17ced29b915d351685fd4644785c6d1559dd1f2d4189a5e851ef753a
Status: Downloaded newer image for alpine:latest
docker.io/library/alpine:latest
$ docker run -it --rm -d --net none --name net-test01 alpine:latest
4b950da176c66c25b3b12f5684b2d50408d49cf50858660f969396911e753b2f
$ docker ps
CONTAINER ID   IMAGE           COMMAND     CREATED          STATUS          PORTS     NAMES
4b950da176c6   alpine:latest   "/bin/sh"   22 seconds ago   Up 20 seconds             net-test01コンテナが起動されましたので、コンテナに入ってネットワークインターフェースの設定を確認します。
$ docker exec -it net-test01 /bin/sh
$ ifconfig
lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)ループバックアドレスしかありません。コンテナのOSはスタンドアロン状態で起動していることが確認できました。
コンテナにbridgeを設定する
次にbridgeネットワークに接続してコンテナ起動する場合は、docker runコマンドの「–net」オプションに「bridge」を指定します。
Dockerでは、コンテナ起動時のデフォルトが「bridge」であるため、「–net」オプションを省略することもできます。
$ docker run -it --rm -d --net bridge --name net-test02 alpine:latest
85517e47fa797d1df87cc4f3bca207d1ed08ce4e1bd1a96b7d0386104c6013a5
$ docker ps
CONTAINER ID   IMAGE           COMMAND     CREATED          STATUS          PORTS     NAMES
85517e47fa79   alpine:latest   "/bin/sh"   35 seconds ago   Up 34 seconds             net-test02
4b950da176c6   alpine:latest   "/bin/sh"   13 minutes ago   Up 13 minutes             net-test01「bridge」を指定したコンテナに入ってネットワークインターフェースの設定を確認します。
$ docker exec -it net-test02 /bin/sh
$ ifconfig
eth0      Link encap:Ethernet  HWaddr 02:42:AC:11:00:02
          inet addr:172.17.0.2  Bcast:172.17.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:8 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:656 (656.0 B)  TX bytes:0 (0.0 B)
lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)eth0のネットワークインターフェースとループバックアドレスが設定されていることが確認できます。eth0のIPアドレスには、172.17.0.2が自動的に割り当てられています。
docker runコマンドの「–ip」オプションを使うことで、任意のIPアドレスをコンテナに割り当てることも可能です。
コンテナにhostを設定する
Nginxのイメージコンテナをpullして、コンテナを起動します。
$ docker pull nginx:latest
latest: Pulling from library/nginx
8740c948ffd4: Pull complete
d2c0556a17c5: Pull complete
c8b9881f2c6a: Pull complete
693c3ffa8f43: Pull complete
8316c5e80e6d: Pull complete
b2fe3577faa4: Pull complete
Digest: sha256:b8f2383a95879e1ae064940d9a200f67a6c79e710ed82ac42263397367e7cc4e
Status: Downloaded newer image for nginx:latest
docker.io/library/nginx:latest
$ docker images
REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
nginx        latest    a99a39d070bf   2 weeks ago   142MB
alpine       latest    042a816809aa   2 weeks ago   7.05MB
$ docker run -d --net host --name test-nginx nginx:latest
68ac99138c4a96457aaceec78e06d04f4a4f2d3e0bed35261dd65a3015e15c1f
$ docker run -d --rm --net host -p 80:80 --name test-nginx nginx:latest
WARNING: Published ports are discarded when using host network mode
0deeb856ba7121395e957678948c6a07a8c91d9190ec6bd7d976fc9f08d68843
$ docker ps
CONTAINER ID   IMAGE           COMMAND                  CREATED          STATUS          PORTS     NAMES
0deeb856ba71   nginx:latest    "/docker-entrypoint.…"   5 seconds ago    Up 4 seconds              test-nginx
85517e47fa79   alpine:latest   "/bin/sh"                45 minutes ago   Up 45 minutes             net-test02
4b950da176c6   alpine:latest   "/bin/sh"                57 minutes ago   Up 57 minutes             net-test01ブラウザからURL「http://<ホストのIPアドレス>:80」を叩くと、コンテナで起動されたNginxの初期画面が表示されます。

論理ネットワークを作成する
次に、Docker networkに新しい論理ネットワークを作成する方法を解説します。
bridgeネットワークを作成する
新しい「bridge」ネットワークを作成します。新しいネットワーク作成前のDocker networkの状態を確認します。
$ docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
4dff45e4edd1   bridge    bridge    local
6be4541b5f79   host      host      local
894265cd5830   none      null      local
$ docker network inspect bridge
[
    {
        "Name": "bridge",
        "Id": "4dff45e4edd1568b405aa73aa5d7ee2916f816aa308f5f79d22e774b50cbf805",
        "Created": "2023-02-05T15:28:33.075749794+09:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.17.0.0/16",
                    "Gateway": "172.17.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {
            "com.docker.network.bridge.default_bridge": "true",
            "com.docker.network.bridge.enable_icc": "true",
            "com.docker.network.bridge.enable_ip_masquerade": "true",
            "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
            "com.docker.network.bridge.name": "docker0",
            "com.docker.network.driver.mtu": "1500"
        },
        "Labels": {}
    }
]デフォルトのbridgeは、サブネット172.17.0.0/16、デフォルトゲートウェイは172.17.0.1になっていることが確認できます。
次に、サブネット172.17.10.0/24、デフォルトゲートウェイ172.17.10.254の新しいネットワークを作成してみます。Docker networkの作成は、docker network createコマンドを使います。
「-d」オプションには、作成するネットワークドライバを指定します。サブネットは、「–sunet」オプションにCIDR表記で指定します。デフォルトゲートウェイは、「–gateway」オプションに指定します。
$ docker network create -d bridge --subnet=192.168.10.0/24 --gateway=192.168.10.254 test_bridge
dd2a27d4d42bd13107bfd1a1f4f103f2da0cd7e260f7df45ef386d16cea5b062
$ docker network ls
NETWORK ID     NAME         DRIVER    SCOPE
4dff45e4edd1   bridge       bridge    local
6be4541b5f79   host         host      local
894265cd5830   none         null      local
dd2a27d4d42b   test_bridge  bridge    local新しく作成した論理ネットワーク「test_bridge」が作成されました。ネットワークの詳細を確認してみます。
$ docker network inspect test_bridge
[
    {
        "Name": "test_bridge",
        "Id": "dd2a27d4d42bd13107bfd1a1f4f103f2da0cd7e260f7df45ef386d16cea5b062",
        "Created": "2023-02-05T15:49:17.294660469+09:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "192.168.10.0/24",
                    "Gateway": "192.168.10.254"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {},
        "Labels": {}
    }
]指定したサブネットとデフォルトゲートウェイが設定されていることが確認できました。
なお、「bridge」ネットワークと似た「overlay」ネットワークもDocker networkには存在します。「bridge」ネットワークは、同一ホスト内で起動されているコンテナ間の通信が可能な論理ネットワークです。一方、「overlay」は、複数のホスト上で起動されているコンテナ間の通信を同一サブネットで可能とするための論理+物理ネットワークです。
マルチホストでコンテナを起動させてシステム構築する場合に「overlay」ネットワークが必要になります。この場合、物理ネットワークとポートを意識しながら設計する必要があるため、難易度はやや高くなります。
論理ネットワークを削除する
最後に、上記で作成した論理ネットワークを削除してみます。論理ネットワークの削除は、docker network rmコマンドを使います。
はじめに、Docker networkの一覧を確認します。
$ docker network ls
NETWORK ID     NAME         DRIVER    SCOPE
4dff45e4edd1   bridge       bridge    local
6be4541b5f79   host         host      local
894265cd5830   none         null      local
dd2a27d4d42b   test_bridge  bridge    local「test_bridge」を削除してみます。
$ docker network rm test_bridge
test_bridg
$ docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
4dff45e4edd1   bridge    bridge    local
6be4541b5f79   host      host      local
894265cd5830   none      null      local「test_bridge」が削除されたことが確認できました。
まとめ
いかがでしたでしょうか。今回はデフォルトで設定されているDocker networkの使い方とコンテナへの接続方法、論理ネットワークの作成方法などについて解説しました。
この解説で登場したDocker networkコマンドは、以下の表のとおりです。
| docker networkコマンド | 概要 | 
|---|---|
| docker network ls | Docker networkの一覧を表示する | 
| docker network inspect | Docker networkのサブネットやデフォルトゲートウェイなどの詳細情報を表示する | 
| docker network create | ネットワークを作成する | 
| docker network rm | ネットワークを削除する | 
Docker networkは、複数のコンテナ間で通信を行う場合に必要な機能になりますので、しっかり理解しておきましょう。
参考になれば幸いです。
システムのお悩みについてご相談ください
SOHOのシステム運用管理に関するお悩みごとについて、なんでもお気兼ねなくご相談ください。
現役システムエンジニアのスタッフが、ボランティアでご相談にご対応させていただきます。


