IDE上でしかSpringアプリを実行できなかった奴がDockerで動かしてみた

# 経緯

テキトーなIDEを使ってSpringアプリは作れるけど、Dockerとかjarとかよくわからない人向けに書きました。

とりあえずローカルでDocker＋Spring環境に慣れようと思ったのでその学習備忘録。

# 前提

## 実行環境

* macOS Catalina 10.15.6

## 使用するもの（ざっくり）

* Spring-Bootで作成したアプリ（IDE上で動く前提、バージョン:2.3.3）
* Gradle(関係するのはjar生成部分のみなので、Mavenご使用の方はビルドコマンドのみ別途お調べいただけると)
* Docker（バージョン:19.03.13）

## アプリのディレクトリ構成

```
.
├── HELP.md
├── build
├── build.gradle // ビルド設定
├── gradle
├── gradlew
├── gradlew.bat
├── settings.gradle
└── src // 丹精込めて書いたソース
```

自分はSpring initializerから生成したけど大抵は上記のようになっているはず。。

# 手順

## 概要

1. 作成したアプリからjarファイルを生成する。
2. Dockerfileを用意する。
3. Docker起動。
 
fin.（Dockerコンテナ上で動く！！）

# 詳細

### 1.作成したアプリからjarファイルを生成する。

#### build.gradleにjarを生成するための設定を追加

```gradle

// ↑省略、依存関係がつらつらと・・・ //

// 追加分↓ //
def springBootApplicationName = 'test-build' // 生成するjarファイル名を定義した変数（別に変数化しなくても良い）
def applicationVersion = project.properties['release.version'] // バーションを定義した変数（別に変数化しなくても良い）

bootJar {
    baseName = springBootApplicationName // 生成するjarファイル名を指定
    version = applicationVersion // バーションを指定（詳しいことは調べてないけどなくても良さそう）
}
```

#### ターミナル上でアプリのディレクトリに移動し、以下のコマンドを叩く

```terminal
$ gradle build
```

#### `./build/libs`配下にjarファイルが生成されていることを確認する

```terminal
$ tree ./build/libs
./build/libs
└── test-build.jar
```

### 2.Dockerfileを用意する。

#### アプリの最上ディレクトリに`Dockerfile`という名前のファイルを作成する。（拡張子不要）

```
.
├── Dockerfile // New!!
├── HELP.md
├── build
├── build.gradle
├── docker-compose.yaml
├── gradle
├── gradlew
├── gradlew.bat
├── settings.gradle
└── src
```

#### Dockerfileに以下を記述

```dockerfile
# DockerHubの使用するイメージを指定。Java11を実行させるためのJDKを指定
# （公式のopenJDKもあるけど、AWSにデプロイする前提で作成したのでここではなんとなくAWS提供のものを指定）
FROM amazoncorretto:11 

# 前に生成したjarが置いてあるディレクトリパスを格納する変数定義（ここではコマンドから値を指定する）
ARG JAR_FILE

# jarファイルをコンテナ内にコピーする。(app.jarはコンテナ内での配置場所を指定（任意の場所）)
COPY ${JAR_FILE} app.jar

# 当コンテナ実行時に実行するコマンドを定義（ここではコピーしたjarを実行している）
ENTRYPOINT ["java","-jar","/app.jar","--spring.profiles.active=docker"]
```

### 3.Docker起動。

#### 未インストールなら`Docker`をインストール

* [こちら](https://qiita.com/ama_keshi/items/b4c47a4aca5d48f2661c)の記事をご参考に

#### ターミナル上でアプリのディレクトリへ移動し、以下のコマンドを叩く。（Dockerイメージの生成）


```terminal
docker build --build-arg JAR_FILE=build/libs/test-build.jar -t springio/gs-spring-boot-docker .
```

* オプション一部解説：
  
Dockerfile上で定義した変数の値を指定する。

```terminal
--build-arg JAR_FILE=build/libs/test-build.jar
```

生成するイメージにつける名前（任意、ここでは参考にした記事のものをそのまま引用させていただいてます）

```terminal
-t springio/gs-spring-boot-docker
```

#### イメージを生成できたら、以下のコマンドを叩く。（Dockerイメージの起動）
 注意：-pなどのオプションは`run`のすぐ右側で定義しないと設定されない。（参考記事が無くてここでめちゃくちゃハマった・・・コマンド界隈では常識なのか・・？） 

```terminal
docker run -p 8080:8080 --name spring-test --rm  springio/gs-spring-boot-docker
```

* オプション一部解説：

コンテナ上のポート（左）と、実行ホスト上のポート（右）をマッピングする。
application.propertiesで指定していなければ8080で起動しているはずなので、それをローカルの8080ポートと紐付ける

```terminal
-p 8080:8080
```

#### IDEで見慣れたSpring起動ログが流れると思うので、無事起動を確認したらlocalhost:8080にアクセス
→コンテナ上のアプリと接続できる！！

※イメージの停止や削除の方法は割愛。

### 余談：localhost上のDBと繋ぐには

* `host.docker.internal:（ポート番号）`と定義（`localhost:（ポート番号）`のままだと繋がらない）
 * 例：`jdbc:mysql://host.docker.internal:3306/xxx`

# 後書き

これを見ればとりあえずSpringをDockerで動かせる・・・！という状態になれるような記事を目指して書きました。
Dockerの概念やコマンドの詳細など、細かい解説は様々な有識者が記事にしてくださっているのでここでは割愛いたします。

Dockerまだ触りたてなので理解が間違っている箇所などありましたらご指摘いただけると幸いです。

# 参考

* [公式記載の手順](https://spring.pleiades.io/guides/gs/spring-boot-docker/)
* [Macにdockerインストール](https://qiita.com/ama_keshi/items/b4c47a4aca5d48f2661c)
* [Docker × Spring Boot環境構築](https://qiita.com/A-Kira/items/beaf79a0d39d9839e61e)
* [Dockerfileを書いてみる](https://qiita.com/nl0_blu/items/1de829288db2670276e8)