Kotlin 基礎 Part 13 -- Spring アプリを Docker イメージにビルドして実行する
Tags: kotlin, spring, docker, java
Published: 2023-02-13 07:59:58

## why

AWS の ECR にデプロイし、ECS のタスクとして動作させるため。
ECR はコンテナ・レジストリのため、Docker イメージにする必要があった。

---

## コンテナイメージへのビルドを調査

Spring のアプリは以前の記事ですでに作成してビルド実行まで可能な状態にしてある。

Docker イメージへのビルドと動作確認ができればば、
ECR に docker push できると考えた。

---

## Spring 公式を見て、Dockerfile を作成

https://spring.io/guides/topicals/spring-boot-docker/

Spring 公式を見て作る。

```Dockerfile
FROM eclipse-temurin:17-jdk-alpine
VOLUME /tmp
ARG JAR_FILE
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
```

temurin の jdk17 を使い
/tmp に永続化し？
JAR_FILE を受け取り(引数で渡す)
JAR_FILE を app.jar にコピー
app.jar を実行するエントリーポイント？を決める

このように解釈した。

---

### なぜ　openJDK ではなく temurin?

Docker 公式で非推奨になっているからだった。

https://stackoverflow.com/a/70355582

openjdk もあるのはわかった。

https://hub.docker.com/_/openjdk

ただ、Docker Hub には openJDK は非推奨で、
amazon correto や temurin を使えと書いてあった。

なので temurin を使う。

----
---


# Spring 公式通りに　Docker イメージを作成して失敗。

---

## Spring 公式を参考に Docker build で Docker イメージを作る

---

### Spring 公式の引数を使ってビルドに失敗

https://spring.io/guides/topicals/spring-boot-docker/

```php
docker build \
--build-arg JAR_FILE=target/*.jar \
-t myorg/myapp .
```

これでは Mac の自分の環境ではビルドできなかった。
Spring 公式ではこのコマンドでビルドできると書いてあった。
一方、下記の 2 つのエラーが出た。

---

### Docker の並列実行がエラーになる

```php
dockerfile.v0: failed to create LLB definition
```

https://qiita.com/takkeybook/items/2214892b45f9044de01d#%E7%92%B0%E5%A2%83%E5%A4%89%E6%95%B0%E3%81%AE%E8%A8%AD%E5%AE%9A

この takkeybook さんの記事を参考に

```php
export DOCKER_BUILDKIT=0
export COMPOSE_DOCKER_CLI_BUILD=0
```

.zshrc に上記の設定を追記して zsh を再起動したら解決した。
これは Docker の並列実行の設定を　OFF にしている。

---

### Linux/arm64 でビルドされていないエラー

次にビルドする Docker イメージが Mac のコアのアーキテクチャと違うエラーが出た。

```php
no matching manifest for linux/arm64 in the manifest list entries
```

https://qiita.com/jizya/items/38f15271903de629d1ab#%E3%82%A8%E3%83%A9%E3%83%BC%E5%86%85%E5%AE%B9

https://stackoverflow.com/questions/65612411/forcing-docker-to-use-linux-amd64-platform-by-default-on-macos

これらの 記事を参考にして

```php
--platform=linux/amd64
```

これを docker ビルド時に追加すると、上記のエラーが消えた。

----
----





# 改善を加えて実際に動作を確認

---

## 実際に動かすために必要だったファイルとコマンドたち

プロジェクト名は spring302

Dockerfile

```dockerfile
FROM eclipse-temurin:17-jdk-alpine
VOLUME /tmp
COPY build/libs/spring302-0.0.1-SNAPSHOT.jar app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
```

イメージのビルドコマンド

```php
docker build -t spring302 . 
```

イメージの実行コマンド

```php
docker run -p 8080:8080 spring302
```

このコマンドで実際に動かすことができた。

---

## -t とは？

https://qiita.com/saitoshi/items/a931399e81e63e8e4f1e#%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A%E3%82%A4%E3%83%A1%E3%83%BC%E3%82%B8%E3%81%AE%E3%83%93%E3%83%AB%E3%83%89

この記事によると、-t の引数は

-t {DockerHub のユーザー名}/イメージ名:タグ名

になっていて、ユーザー名とタグ名はオプショナルだ。

---

## 動作の詳細

```php
docker build -t spring302 .                      
Sending build context to Docker daemon  24.91MB
Step 1/4 : FROM eclipse-temurin:17-jdk-alpine
 ---> ce2d65591ecf
Step 2/4 : VOLUME /tmp
 ---> Using cache
 ---> 2bb51666c4a9
Step 3/4 : COPY build/libs/spring302-0.0.1-SNAPSHOT.jar app.jar
 ---> 3b3b9921a589
Step 4/4 : ENTRYPOINT ["java","-jar","/app.jar"]
 ---> [Warning] The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested
 ---> Running in 413b5bbec2fe
Removing intermediate container 413b5bbec2fe
 ---> 67cbf2faa084
Successfully built 67cbf2faa084
Successfully tagged spring302:latest
```

Dockerfile に従ってビルドが成功。

```php
docker images

REPOSITORY                TAG             IMAGE ID       CREATED          SIZE
spring302                 latest          67cbf2faa084   14 seconds ago   382MB
```

イメージが生成されている。

```php
docker run -p 8080:8080 spring302

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v3.0.2)

Started Spring302ApplicationKt in 14.871 seconds
```

イメージから起動できる。

---

## まとめ

MacOS を使って Spring アプリを Docker イメージにして実行する。
そのためには

1. zshrc などで Docker の並列ビルドを無効化
2. COPY する jar ファイルとして、build/...SNAPSHOT.jar を指定
3. docker build して　docker run する

これらの手順で実行できる。

---

## 今後

コンテナ化が完了したので、ECR にデプロイする。