有機インフラの庭

有機インフラの庭

某SI企業エンジニアのIT備忘録

3つの公式Dockerイメージを使用してコンテナWEBアプリを構築する

はじめに

本記事では、ApacheTomcatPostgreSQLが組み込まれた公式のDockerイメージを使ってWEBアプリを実装する。デプロイするWEBアプリは『CentOS VM上に標準OSSでサンプルWEBアプリを実装する』で取り扱った『TERASOLUNAツアー予約システム』を採用します。CentOS上に作成したDockerネットワークに3つのコンテナを作成し、それぞれのコンテナを連携させてWEBアプリを構築します。完成イメージは以下になります。

f:id:chakkyNote:20210317014509p:plain


想定環境

本記事で想定している環境構成を記載します。

カテゴリ 製品・バージョン
仮想化製品 VMware Workstation 15 Player
ゲストOS Cent OS 8.1
(CPU : 2 / Memory : 4GB / Disk : 20GB / NW : NAT)
コンテナ製品 Docker 20.10.5
WEBサーバ Apache 2.4.37
APサーバ Apache Tomcat 8.5.43
https://tomcat.apache.org/download-80.cgi
データベース psql (PostgreSQL) 12.6-1
https://yum.postgresql.org/repopackages
アプリケーション terasoluna-tourreservation 5.6.1
https://github.com/terasolunaorg/terasoluna-tourreservation

留意事項

表記ルール

・コードブロックにおける"#"はrootユーザでの実行です。

・コードブロックにおける"$"は非rootユーザでの実行です。

・コンテナログイン時のプロンプトは"Container>"で表示します。

お作法

・ファイルのバックアップなどは各自要否を判断してください。

・想定外動作の原因にもなるので、バージョンはできるだけ揃えることを推奨します。


OS基本設定

CentOS 8.1インストール初期状態から基本的なOS設定を行います。インストール後にifconfigコマンドでIPアドレスを確認し、ホストOSからTeratermなどで接続して下さい。

ホスト名の設定

任意のホスト名を設定する。ここでは"docker"に設定します。

$ su -
# echo "docker" > /etc/hostname
# cat /etc/hostname
docker

タイムゾーンの設定

タイムゾーンを"Asia/Tokyo"に設定します。

# timedatectl set-timezone Asia/Tokyo
# timedatectl status | grep "Time zone"
                Time zone: Asia/Tokyo (JST, +0900)

ファイアウォールの無効化

検証用の環境のため、ファイアウォールは無効化しておく。

# systemctl stop firewalld
# systemctl disable firewalld
# systemctl status firewalld

SELinuxの無効化

同様の理由で、SELinuxも無効化しておく。

# sed -i -e 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
# cat /etc/selinux/config | grep -v ^# | grep "SELINUX="
SELINUX=disabled

OS再起動

設定反映を確認するため、OS再起動する。

# shutdown -r now

Dockerインストール

コンテナ環境を構築するため、Dockerをインストールする。

レポジトリ最新化

まずパッケージレポジトリ情報を最新化する。

$ su -
# dnf -y update

Dockerレポジトリ追加

Docker関連レポジトリを追加する。

# dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

Dockerインストール

Dockerを動作させる必須コンポーネントであるcontainerd.ioをインストールし、Dockerをインストールする。インストールしたDockerのバージョンを確認した上でサービスを起動し、自動起動を有効化する。

# wget https://download.docker.com/linux/centos/8/x86_64/stable/Packages/containerd.io-1.4.3-3.1.el8.x86_64.rpm
# dnf install -y containerd.io-1.4.3-3.1.el8.x86_64.rpm
# dnf install -y docker-ce docker-ce-cli
# docker --version
Docker version 20.10.5, build d3cb89e

# systemctl start docker
# systemctl enable docker
# systemctl status docker

Dockerコンテナ作成

インストールしたDockerを使ってDockerネットワークを作成し、公式Dockerイメージからコンテナを作成、起動する。

Dockerネットワーク作成

Dockerは異なるコンテナ間での通信を可能にするため、仮想プライベートネットワークをホスト上に作成することができる。ここではWEBアプリ用のネットワークとして"terasoluna-tourreserve"という名前のネットワークを新規で作成する。サーバと独立したネットワークとして構築するため、ネットワーク種別はbridgeを指定する。

※Dockerのネットワークにはいくつかの種類があるが、ここでの説明は割愛する。

# docker network create -d bridge terasoluna-tourreserve
# docker network ls

Dockerイメージダウンロード

ApacheTomcatPostgreSQLそれぞれの用途に合わせたDockerイメージをダウンロードする。ダウンロード後にDockerイメージの一覧を表示する。

# docker pull httpd:2.4.37
# docker pull tomcat:8.5.43
# docker pull postgres:12.6
# docker images
REPOSITORY   TAG       IMAGE ID       CREATED         SIZE
postgres     12.6      fd94a7538179   4 days ago      314MB
tomcat       8.5.43    6e30b06a90d3   19 months ago   506MB
httpd        2.4.37    ef1dc54703e2   2 years ago     132MB

Dockerコンテナ作成

ダウンロードしたDockerイメージから3つのDockerコンテナを作成する。それぞれのコンテナ名はapache01、tomcat01、postgres01とする。コンテナを作成後にコンテナの一覧とコンテナの起動状態を確認する。docker runコマンドで指定するオプションについて、ポイントを以下に記載しておきます。

  • コンテナ内での操作を可能とするため、-itオプションを指定

  • コンテナがバックグラウンドで動かすため、-dオプションを指定

  • HTTPアクセスをApacheコンテナに転送するため、HTTPポートに対してポートバインディングを設定(apache01のみ)

  • パスワードを設定しないとコンテナが起動しないため、PostgreSQLの特権ユーザとパスワードを設定(postgres01のみ)

  • WEBアプリのデータベース要件を満たすため、エンコーディングロケールを設定(postgres01のみ)

# docker run -it -d --network terasoluna-tourreserve -p 80:80 --name apache01 httpd:2.4.37
# docker run -it -d --network terasoluna-tourreserve --name tomcat01 tomcat:8.5.43
# docker run -it -d --network terasoluna-tourreserve -e POSTGRES_USER=postgres -e POSTGRES_PASSWORD=P0stgres -e POSTGRES_INITDB_ARGS="--encoding=UTF-8 --locale=C" --name postgres01 postgres:12.6
# docker ps -a --no-trunc
# docker inspect --format='{{.State.Status}}' apache01 tomcat01 postgres01
running
running
running

コンテナIPアドレス確認

作成したコンテナに割り当てられているIPアドレスを確認するため、docker network inspectコマンドを実行する。なお、同じDockerネットワークに属しているDockerコンテナはコンテナ名で名前解決ができるため、通常IPアドレスを意識する必要はない。

# docker network inspect terasoluna-tourreserve

ポート疎通確認

製品のインストール状況、およびコンテナ間連携に必要なポートが開放されていることを確認する。コンテナにdocker execコマンドでログインし、本記事で必要となるパッケージをインストールした上で疎通確認を行う。なお、今回ダウンロードしたDockerイメージはDebian系のためyumやdnfなどRed Hat系のコマンドが使えないので注意して下さい。疎通確認における確認対象ポートは以下の通りです。

# docker exec -it apache01 /bin/bash
Container> # httpd -version | grep version
Server version: Apache/2.4.37 (Unix)
Container> # apt-get update
Container> # apt-get install -y iputils-ping netcat
Container> # ping tomcat01
Container> # nc -zv tomcat01 8009
tomcat01 [172.19.0.3] 8009 (?) open
Container> # exit

# docker exec -it tomcat01 /bin/bash
Container> # version.sh | grep version
Server version: Apache Tomcat/8.5.43
Container> # apt-get update
Container> # apt-get install -y netcat wget maven
Container> # ping postgres01
Container> # nc -zv postgres01 5432
postgres01 [172.19.0.4] 5432 (postgresql) open
Container> # exit

WEBアプリ構築

PostgreSQLコンテナ、Tomcatコンテナ、Apacheコンテナの順にWEBアプリ環境をセッティングし、WEBアプリが動作することを確認する。

パッケージインストール(postgres01)

PostgreSQLコンテナにログインし、本記事で必要なパッケージをインストールする。

# docker exec -it postgres01 /bin/bash
Container> # apt-get update
Container> # apt-get install -y wget maven
Container> # exit

データベース作成(postgres01)

PostgreSQLのバージョンを確認し、WEBアプリ用のデータベースを作成する。

# docker exec -it postgres01 /bin/bash
Container> # su - postgres
Container> $ psql --version
psql (PostgreSQL) 12.6 (Debian 12.6-1.pgdg100+1)
Container> $ psql -U postgres
Container> postgres=# CREATE DATABASE tourreserve;
Container> postgres=# \l
Container> postgres=# \q
Container> $ exit
Container> # exit

サンプルデータのセッティング(postgres01)

WEBアプリ資材をURLを指定してダウンロード&解凍し、Mavenユーティリティを使用してSQLを実行し、サンプルデータをセッティングする。mvnコマンド実行前に実行されるSQLのファイルセットを確認しておく。SQL実行後はデータベースに接続し、アプリケーション用のテーブルが作成されていることを確認する。

# docker exec -it postgres01 /bin/bash
Container> # wget https://github.com/terasolunaorg/terasoluna-tourreservation/archive/5.6.1.RELEASE.tar.gz
Container> # tar zxvf 5.6.1.RELEASE.tar.gz
Container> # ls -ld terasoluna-tourreservation-5.6.1.RELEASE/

Container> # cd terasoluna-tourreservation-5.6.1.RELEASE
Container> # ls -l terasoluna-tourreservation-initdb/src/main/sqls/postgres
Container> # mvn -f terasoluna-tourreservation-initdb/pom.xml sql:execute

Container> # su - postgres
Container> $ psql -d tourreserve -U postgres
Container> tourreserve=# \dp
Container> tourreserve=# \q
Container> $ exit
Container> # exit

DB接続先の設定(tomcat01)

WEBアプリ資材をURLからダウンロード&解凍し、データベース接続先を"localhost"から"postgres01"に修正する。

# docker exec -it tomcat01 /bin/bash
Container> # wget https://github.com/terasolunaorg/terasoluna-tourreservation/archive/5.6.1.RELEASE.tar.gz
Container> # tar zxvf 5.6.1.RELEASE.tar.gz
Container> # ls -ld terasoluna-tourreservation-5.6.1.RELEASE/

Container> # cd terasoluna-tourreservation-5.6.1.RELEASE/terasoluna-tourreservation-env/src/main/resources/META-INF/spring/
Container> # sed -i -e 's/localhost/postgres01/' terasoluna-tourreservation-infra.properties
Container> # cat terasoluna-tourreservation-infra.properties | grep database.url
database.url=jdbc:postgresql://postgres01/tourreserve
Container> # exit

アプリケーションのデプロイ(tomcat01)

Mavenユーティリティを使用してアプリケーションのビルドを行う。ビルド処理で生成されたwarファイルをコンテキストルートにコピーし、アプリケーションをデプロイする。

# docker exec -it tomcat01 /bin/bash
Container> # cd terasoluna-tourreservation-5.6.1.RELEASE/
Container> # mvn clean install

Container> # ls -l terasoluna-tourreservation-web/target/terasoluna-tourreservation-web.war
Container> # cp -p terasoluna-tourreservation-web/target/terasoluna-tourreservation-web.war /usr/local/tomcat/webapps/
Container> # ls -l /usr/local/tomcat/webapps/
Container> # exit

リバースプロキシ設定(apache01)

WEBアプリへのアクセスをApache経由で行うため、AJP通信の設定を行う。ApacheTomcatの双方で適切な設定が必要だが、Tomcatの公式イメージはデフォルトでAJP通信を許可しているため、今回はApache側のみ設定を修正する。修正後に設定を反映させるためApacheコンテナを再起動する。

# docker exec -it apache01 /bin/bash
Container> # ls -l conf/httpd.conf
Container> # sed -i -e 's/#LoadModule proxy_module modules\/mod_proxy.so/LoadModule proxy_module modules\/mod_proxy.so/' conf/httpd.conf
Container> # sed -i -e 's/#LoadModule proxy_ajp_module modules\/mod_proxy_ajp.so/LoadModule proxy_ajp_module modules\/mod_proxy_ajp.so/' conf/httpd.conf
Container> # cat conf/httpd.conf | grep -e mod_proxy.so -e mod_proxy_ajp.so
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_ajp_module modules/mod_proxy_ajp.so
Container> # echo "ProxyPass / ajp://tomcat01:8009/" >> conf/httpd.conf
Container> # tail -1 conf/httpd.conf
ProxyPass / ajp://tomcat01:8009/
Container> # exit

# docker restart apache01

WEBアプリ接続確認

ブラウザを起動し、http://<SERVER_IP_ADDRESS>/terasoluna-tourreservation-web にアクセスする。<SERVER_IP_ADDRESS>にはApacheコンテナではなくホスト(CentOS)のIPアドレスを指定する。以下のサンプルWEBアプリの画面が表示されていれば 構築完了です。

f:id:chakkyNote:20210317014529p:plain


おわりに

本記事ではDockerコンテナの公式イメージを使ってWEBアプリを構築してみました。コンテナ技術によって、製品のインストールや設定が非常に簡素化されることが実感できました。各コンポーネント連携に必要な設定も最小限であり、疎結合アーキテクチャを構成しやすいと感じました。次のステップとしては今回構築したコンテナWEBアプリをdocker-composeでパッケージ化し、環境複製することを視野に入れたより実践的なシナリオに挑戦してみたいと思います。