SEワンタンの独学備忘録

IT関連の独学した内容や資格試験に対する取り組みの備忘録

【Docker】DockerコンテナでNginx+NginxUnit(Flask)アプリを構築する ~初めてのコンテナ間連携~

構築イメージと前提

構築イメージ

f:id:wantanBlog:20200419172231p:plain


初心者でよくわからなくても大丈夫、私もやりながら作成したものなので。

前提

受け側のNginxUnit(APサーバ)は以下のものと同様レベルのコンテナが構築されているものとします。

www.wantanblog.com


NginxのDockerコンテナを構築する

イメージを取得する

DockerHubの公式ページから取得するバージョンを選びます。

公式サイト:Docker Hub


f:id:wantanBlog:20200416223745p:plain

今回は「1.7」を選択しました。
今更気づきましたが、取得するイメージ決まったら右側のボタンからpullコマンドがコピーできますね。

・イメージの取得

docker pull nginx:1.17
Dockerネットワークの作成

コンテナ間の通信をする方法はいくつか存在するようですが、今回はDockerネットワークを作成しその中に両コンテナを含めることで、コンテナ間通信を実現したいと思います。

・ネットワークの作成

docker network create nginx-network

・ネットワーク一覧の表示

ネットワークが作成されたことを確認しておきます。

docker network ls

NETWORK ID NAME DRIVER SCOPE
d2da30109c5e bridge bridge local
7ff815c019dc host host local
4d3d14e1992e nginx-network bridge local
d69ee7c6df87 none null local

nginx-network」が今回作成したネットワークです。


Nginxコンテナの生成とネットワーク追加

今回の構築ではコンテナの起動時にも少しポイントがあります。

今回はNignxとNginxUnitとの連携を行いますので、受け側となるNginxUnitのコンテナが先に起動していることを前提となります。
先に起動しているコンテナの名前を「devunit」としていますので適宜置き換えてください。

docker run -d -p 8080:8080  --name devnginx --network nginx-network nginx:1.17 

・-d
ひとまずはバックグラウンドで起動

・-p 8080:8080
ポート番号を設定。当環境では80だと他とぶつかるので8080に設定してます。任意です。

・--network
NginxコンテナをNginxネットワークを指定して起動します。

・生成済みのコンテナをネットワークに追加する
既に生成済みのコンテナをネットワークに追加するには以下のようなコマンドを実行します。
以下の例ではすでに作成済みのAPサーバである「devunit」を追加します。

docker network connect nginx-network devunit


・ネットワークの詳細確認

コンテナが指定のネットワークに追加されているか確認しておきます。

docker network inspect nginx-network


出力結果の抜粋

"Containers": {
"8da08ca61a31ea0108f68e37dd0388b613d6c911f8d4914b49df71091f644e70": {
"Name": "devunit",
"EndpointID": "8245a53a22500c3f89d456307fb4bd972b51f787a88fd56d9f7f2688baeef585",
"MacAddress": "02:42:ac:12:00:03",
"IPv4Address": "172.18.0.3/16",
"IPv6Address": ""
},
"d3c7bd6b00052367c2483f36e978f4c3ed71627149e4fee2f8a60ebfdc4b2b72": {
"Name": "devnginx",
"EndpointID": "b9c93f672cb8971164187e2e5033b481c68a1ad7fbed8395de3b466ddb5cb5b1",
"MacAddress": "02:42:ac:12:00:02",
"IPv4Address": "172.18.0.2/16",
"IPv6Address": ""
}
},


これでNginxコンテナとNginxUnitコンテナがネットワーク内に生成できていることがわかります。
また、それぞれに割り振られているIPアドレスもここで確認できます。

コンテナ間の疎通確認

今回はコンテナ間の接続は初めてということもあるので、コンテナ間で疎通確認を行います。
疎通確認と言えば、初心者でも知っているのはpingですが、コンテナ内にインストールがされていなかったのでインストールから実行します。

・コンテナへの接続

docker container exec -it devnginx /bin/bash

・aptの最新化

apt update
apt upgrade

・pingインストール

apt-get install iputils-ping net-tools

・疎通確認(ping)の実行

ping 172.18.0.3

出力結果が以下のようになっていれば疎通確認の成功です。
これで二つのコンテナが接続できる状態になっていることが確認できました。

PING 172.18.0.3 (172.18.0.3) 56(84) bytes of data.
64 bytes from 172.18.0.3: icmp_seq=1 ttl=255 time=0.099 ms
64 bytes from 172.18.0.3: icmp_seq=2 ttl=255 time=0.090 ms
64 bytes from 172.18.0.3: icmp_seq=3 ttl=255 time=0.068 ms

Nginxコンテナの基本設定

まずはブラウザやホストOSから疎通でできるかを確認します。

一点注意ですが、コンテナの起動時にポートをデフォルトの80から変更している場合、おそらく起動してすぐはブラウザなどから変更後のポートで指定してアクセスしても疎通ができないと思います。

コンテナのポート自体は8080(私の場合)が開いていますが、コンテナ内部のNginxはデフォルトのままだとポート80で起動しているせいです。
なので、設定ファイルの修正を行います。

なおファイルの編集はコンテナ内にエディタをインストールするか、ファイルを一度ホストにコピーして編集し、再度戻す作業が必要になると思われます。

・設定ファイルのパス

/etc/nginx/conf.d/default.conf

上記ファイルのlistenの部分を以下のように修正しました。

    listen       8080;

設定したらNginxの設定の再読み込みを行っておきます。

nginx -s reload


ブラウザから以下のような画面が表示できれば成功しています。

f:id:wantanBlog:20200417011439p:plain

NginxコンテナとNginxUnitコンテナの連携設定

いろいろと整ってきたので、本題ともいえるコンテナ間の(Nginx自体の)連携設定を行います。

さきほどと同様の「default.conf」に以下のような内容を追記します。
server {}の中であればどこでもいいと思いますし、パスがぶつかっていなければデフォルトのlocationは削除しなくても大丈夫です。

location /sample/ {
        proxy_pass   http://devunit:8082/;
    }

補足としてlocationの横に書いているのがURLの後方につけるパスで、proxy_passに記載しているのがNginxUnitでListenしているURLになります。

なお、ホストにはIPアドレスの直指定かコンテナ名(エイリアスを指定している場合はそちら)を記述します。
Dockerネットワークにコンテナを追加したときにDNS解決はしてくれるようです。

さきほどと同様にNginx設定の再読み込みを行います。

ブラウザからURLを指定して開きます。
私と同じ設定にしている場合には「:8080/」のままだとNginxのデフォルト画面が表示され、「:8080/sample/」を指定すると以下のような表示がされるはずです。

f:id:wantanBlog:20200417013255p:plain

おめでとう私!!!!
これで構築イメージに準ずるものが構築できたことが確認できました。

Dockerfileでの構築

上記と同じものをDockerfileでも構築してみます。
なお、私と同じように上記の作業に続けて実施する場合にはトラブルを避けるために一度構築Dockerコンテナをネットワークから外し停止させ、削除しておいた方がいいかもしれません。

但し必要があったら設定ファイルをコンテナから抜いておく必要があります。

構成情報

・ディレクトリ構成とファイル配置

/home/ec2-user/docker_work/nginx-unit
  ┣default.conf
  ┗nginxDfile


・設定ファイルの取得
コンテナ内の設定ファイルをあらかじめホスト側にコピーしておきます。

docker container cp devnginx:/etc/nginx/conf.d/default.conf /home/ec2-user/docker_work/nginx-unit/default.conf

・default.conf(抜粋)

server {
    listen       8080;
    server_name  localhost;

    #charset koi8-r;
    #access_log  /var/log/nginx/host.access.log  main;

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }

    location /sample/ {
        proxy_pass   http://devunit:8082/;
    }
<---------中略--------->
}

私の場合の変更点としてはlistenのポートを「8080」に修正している点とNginxUnitにフォワードするための情報を追加しています。

コンテナの破棄

ポート番号の競合や原因の究明が難しくなるのを防ぐために上記で構築したコンテナをあらかじめ停止して、ネットワークから外しておきます。

もちろん、事前の作業を行っていない場合には不要な作業です。

・コンテナの停止

docker container stop devnginx


・Dockerネットワークからコンテナを外す

docker network disconnect nginx-network devnginx

この後コンテナ自体を消すかは任意です。私はDockerfileでの構築が完了するまでは念のため残しておくことにしました。

Dockerfileの記述

今回のDockerfileの記述はかなりシンプルになっています。

・nginxDfile

# ベースイメージnginx取得
FROM nginx:1.17

# 設定ファイルのコピー
COPY default.conf /etc/nginx/conf.d/

ベースイメージの取得と設定ファイルのコピーだけです。

ビルドと起動

前提として、前述のDockerネットワークが構築されていることと、APサーバとなるNginxUnitコンテナが正常にネットワーク内に構築されていることです。

・イメージのビルド

docker build -t nginxim:1.0 -f nginxDfile /home/ec2-user/docker_work/nginx-unit


・Dockerコンテナの起動
ビルドイメージからコンテナを生成し起動します。
その際にネットワークへの追加を忘れないこと。

docker run -d -p 8080:8080 --name devnginx2 --network nginx-network nginxim:1.0 
疎通確認

ブラウザから画面表示の確認を行います。
最初の構築と同様でURLが「:8080/sample/」になっているところだけ注意です。

f:id:wantanBlog:20200419024240p:plain


コマンド操作で事前に動作確認してるからのおかげもあるけどDockerfileで記述するとやることがシンプルになりますね。


ーーーーーーーー

・ソース類
docker/sample/nginx-unit at master · wantanblog/docker · GitHub

※本記事は本書の内容に沿っているわけではありません。