Dockerでのネットワークの構築 -nginxコンテナとtomcatコンテナ-

## 目的
Dockerコンテナのネットワークを構築して、Webサーバーとアプリケーション・サーバーを接続する。
デフォルトのネットワークとDocker network createで作成したネットワークの違いを確かめる。

###前提
Dockerがインストールされていること
###構成
Webサーバー、APサーバーを別々のコンテナで起動させる。
WebサーバーからhttpアクセスでAPサーバーへフォワーディングする。
Webサーバー 
・nginx
APサーバー
・tomcat
ソース（ってほどのものでもないですが。。。）
https://github.com/tky-k/docker/tree/master/docker_network_sample 
#####構成図
![スクリーンショット 2019-07-20 13.53.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/388313/0c082669-61ed-9b96-6fc3-f9d9e9ad8e1b.png)

##Dockerコンテナのネットワークを構築して、Webサーバーとアプリケーション・サーバーを接続する。
###構築
と、言っても行う作業はとても少ないです。
以下5点を行います。
Dockerfileの作成
nginxのconfファイルの作成
コンテナのビルド
Docker networkの作成
コンテナの起動

#####Dockerfileの作成
ベースイメージをnginxとし、confファイルをコピーするようにします。

```Dockerfile.file
FROM nginx

COPY docker_sample.conf /etc/nginx/conf.d/
EXPOSE 80
EXPOSE 3000
ENTRYPOINT /usr/sbin/nginx -g 'daemon off;' -c /etc/nginx/nginx.conf

```

#####nginxのconfファイルの作成
APサーバーへのフォワーディングを行うため、serverコンテキストを追加します。
nginxはデフォルトで/etc/nginx/conf.d/*.conf内のファイルを読み込むようになっているため、上記のDockerfileでコピーするようにしています。
listenは監視するポート番号、server_nameはブラウザがアクセスしようとするホスト名（HTTPヘッダのHOST）です。
proxy_passはフォワード先です。

```docker_sample.conf
server {
    listen       3000;
    server_name  localhost;

    location / {
        proxy_pass http://docker-network-tomcat:8080;
    }

    location ~ /\.ht {
       deny  all;
    }
}
```

#####コンテナのビルド
作成したnginxのconfファイルを取り込むために、コンテナをビルドします。
-tでタグを設定しておいたほうがよいでしょう。

```sh
docker build --no-cache=true . -t docker_network_sample:1.0
```

#####Docker networkの作成
Docker networkはDocker標準で用意されているコマンドを利用します。
-dでネットワークのタイプを選びます。bridgeかoverlayを指定できます。（ここについては省略）
docker network create -d=#NETWORKTYPE #NETWORK_NAME

```sh
docker network create -d=bridge docker-sample-network
```

#####コンテナの起動
コンテナを起動します。
--netで作成したnetworkを指定します。
docker_network_sampleがWebサーバーになるため、ホストのポートとコンテナのポートをDockerエンジンにフォワードさせるため、-pで設定します。

```sh
docker run --name docker-network-tomcat --net=docker-sample-network -d tomcat
docker container run --name docker-network-sample --net=docker-sample-network -d -p 8080:80 -p 8081:3000 docker_network_sample:1.0
```

以上で作業は完了です。

####動作確認
以下のURLにアクセスしてみます。nginxのデフォルトのindexページが表示されます。
http://localhost:8080
![スクリーンショット 2019-07-20 14.16.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/388313/418ac0fa-d46e-3d77-b57a-bc47d8a7d19c.png)

次いではこちらにアクセスしてみます。APサーバー（tomcat）にフォワーディングされることが確認できました。
http://localhost:8081
![スクリーンショット 2019-07-20 14.18.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/388313/b331a044-7308-6761-323e-2b6b9940606a.png)

##デフォルトのネットワークとDocker network createで作成したネットワークの違いを確かめる。
Dockerはデフォルトで3種類のネットワークがあります。
bridge,host,noneの3種類です。

```sh
$docker network ls
NETWORK ID          NAME                    DRIVER              SCOPE
ef01c927c34d        bridge                  bridge              local
449369b9a406        docker-sample-network   bridge              local
a2396438eabe        host                    host                local
123e0d0fdf37        none                    null                local
```

####作成したネットワークの確認
先程作成したネットワークの情報です。

```sh
$docker network inspect docker-sample-network
〜中略〜
        "Containers": {
            "7852061ce4d0624d7048ecf3e0527e8793766bb6884ccab121e8cfbe944fcbd9": {
                "Name": "docker-network-sample",
                "EndpointID": "afb0318d89f21e033e582a43c4667da79aecdba480705938a805cf2e1f5bc277",
                "MacAddress": "02:42:ac:1a:00:03",
                "IPv4Address": "172.26.0.3/16",
                "IPv6Address": ""
            },
            "af0af80e57281abacc4624f6dd0b1d93fd8af68d8df7c1b38dcb2292bed9d1cf": {
                "Name": "docker-network-tomcat",
                "EndpointID": "25d89174f6caa569baca1a411ef9f5b8a1b17bde20654bc49cd4e43e186086c3",
                "MacAddress": "02:42:ac:1a:00:02",
                "IPv4Address": "172.26.0.2/16",
                "IPv6Address": ""
            }
        },
```

この状態で相互接続できるのか確認します。
nginxのコンテナにはpingがないため、tomcatのコンテナに接続

```sh
$docker container exec -it docker-network-tomcat /bin/bash
#ping docker-network-sample
PING docker-network-sample (172.26.0.3) 56(84) bytes of data.
64 bytes from docker-network-sample.docker-sample-network (172.26.0.3): icmp_seq=1 ttl=64 time=0.063 ms
```

接続できています。名前によってIPアドレスも解決されています。

####標準のネットワークの確認
標準のネットワークで確認するため、コンテナを立ち上げ直します。

```sh
$docker run --name docker-network-tomcat --net=bridge -d -p 8082:8080 tomcat
966b1870debfb1cdf1d6b2e216c936c5f7967475f0dbaba46b12015051203ef3
$docker container run --name docker-network-sample --net=bridge -d -p 8080:80 -p 8081:3000 docker_network_sample:1.0
efeca9569ba7ed37436abeb1e40b1640331a08e67d67368c49e64a7df064945a
$docker network inspect bridge
〜中略〜
        "Containers": {
            "966b1870debfb1cdf1d6b2e216c936c5f7967475f0dbaba46b12015051203ef3": {
                "Name": "docker-network-tomcat",
                "EndpointID": "0a5b443e816af8a5709247fc0f15e221b1fe81e7dba139b625941d5e97c16b97",
                "MacAddress": "02:42:ac:11:00:02",
                "IPv4Address": "172.17.0.2/16",
                "IPv6Address": ""
            }
        },
```

Containersにdocker-network-sampleが存在しません。
起動しているコンテナ一覧を確認します。

```sh
$docker container ls
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                    NAMES
966b1870debf        tomcat              "catalina.sh run"   3 minutes ago       Up 3 minutes        0.0.0.0:8082->8080/tcp   docker-network-tomcat
```

docker-network-sampleのコンテナは起動していないようです。
なぜ起動しないか不明なので、-dを除いて実行してみます。

```sh
$docker container run --name docker-network-sample --net=bridge -p 8080:80 -p 8081:3000 docker_network_sample:1.0
2019/07/20 05:40:41 [emerg] 7#7: host not found in upstream "docker-network-tomcat" in /etc/nginx/conf.d/docker_sample.conf:6
nginx: [emerg] host not found in upstream "docker-network-tomcat" in /etc/nginx/conf.d/docker_sample.conf:6
```

docker-network-tomcatが名前解決できないため、nginxの起動でエラーになり、コンテナも起動しなかったようです。

####理由
Dockerの標準で作成されているネットワークはコンテナを起動するときに--netをつけなかった場合、自動で参加するようになっています。

```sh
$docker container run -d nginx
$docker container ls
CONTAINER ID        IMAGE               COMMAND                  CREATED              STATUS              PORTS                    NAMES
0397130c2a99        nginx               "nginx -g 'daemon of…"   About a minute ago   Up About a minute   80/tcp                   romantic_johnson
$docker network inspect bridge
〜中略〜
     "Containers": {
            "0397130c2a997fd86593f6fb1f1248c23fa3ba1532623650f3566c891bbf606a": {
                "Name": "romantic_johnson",
                "EndpointID": "3bf43195b6eff3f906bfc434fbe5e087f06b16cf2a6a45629f43c4753f9fdc5c",
                "MacAddress": "02:42:ac:11:00:03",
                "IPv4Address": "172.17.0.3/16",
                "IPv6Address": ""
            },
〜中略〜
```

この標準のネットワークは内部DNSを使用しないため、名前解決ができません。
一方、作成したネットワークはDockerの内部DNSを使って名前解決ができるようになります。
この動作の違いがあるため、標準ネットワークを使って起動しようとしたnginxは名前解決できずにエラーになってしまったようです。

2019/08/01
Docker-composeを使ってネットワーク作成、ビルド、起動まで一括でできるようにしました。
複数のコンテナの単一サーバー上での連携も設定ファイルひとつでできるので、また1つ便利だなと感じました。

##終わり
コンテナの機能の一部しかまだ把握できていませんが、まだまだ便利だなっていう感想しかでてきません。
ここがイケてないとか言えるほど修めたいですね。