Docker を使ったサービスでは、サービスを構成する各サーバプログラムをそれぞれ別のコンテナで立ち上げるのが一般的なようだ。例えばデータベース(MySQLなど)を利用する web アプリケーションであれば、つぎの3つのコンテナを立ち上げることになる:
- データベースサーバ
- web アプリケーションサーバ
- HTTP サーバ
当然、これらを連携するにはコンテナ間をまたいだ通信をする必要がある。Docker にはコンテナ間通信を実現するネットワーク機能が備わっていて、各コンテナは同じ(Docker の)ネットワークに接続していれば、コンテナ名とポート番号を使って通信することができる。
今日はそのコンテナ間通信を試してみる。
題材と構成
先日作った書籍管理 web アプリと、HTTP サーバとして Nginx を前に立てる構成とする。上にはデータベースサーバが書いてあるけど、この書籍管理アプリはデータベースに Sqlite を使っているので、今回データベースサーバはなし。アプリケーションサーバと HTTP サーバ(Nginx)の2つだ。
コンテナ名は、アプリケーションサーバを bruschetta-back、HTTP サーバを nginx-c とする。この2つが Docker ネットワークで通信するわけだ。nginx-c は80番ポートをホスト側の8080ポートに接続する。ホスト側からは bruschetta-d というホスト名で nginx-c にアクセスできるようにしておく。
アプリケーションサーバ
先日作ったものなので詳細は省略。ただ、あいだに PC のリプレイスをはさんだので、イメージ名が bruschetta:1 に変わっている。内容は変更なし。
HTTPサーバ
全面に立てる HTTP サーバには、Docker Hub で公開されている Nginx こイメージをメースにして、アプリケーションサーバにつなぐための設定ファイルをコピーしたものを用意する。
Dockerfile はこう:
ROM nginx:1.17.10 COPY ./files/bruschetta-d /etc/nginx/conf.d/bruschetta-d.conf RUN mkdir /var/log/nginx/bruschetta CMD [ "nginx", "-g", "daemon off;" ]
この中でコピーしている Nginx の仮想ホストの設定ファイルはこうだ:
upstream uwsgi-bruschetta { server bruschetta-back:5000; } server { # port listen 80; # server name server_name bruschetta-d; # log files access_log /var/log/nginx/bruschetta/access.log combined; error_log /var/log/nginx/bruschetta/error.log warn; keepalive_timeout 60; proxy_connect_timeout 60; proxy_read_timeout 60; proxy_send_timeout 60; location / { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_pass http://uwsgi-bruschetta; } }
これで docker build
した。
できたイメージの状況。
akatoh@apostrophe:docker$ docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE nginx-c 1 6f5be529ea6d About a minute ago 127MB bruschetta 1 11afb91367ae 2 hours ago 451MB nginx 1.17.10 9beeba249f3e 8 hours ago 127MB ubuntu 20.04 1d622ef86b13 3 weeks ago 73.9MB
Docker ネットワークの作成
Docker ネットワークの作成は docker network create
コマンドを利用する。
takatoh@apostrophe:docker$ docker network create nginx-network
これで nginx-network という名前の Docker ネットワークができた。つぎのようにすると様子が見える。
takatoh@apostrophe:docker$ docker network ls NETWORK ID NAME DRIVER SCOPE d0c23099f6be bridge bridge local 492e64e5d79d host host local 7f38bac647a0 nginx-network bridge local b42cbd843632 none null local
nginx-network 当名前が見える。ほかにもあるけど、これらはデフォルトで用意されているものらしい。詳細は調べてない。
コンテナの起動
2つのコンテナを起動する。その際、--netowork
オプションで接続する Docker ネットワークの名前(今回は nginx-network)を指定する。また、HTTP サーバのコンテナの方でアプリケーションサーバの名前を bruschetta-back と指定しているので、これを間違えないようにする。
まずはアプリケーションサーバのコンテナから。
takatoh@apostrophe:docker$ docker run --name bruschetta-back --network nginx-network -d bruschetta:1
HTTP サーバ。ポートの指定も忘れずに。
akatoh@apostrophe:docker$ docker run --name nginx-front --network nginx-network -p 8080:80 -d nginx-c:1
ホスト側から確認
起動したコンテナは bruschetta-d というホスト名で待ち受けているので、/etc/hosts ファイルに 127.0.0.1 を指すように記述を追加する。それができたら準備は完了だ。http://bruschetta-d:8080/ にブラウザでアクセスしてみる。
結果、期待通りにアプリケーションにアクセス、使用できることが確認できた。