docker-composeでspring-boot+mysqlのアプリケーションを起動

docker-composeでアプリを管理したかったので、作ってみた

## リポジトリ
https://github.com/yamee-dev/kotlin_restapi

```console
git clone git@github.com:yamee-dev/kotlin_restapi.git
git checkout 7921016d820eead5f3869090e2d5f71fe70c7c0f
```

## QuickStart
```console
git clone git@github.com:yamee-dev/kotlin_restapi.git
git checkout 7921016d820eead5f3869090e2d5f71fe70c7c0f
gradle build
docker-compose up --build
```

## docker-compose.yml

`docker-compose.yml`でDBサーバーとAPPサーバーのコンテナ設定を書く。

```./docker-compose.yml
version: "3"
services:
  dbserver:
    container_name: mysql5.7_kotlin_restapi
    image: mysql:5.7
    environment:
      MYSQL_DATABASE: kotlin_restapi_db
      MYSQL_USER: user
      MYSQL_PASSWORD: password
      MYSQL_ROOT_PASSWORD: rootpassword
    expose:
      - 3306
    ports:
      - 3306:3306
    volumes:
      # 起動スクリプト
      - ./docker-compose/mysql/initdb:/docker-entrypoint-initdb.d
      # MySQLの設定ファイル
      - ./docker-compose/mysql/config:/etc/mysql/conf.d
      # DBの永続化
      - mysql_db:/var/lib/mysql
  app:
    container_name: spring_app
    build: ./docker-compose/spring
    depends_on:
      # dbserverが起動してから、appを起動
      - dbserver
    ports:
      - "8080:8080"
    volumes:
      - .:/app
    environment:
      # mysqlの接続設定 host:portはコンテナ名指定
      spring.datasource.driverClassName: "com.mysql.cj.jdbc.Driver"
      spring.datasource.url: "jdbc:mysql://dbserver/kotlin_restapi_db"
      spring.datasource.username: "user"
      spring.datasource.password: "password"
# DBの永続化先
volumes:
  mysql_db:
    driver: local
```

## MySQLの設定

`docker-compose.yml`の以下の部分に対応するファイルを作成

```docker-compose.yml
services:
  dbserver:
--- 省略 ---
    volumes:
      # 起動スクリプト
      - ./docker-compose/mysql/initdb:/docker-entrypoint-initdb.d
      # MySQLの設定ファイル
      - ./docker-compose/mysql/config:/etc/mysql/conf.d
```

MySQLの設定を管理するファイル。とりあえず、文字コードを設定してみる

```./docker-compose/mysql/config/my.cnf
[mysqld]
character-set-server=utf8

[client]
default-character-set=utf8
```

`./docker-compose/mysql/initdb`以下にsqlファイルを配置すると、MySQL起動時に実行される。
今回は使用しない。(JPAにその役割を持たせているため)

## App(SpringBoot)の設定
buildされる`Dockerfile`を書く

```./spring/Dockerfile
# jdkを環境にインストール
FROM openjdk:jdk-alpine
VOLUME /tmp
# ワーキングディレクトリの作成
RUN mkdir /app
WORKDIR /app

ENV JAR_TARGET "kotlin_restapi-0.0.1-SNAPSHOT.jar"
# 起動コマンドをシェル環境で実行
ENTRYPOINT ["sh","-c","java -jar -Dspring.profiles.active=docker-compose ./build/libs/${JAR_TARGET}"]
```

## application.ymlの修正
ローカル環境と環境を分けたいので、新たに、`docker-compose`という名前の環境を追加
`java -jar -Dspring.profiles.active=docker-compose ./build/libs/${JAR_TARGET}`のように、起動コマンドで実行環境を指定できる。

```./src/main/resources/application.yml
spring:
  profiles:
    active: localhost

---
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/kotlin_restapi_db
    username: root
    password:
    driver-class-name: com.mysql.cj.jdbc.Driver
  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true

---
spring:
  profiles: docker-compose
  datasource:
    url: jdbc:mysql://dbserver/kotlin_restapi_db
    username: user
    password: password
    driver-class-name: com.mysql.cj.jdbc.Driver
  jpa:
    hibernate:
      ddl-auto: update

```

## 起動確認

docker-composeを実行。mysql→springの順に実行される。

```console
$ docker-compose up --build
```

apiを叩いてみる

```console
$ curl -XPOST -H "Content-type: application/json" -d '{"username": "Kazuma","age": 17,"jobs": "NEET"}' 'http://localhost:8080/api/v1/characters'
{
  "id": 1,
  "username": "Kazuma",
  "age": 17,
  "jobs": "NEET"
}

$ curl http://localhost:8080/api/v1/characters |jq
[
  {
    "id": 1,
    "username": "Kazuma",
    "age": 17,
    "jobs": "NEET"
  }
]
```

 - バックグラウンドで実行

```console
$ docker-compose up -d
```

- 終了

```console
$ docker-compose down
```