固定文字列を返すAPIをDockerでデプロイする

前回仮想マシンを作ったので、今回は固定文字列を返すAPIを作り、AppServiceにデプロイします。色々と設定や制約があるかもしれないのでDockerをデプロイする形が一番ハマる要素がないかと思っています。

## APIを作る
SpringBootの公式に手順があったのでVisualStudioCodeで作る

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

```java:Application.java
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@RestController
public class Application {

  @RequestMapping("/")
  public String home() {
    return "Hello Docker World kaikusakari!!";
  }

  public static void main(String[] args) {
    SpringApplication.run(Application.class, args);
  }
}
```

Docker用にファイルを作る
公式のサンプルをコピペ

```dockerfile:dockerfile
FROM openjdk:8-jdk-alpine
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
```

Gradleでビルド
VSC上でシェル実行できるのでわざわざターミナル起動しなくて良いのが地味に嬉しい。

```sh
$ ./gradlew build && java -jar build/libs/gs-spring-boot-docker-0.1.0.jar

Welcome to Gradle 7.5!

Here are the highlights of this release:
 - Support for Java 18
 - Support for building with Groovy 4
 - Much more responsive continuous builds
 - Improved diagnostics for dependency resolution
For more details see https://docs.gradle.org/7.5/release-notes.html

BUILD SUCCESSFUL in 4s
7 actionable tasks: 7 executed
Error: Unable to access jarfile build/libs/gs-spring-boot-docker-0.1.0.jar
$

# サンプルを一部修正したのでファイル名が変わってしまった。これで問題なく動きました。
$ java -jar build/libs/demo-0.0.1-SNAPSHOT.jar
```

Dockerのビルド

```sh
$ docker build --build-arg JAR_FILE=build/libs/\*.jar -t springio/gs-spring-boot-docker .
```

ローカルでDockerをデプロイしてみる

```sh
$ docker run -p 8080:8080 springio/gs-spring-boot-docker
Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main" java.lang.UnsupportedClassVersionError: org/springframework/boot/loader/JarLauncher has been compiled by a more recent version of the Java Runtime (class file version 61.0), this version of the Java Runtime only recognizes class file versions up to 52.0
        at java.lang.ClassLoader.defineClass1(Native Method)
```

Javaのビルドバージョンと実行バージョンが異なるのでエラーになった。
dockerfileを見ると8で実行しているので17に変更する

```dockerfile
- FROM openjdk:8-jdk-alpine
+ FROM openjdk:17-jdk-alpine
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
```

再度Dockerをビルドしするもイメージがないとエラーになった

```sh
 => ERROR [internal] load metadata for docker.io/library/openjdk:17-jdk-alpine  
```

イメージを確認してみると openjdk: **17-alpine** という名前とのことでした
再度修正してビルドしました

```dockerfile
- FROM openjdk:17-jdk-alpine
+ FROM openjdk:17-alpine
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
```

runして動作確認できました

```
docker run -p 8080:8080 springio/gs-spring-boot-docker
```

以前どこかのドキュメントでAppServiceは80ポートしか使えない、と見た記憶があったのでリッスンするポートを8080→80に変更する

```application.properties
server.port=80
```

ポートを整理する

```
docker run -p 80:80 springio/gs-spring-boot-docker
```

http://localhost で動作確認できました。
ここからAzureのレジストリにpushしてAppServiceにデプロイしたいのですが、遅くなってしまったので次の日に続けたいと思います。