砂漠の旅人(たびと)

UNIX / MS-DOS 時代から電脳砂漠を旅しています

【docker】Web サーバと DB サーバを作って相互に通信できるようにする

こんにちは、たびとです。

docker を始めるとサーバを2台以上作って、 例えば Web サーバに置いたアプリから DB を参照したいと思ったことはありませんか?

以前、Web/AP/DB の3層構造のサーバを構築して苦労しましたが、 今回は Web と DB の 2 サーバを作って、相互に参照できるようにコンテナを作成します。

この記事の対象者

  • docker 環境で複数のサーバを作って、相互に参照したい。
  • DB サーバを作って、テーブルも作成したい。

事前準備

docker 環境をまだ作っていなければ、以前の記事を参考にしてください。

sabakunotabito.hatenablog.com

docker 構築

最終的なファイル構成を先に紹介します。 Visual Studio Code (VS Code) を使うと Windows 上からファイルの編集が可能です。

ファイル構成

ホームディレクトリ配下に webdb ディレクトリを作成し、今回の資材一式を作っていきます。

$ mkdir webdb
$ mkdir web
$ mkdir -p rdb/initdb
$ cd webdb

docker-compose.yml

docker-compose.yml を作成します。

$ touch docker-compose.yml
$ code .

docker-compose.yml をVS Code で編集し、Web サーバと DB サーバを定義します。

version: '3.8'
services: 
  rdb:
    container_name: 'postgres'
    build: ./rdb
    ports:
      - "5433:5432"
    environment:
      POSTGRES_DB: postgres
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: Password01#
      DATABASE_HOST: localhost
    volumes:
      - rdb_data:/var/lib/postgresql/data:rw
      - ./rdb/initdb:/docker-entrypoint-initdb.d
    tty: true
    restart: always
    networks:
      - mynetwork
  
  web:
    container_name: 'nginx'
    build: ./web
    ports:
      - "8080:80"
    environment:
      - LANG=ja_JP.utf8
      - TZ=Asia/Tokyo
    tty: true
    restart: always
    networks:
      - mynetwork

volumes:
  rdb_data:

networks:
  mynetwork:
    driver: bridge
    ipam:
      driver: default

ネットワークを作成することで、docker コンテナ内で名前により、参照することができるようになります。 IP アドレスを指定することも可能ですが、今回は簡単な方法で定義します。

Web サーバ

Web サーバ用の Dockerfile を作成します。

$ cd web
$ touch Dockerfile

Dockerfile に docker-hub のイメージ・環境変数・Nginx起動を記述します。

FROM nginx:alpine
ENV LANG ja_JP.utf8
ENV TZ Asia/Tokyo

ENTRYPOINT /usr/sbin/nginx -g "daemon off;" -c /etc/nginx/nginx.conf

DB サーバ

DB サーバ用の Dockerfile とテーブル作成用のシェル(init.sh)を作成します。

$ cd rdb
$ touch Dockerfile
$ cd initdb
$ touch init.sh

Dockerfile に docker-hub のイメージ・環境変数を定義します。

FROM postgres:alpine
ENV LANG ja_JP.utf8
ENV TZ Asia/Tokyo

init.sh に初期テーブルとして、sample を作成するように記述します。

set -e
psql -U postgres postgres << ENDSQL
--
CREATE TABLE sample (
  id text primary key,
  name text
);
COMMENT ON COLUMN sample.id is 'ID';
COMMENT ON COLUMN sample.name is '名前';
--
ENDSQL

docker 実行

前述の各ファイルをビルド & 実行し、正常に動作していることを確認します。

ビルド & 実行

docker-compose.yml をビルドします。

$ cd webdb
$ docker-compose build
[+] Building 28.1s (9/9) FINISHED
 => [webdb_web internal] load build definition from Dockerfile                                                     0.1s
 => => transferring dockerfile: 163B                                                                               0.0s
 => [webdb_web internal] load .dockerignore                                                                        0.1s
 => => transferring context: 2B                                                                                    0.0s
 => [webdb_rdb internal] load build definition from Dockerfile                                                     0.1s
 => => transferring dockerfile: 96B                                                                                0.0s
 => [webdb_rdb internal] load .dockerignore                                                                        0.1s
 => => transferring context: 2B                                                                                    0.0s
 => [webdb_web internal] load metadata for docker.io/library/nginx:alpine                                          6.1s
 => [webdb_rdb internal] load metadata for docker.io/library/postgres:alpine                                       5.0s
 => [webdb_rdb 1/1] FROM docker.io/library/postgres:alpine@sha256:6a01df718f0944524e72873b1d7c9a63a3976e776b1fe3  22.9s
 => => resolve docker.io/library/postgres:alpine@sha256:6a01df718f0944524e72873b1d7c9a63a3976e776b1fe3faabc0a7924  0.0s
 => => sha256:6a01df718f0944524e72873b1d7c9a63a3976e776b1fe3faabc0a7924b49aeae 1.65kB / 1.65kB                     0.0s
 => => sha256:7d6403121b12c9d29c13c9873bc0f76da8ff51f6c89fae10b99dc890807e27ae 1.99kB / 1.99kB                     0.0s
 => => sha256:41cd24e8c51bfe2a56fbe1577c41f5160692de3092d7ba0f2e0a622c57724fc3 7.87kB / 7.87kB                     0.0s
 => => sha256:915bf02ec4105a810e064257cd9ce9cbf90be2ec069bf0f87d12f98038d07c56 1.29kB / 1.29kB                     0.3s
 => => sha256:b026a0cf3c97e00c74281e123e212ce0517eee48fbd9a1086027c4684f6f5517 149B / 149B                         0.5s
 => => sha256:530afca65e2ea04227630ae746e0c85b2bd1a179379cbf2b6501b49c4cab2ccc 2.80MB / 2.80MB                     0.9s
 => => sha256:88659e2107f6c19018c4e187da12c1d25804ea415012db2800349a24303c3f58 81.87MB / 81.87MB                  17.1s
 => => sha256:33960a1e9871a67fd4cdc90215bb1e3002ec7fac9e5ffa3d9729f1632f659f91 9.20kB / 9.20kB                     1.0s
 => => extracting sha256:530afca65e2ea04227630ae746e0c85b2bd1a179379cbf2b6501b49c4cab2ccc                          0.4s
 => => sha256:b9bbc907277f07d68b85d7eab8d131447831f84eaac4d1bf2421ff2e6139ea7c 162B / 162B                         1.2s
 => => sha256:7e545c6230ec7e1d72b3d7fdfae81ebfa9d1ee7ab1fb165b956202376cafe277 195B / 195B                         1.2s
 => => sha256:ba5428d6e942832c77d8b941f2a66f721abc27bb010a93d9a60a933df9e51dc4 4.70kB / 4.70kB                     1.4s
 => => extracting sha256:915bf02ec4105a810e064257cd9ce9cbf90be2ec069bf0f87d12f98038d07c56                          0.0s
 => => extracting sha256:b026a0cf3c97e00c74281e123e212ce0517eee48fbd9a1086027c4684f6f5517                          0.0s
 => => extracting sha256:88659e2107f6c19018c4e187da12c1d25804ea415012db2800349a24303c3f58                          4.9s
 => => extracting sha256:33960a1e9871a67fd4cdc90215bb1e3002ec7fac9e5ffa3d9729f1632f659f91                          0.0s
 => => extracting sha256:b9bbc907277f07d68b85d7eab8d131447831f84eaac4d1bf2421ff2e6139ea7c                          0.0s
 => => extracting sha256:7e545c6230ec7e1d72b3d7fdfae81ebfa9d1ee7ab1fb165b956202376cafe277                          0.0s
 => => extracting sha256:ba5428d6e942832c77d8b941f2a66f721abc27bb010a93d9a60a933df9e51dc4                          0.0s
 => [webdb_web 1/1] FROM docker.io/library/nginx:alpine@sha256:4a846cc240449c53c8ae24269ba6bcaee5167d8ad75cd2a8d8  2.7s
 => => resolve docker.io/library/nginx:alpine@sha256:4a846cc240449c53c8ae24269ba6bcaee5167d8ad75cd2a8d8ba422b7c72  0.0s
 => => extracting sha256:530afca65e2ea04227630ae746e0c85b2bd1a179379cbf2b6501b49c4cab2ccc                          0.3s
 => => sha256:4a846cc240449c53c8ae24269ba6bcaee5167d8ad75cd2a8d8ba422b7c726979 1.65kB / 1.65kB                     0.0s
 => => sha256:1d00e644bcaf116218f25250ec8a85022d3035a8b8dca2745199f86bb3cf85d1 1.57kB / 1.57kB                     0.0s
 => => sha256:87a9dea80b01f6b82538e15828ecf9b21a52953ca6ef073913921bc1a7129b11 8.89kB / 8.89kB                     0.0s
 => => sha256:530afca65e2ea04227630ae746e0c85b2bd1a179379cbf2b6501b49c4cab2ccc 2.80MB / 2.80MB                     0.0s
 => => sha256:6a89def8063152acad33aa7eba1cd2d9c5388fa6fee6d3a6e7c8bed1ee0546aa 7.38MB / 7.38MB                     1.1s
 => => sha256:29e4e820b7210a8dd7e779fa527ce217e4ed0514d31d30e6b35f601f65a16a2d 604B / 604B                         0.8s
 => => sha256:0b3cca595de12677cd14cc43d1fcf9832bf1263e771b66ba782b06248ad15589 894B / 894B                         1.0s
 => => sha256:2b101aaad7024d10982d455bf1138b39fd1c0fb5f1460fa2350a16b231076afd 665B / 665B                         1.3s
 => => extracting sha256:6a89def8063152acad33aa7eba1cd2d9c5388fa6fee6d3a6e7c8bed1ee0546aa                          0.8s
 => => sha256:f3c5ffbedfb2b04855073e67368f62057671052390d94d74174dece1e8c5144d 1.39kB / 1.39kB                     1.5s
 => => extracting sha256:29e4e820b7210a8dd7e779fa527ce217e4ed0514d31d30e6b35f601f65a16a2d                          0.0s
 => => extracting sha256:0b3cca595de12677cd14cc43d1fcf9832bf1263e771b66ba782b06248ad15589                          0.0s
 => => extracting sha256:2b101aaad7024d10982d455bf1138b39fd1c0fb5f1460fa2350a16b231076afd                          0.0s
 => => extracting sha256:f3c5ffbedfb2b04855073e67368f62057671052390d94d74174dece1e8c5144d                          0.0s
 => [webdb_rdb] exporting to image                                                                                 0.1s
 => => exporting layers                                                                                            0.0s
 => => writing image sha256:ddc0faa2275d8bd07d9882e7c02425c8462e49f075f00f7ac33eb04e94a74c82                       0.0s
 => => naming to docker.io/library/webdb_web                                                                       0.0s
 => => writing image sha256:0c2bea41d3f6a0bc0614c77943f44728dcb38b4051fa5ba843ecb43bcd519efc                       0.0s
 => => naming to docker.io/library/webdb_rdb                                                                       0.0s

Use 'docker scan' to run Snyk tests against images to find vulnerabilities and learn how to fix them

ビルドしたコンテナを実行します。

$ docker-compose up -d
[+] Running 4/4
 ⠿ Network webdb_mynetwork  Created                                                                                0.0s
 ⠿ Volume "webdb_rdb_data"  Created                                                                                0.0s
 ⠿ Container nginx          Started                                                                                1.7s
 ⠿ Container postgres       Started                                                                                1.7s

Web サーバ確認

Web サーバの Nginx が正常に動作していることを確認します。 ブラウザを開いて、http://localhost:8080 を入力します。

Nginx の確認

DB サーバ確認

DB サーバの PostgreSQL が正常に動作していることを確認します。

DBの接続テスト

設定が正しければ、以下のダイアログが表示されます。

DBへの接続成功

次に init.sh で作成したテーブル(sample)が正しく作成されていることを確認します。

init.sh で作成したテーブルの確認

サーバ名で疎通確認

Web サーバから DB サーバに ping を実行してみます。 DB サーバの名前は docker-compose.yml で指定した rdb になります。

$ docker-compose exec web /bin/sh
/ # ping rdb
PING rdb (172.19.0.3): 56 data bytes
64 bytes from 172.19.0.3: seq=0 ttl=64 time=1.050 ms
64 bytes from 172.19.0.3: seq=1 ttl=64 time=0.262 ms
64 bytes from 172.19.0.3: seq=2 ttl=64 time=0.091 ms
64 bytes from 172.19.0.3: seq=3 ttl=64 time=0.132 ms
64 bytes from 172.19.0.3: seq=4 ttl=64 time=0.061 ms
^C
--- rdb ping statistics ---
5 packets transmitted, 5 packets received, 0% packet loss
round-trip min/avg/max = 0.061/0.319/1.050 ms

今度は DB サーバから Web サーバに ping を実行してみます。 Web サーバの名前は docker-compose.yml で指定した web になります。

$ docker-compose exec rdb /bin/sh
/ # ping web
PING web (172.19.0.2): 56 data bytes
64 bytes from 172.19.0.2: seq=0 ttl=64 time=0.661 ms
64 bytes from 172.19.0.2: seq=1 ttl=64 time=0.103 ms
64 bytes from 172.19.0.2: seq=2 ttl=64 time=0.128 ms
64 bytes from 172.19.0.2: seq=3 ttl=64 time=0.169 ms
64 bytes from 172.19.0.2: seq=4 ttl=64 time=0.190 ms
^C
--- web ping statistics ---
5 packets transmitted, 5 packets received, 0% packet loss
round-trip min/avg/max = 0.103/0.250/0.661 ms

まとめ

今回は、docker で Web サーバと DB サーバを構築する方法を紹介しました。 ネットワークの設定をすることで、サーバ間を名前でアクセスできるようになります。 DB サーバの場合、コンテナのビルド時にテーブルを作成することが可能です。

前回の .NET アプリをビルドする記事と組み合わせると、 バッチサーバも追加することができるため、やれることの可能性が広がると思います。

sabakunotabito.hatenablog.com

では、皆さん、よい旅を。