DockerでSpring Boot+CentOS+Apache+MySQLな環境を作る

# 概要
DockerでCentOS上にApacheを立て、Spring Bootアプリケーション(MySQLも使う)を動かす以下のような環境を作成しました。
![docker-web-db.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233620/8057c1a1-ae95-5c26-3967-c308457a6a71.png)

Apacheを利用してSpring Bootアプリケーションに対してリバースプロキシをかけています。
普通は軽量LinuxであるAlpineを利用したOpenJDKのイメージを利用することが多いみたいですが、会社でのテスト環境に近い状態を作りたかったので、このような構成になりました。
特に理由がなければ、下記の記事のように、`openjdk:8-jdk-alpine`を使うのが良いと思います。
https://spring.io/guides/topicals/spring-boot-docker

## ファイル構成
```
ルートディレクトリ
   ├── docker-compose.yml
   ├── web
   │   ├── Dockerfile
   │   └── startup.sh
   ├── db
   │   └── Dockerfile
   ├── apache
   │   └── httpd.conf
   ├── initdb
   │   └── initdb.sql
   └── spring-boot
       └── 以下Spring Bootアプリケーション
```

## docker-compose
今回はwebサーバのコンテナとMySQLのコンテナの２つのコンテナを作成するので、docker-compose.ymlを以下のように書きました。

```yml:docker-compose.yml
version: "3"
services:
  web:
    build:
      context: ./web
    ports:
      - 5678:5678
    privileged: true
    tty: true
    links:
      - db
    volumes:
      - ./spring-boot/:/var/www/spring-boot/
      - ./apache/httpd.conf:/etc/httpd/conf/httpd.conf
    container_name: "centos-apache-jdk"
  db:
    build:
      context: ./db
    ports:
      - "13306:3306"
    environment:
      - MYSQL_ROOT_PASSWORD=root
    container_name: "mysql5.7-jp"
    volumes:
      - ./initdb/:/docker-entrypoint-initdb.d
```
※今回MySQLにも日本語対応させる関係で、Dockerfileを用意しています。

ここでのポイントは、dbコンテナ立ち上げ時に初期データを投入できるようにしていることです。
MySQL公式イメージでは、`/docker-entrypoint-initdb.d`配下に.sqlファイルや.shファイルを置いておくと、初回起動時に実行してくれます。

## webコンテナのDockerfile
CentOSのイメージをベースに、ApacheとOpenJDKをインストールしました。

```Dockerfile
FROM centos:7.6.1810

RUN yum -y update

# apacheをインストール
RUN yum -y install httpd

# openjdkのダウンロード
RUN curl -OL https://download.java.net/java/GA/jdk12/33/GPL/openjdk-12_linux-x64_bin.tar.gz
# 解凍
RUN tar zxf openjdk-12_linux-x64_bin.tar.gz -C /opt
# alternativesに登録
RUN alternatives --install /usr/bin/java java /opt/jdk-12/bin/java 1
RUN alternatives --install /usr/bin/jar jar /opt/jdk-12/bin/jar 1
RUN alternatives --install /usr/bin/javac javac /opt/jdk-12/bin/javac 1
# JAVA_HOME設定
ENV JAVA_HOME /opt/jdk-12

WORKDIR /var/www/spring-boot/

COPY startup.sh /startup.sh
RUN chmod 744 /startup.sh
# コンテナ作成時に起動スクリプト実行(ApacheとSpring Bootアプリケーション起動)
CMD ["/startup.sh"]
```
※せっかくなので最新のOpenJDK12を入れたかったのですが、`yum install`が対応していなかったため、バイナリファイルをダウンロードする方式にしています。OpenJDK11は`yum install`できるので、こだわりがなければそちらの方がシンプルです。

ここでのポイントは、ApacheとSpring Bootアプリケーションの起動を、１つの起動スクリプトにまとめていることです。
理由は、CMDを複数記述しても、最後の1行しか実行されないためです。今回ApacheとSpring Bootアプリケーションの起動コマンドは常駐化させたいため、CMDで行う必要があったので、シェルスクリプトにまとめました。詳しくは、以下の記事が参考になると思います。
https://sleepless-se.net/2018/05/26/docker%E3%81%A7%E8%A4%87%E6%95%B0cmd%E3%82%92%E5%AE%9F%E8%A1%8C%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95/

ちなみに、起動スクリプトには以下を記載しています。

```sh:startup.sh
#!/bin/bash

# Apacheの起動
/usr/sbin/httpd -D FOREGROUND

# Spring Bootアプリケーションの起動
./gradlew bootRun
```

## Apacheのconf
Dockerに重きを置いた記事なので、詳細は書きませんが、デフォルトの設定から

1. port:9876のvirtualhostを作成
2. `Listen`を5678に指定
3. `DocumentRoot`と`Directory`を`/var/www/spring-boot`に指定

を変更しました。1のvirtualhostに関しては、以下の内容をconfファイルの一番下に追加しました。

```
LoadModule rewrite_module modules/mod_rewrite.so

# Spring Boot application
<VirtualHost *:5678>
    ServerName localhost
    ProxyPass / http://127.0.0.1:9876/
    ProxyPassReverse / http://127.0.0.1:9876/
</VirtualHost>
```

## DBコンテナのDockerfile
MySQL公式のイメージのままだと、中に入っても日本語が入力できず、初期データで投入しても文字化けする状態だったので、以下のようにDockerfileを作って日本語対応しました。

```Dockerfile
# Dockerfile_MySQL
FROM mysql:5.7

# Set debian default locale to ja_JP.UTF-8
RUN apt-get update && \
    apt-get install -y locales && \
    rm -rf /var/lib/apt/lists/* && \
    echo "ja_JP.UTF-8 UTF-8" > /etc/locale.gen && \
    locale-gen ja_JP.UTF-8
ENV LC_ALL ja_JP.UTF-8

# Set MySQL character
RUN { \
    echo '[mysqld]'; \
    echo 'character-set-server=utf8mb4'; \
    echo 'collation-server=utf8mb4_general_ci'; \
    echo '[client]'; \
    echo 'default-character-set=utf8mb4'; \
} > /etc/mysql/conf.d/charset.cnf
```
こちらは、偉大なる以下の記事をほぼコピペです。
https://qiita.com/muff1225/items/48e0753e7b745ec3ecbd

## 最後に
これでコンテナを起動すれば、目的の環境を構築できます。

```
docker-compose build
docker-compose up
```
webコンテナに色々やらせすぎているので、本来のdockerの使い方ではないかもしれないですが、テスト環境に合わせるなどの要件がある際には、このような構成を試してみてはいかがでしょうか。