【Dockerの最新機能を使ってみよう】マルチホストネットワークで複数ホスト間を繋ぐ仮想ネットワークを作る 2ページ

「docker network」コマンドによるネットワーク管理

 前述のとおり、Docker 1.9以降ではネットワーク関連が刷新され、新たに「docker network」コマンドを利用して仮想ネットワークの作成や管理を行うようになった。以下では、この「docker network」コマンドによるネットワーク管理について紹介していこう。

 なお、記事執筆時点では最新のDocker 1.10を安定版パッケージとして提供しているLinuxディストリビューションは少なかったため、検証環境としてはFedora 24向けの開発版パッケージとして提供されているDocker 1.10.3(docker-1.10.3-4.gitf8a9a2a.fc24.x86_64)をFedora 23にインストールして利用している。

単一ホスト向けのネットワーク作成

 ネットワークの作成は、「docker network create <ネットワーク名>」コマンドで行える。たとえば「testnet01」というネットワークを作成する場合、以下のようになる。

# docker network create testnet01
bd48adb5b4a787cb499640fabff3b2a4bd5c13077b954926443298bf5ad297bc

 使用するドライバは「-d」オプションで指定できるが、この例のように省略するとブリッジ接続を利用する「bridge」ドライバが使用される。

 作成済みのネットワークは、「docker network ls」コマンドで確認できる。

# docker network ls
NETWORK ID          NAME                DRIVER
ad6ade0d2b2e        none                null
7eee9e7be7e3        host                host
e492e130b418        bridge              bridge
bd48adb5b4a7        testnet01           bridge

 ちなみに、作成したネットワークを削除するには「docker network rm」コマンドを使用する。

# docker network rm testnet01

 コンテナの作成時に「–net=<ネットワーク名>」オプションを指定することで、作成したコンテナを指定したネットワークに接続できる。次の例はMySQLコンテナを作成し、testnet01ネットワークに接続するものだ。

# docker run --name mysql01 --net=testnet01 -e MYSQL_ROOT_PASSWORD=<MySQLのrootパスワード> -d mysql

 ネットワークのIPアドレスや接続されているコンテナなどの情報は、「docker network inspect」コマンドで確認できる。

# docker network inspect testnet01
[
    {
        "Name": "testnet01",
        "Id": "bd48adb5b4a787cb499640fabff3b2a4bd5c13077b954926443298bf5ad297bc",
        "Scope": "local",
        "Driver": "bridge",
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.18.0.0/16",
                    "Gateway": "172.18.0.1/16"
                }
            ]
        },
        "Containers": {
            "6bae0a01a426bb41acc95decba22e62d8d61d15ce6509f315566c67341c9677b": {
                "Name": "mysql01",
                "EndpointID": "78401ea23166d967bff762d2cce92362e7743af9c332b176d58082fc3b5d42b7",
                "MacAddress": "02:42:ac:12:00:02",
                "IPv4Address": "172.18.0.2/16",
                "IPv6Address": ""
            }
        },
        "Options": {}
    }
]

 この例では、testnet01ネットワークには172.18.0.0/16というIPアドレスが割り当てられ、ゲートウェイは172.18.0.1、mysq01コンテナには172.18.0.2というIPアドレスが割り当てられていることが分かる。

 DockerホストからはこのIPアドレスを使ってコンテナへアクセスを行える。たとえば、以下のようにしてmysql01コンテナで稼動しているMySQLサーバーにアクセスできる。

# mysql -u root -h 172.18.0.2 -p
Enter password:
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.11 MySQL Community Server (GPL)

Copyright (c) 2000, 2015, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MySQL [(none)]>

 ホストからコンテナへの通信の場合、先のように「docker network inspect」コマンドなどを利用して割り当てられたIPアドレスを取得できるが、コンテナ内からはどのコンテナにどのIPアドレスが割り当てられているかは分からない。そのため、同じネットワーク内に接続されているコンテナ同士の通信は、コンテナ名、もしくは「<コンテナ名>.<ネットワーク名>」というホスト名を使って行えるようになっている。たとえば先に作成しているmysql01コンテナは、同じネットワークにあるほかのコンテナからは「mysql01」もしくは「mysql01.testnet01」というホスト名でアクセスが可能だ。

 以下の例は、これを利用して先に作成したmysql01コンテナ上で稼動しているデータベースに接続するWordPressコンテナを作成するものだ。ここでは「-e」オプションで環境変数として使用するデータベースの情報を指定している。

 

$ docker run --name wp01 --net=testnet01 -p 80:80 -e WORDPRESS_DB_HOST=mysql01.testnet01 -e WORDPRESS_DB_USER=wordpress -e WORDPRESS_DB_PASSWORD=<MySQLのrootパスワード> -d wordpress

 このホスト名解決は、Docker 1.9では/etc/hostsファイル経由で行われていたが、Docker 1.10以降ではDockerが内部的にDNSサーバーを立ち上げるようになっており、そのDNSサーバー経由で名前解決が行われるようになっている。そのため、/etc/hostsファイルにはそれらの情報が記述されないので注意したい。

複数のDockerホストにまたがるネットワーク(マルチホストネットワーク)を利用するための設定

 続いて、今度は複数のDockerホストにまたがるネットワーク(マルチホストネットワーク)を作成してみよう。前述のとおりDockerでは複数のネットワークドライバが利用できるが、今回はDockerに標準で付属するoverlayドライバを使用して環境を構築する。

 overlayドライバでは、各種設定を各Dockerホストで共有するためにKey-valueストアを使用する。Key-valueストアへのアクセスには「libkv」というライブラリを使用するようになっており、現時点ではConsulおよびEtcdApache ZooKeeperがサポートされている。このうち、今回はインストールや設定が容易なEtcdを利用して設定共有を行うこととする。

 EtcdはCoreOSが開発している分散型Key-valueストアで、すでに多くのディストリビューションでパッケージが提供されている。たとえばDebianやUbuntuでは「apt-get」、Red Hat Enterprise Linux/CentOSでは「yum」、Fedoraでは「dnf」といったパッケージマネージャ経由でのインストールが可能だ。今回検証に使用したFedora 23では、以下のようにしてインストールが行える。

# dnf install etcd

 Etcdは分散型Key-valueストアであり、実際の運用環境では複数台で分散運用するのが一般的だが、今回はテストということで1台のマシンだけで稼動させ、そこに各Dockerホストがアクセスする形とした。

 なお、Fedora 23のEtcdのデフォルト設定ではlocalhostからのみアクセスを受け付ける設定になっているので、/etc/etcd/etcd.confファイルを修正して外部から接続できるよう設定を変更しておく必要がある。具体的には、下記の「localhost」をそのホストのIPアドレスに変更している。

(修正前)
ETCD_LISTEN_CLIENT_URLS="http://localhost:2379"
  
  
ETCD_ADVERTISE_CLIENT_URLS="http://localhost:2379"

 変更後の設定ファイルは以下のようになる。

(修正後)
ETCD_LISTEN_CLIENT_URLS="http://<ホストのIPアドレス>:2379"
  
  
ETCD_ADVERTISE_CLIENT_URLS="http://<ホストのIPアドレス>:2379"

 また、ほかのホストからEtcdが使用するTCPの2379および2380番ポートにアクセスできるよう、ファイアウォール等の設定を行っておく。Fedora 23であれば、以下のように「firewall-cmd」コマンドで設定が可能だ。

# firewall-cmd --add-port=2379/tcp
# firewall-cmd --add-port=2380/tcp

 以上の設定が完了したら、次のようにEtcdを起動させておく。

# systemctl start etcd

 続いてDockerホスト側の設定を行っていく。この作業は、使用するDockerホストそれぞれで必要となる。まず、Dockerのネットワーク設定が記述されている/etc/sysconfig/docker-networkファイル内の「DOCKER_NETWORK_OPTIONS」部分を次のように変更する。

DOCKER_NETWORK_OPTIONS='--cluster-store=etcd://*<Etcdを稼動させているホストのIPアドレス>:2379 --cluster-advertise=<そのホストのIPアドレス>:2376'

 注意したいのが、「–cluster-store」ではEtcdを稼動させているホストのIPアドレスを、「–cluster-advertise」にはそのDockerホスト自身のIPアドレスを指定する点だ。

 また、DockerホストからEtcdに対し通信が行えるかを確認しておこう。これは、次のようにcurlコマンドでテストできる。

# curl -L http://<Etcd稼動ホストのIPアドレス>:2379/version
{"etcdserver":"2.2.5","etcdcluster":"2.2.0"}

 また、overlayドライバではUDPの4789番ポートとTCPおよびUDPの7946番ポートを使用する。これに加え、Docker同士の通信に使用するTCPの2376番ポートにほかのDockerホストからアクセスできるよう、ファイアウォールの設定を行っておく。

# firewall-cmd --add-port=4789/udp
# firewall-cmd --add-port=7946/udp
# firewall-cmd --add-port=7946/tcp
# firewall-cmd --add-port=2376/tcp

 以上で設定は完了だ。最後にDockerサービスを再起動させておく。

# systemctl restart docker