昨日、Spring Boot Thin Launcherの話を書いたけど。
最後に、でもFat JARと比べて何が嬉しいのかな?って考えて
Dockerのレイヤーにライブラリーを閉じ込めてしまえば、依存関係が変わらない限り再利用できるなぁ、って思った。それはまた次の機会に書こうと思う。
ということで、とりあえず閉じ込めてみた話。でも、これが役に立つかどうかは正直知らん。
## コードはこれ
https://github.com/bufferings/spring-boot-thin-sandbox
のdemo-thin-docker
ディレクトリ。
こんな感じで依存ライブラリを含まないThin JARを作って
❯ cd demo-thin-docker
❯ ./mvnw clean package
Dockerイメージをビルド
❯ docker build -t demo-thin-docker .
ビルド中に依存ライブラリーのダウンロードをするので、しばらく時間がかかる。
で、実行すると
❯ docker run -p 8080:8080 demo-thin-docker - thin.debug=true - thin.offline=true … 2018–09–30 13:42:32.978 INFO 1 - - [ main] com.example.demo.DemoApplication : Started DemoApplication in 3.437 seconds (JVM running for 5.804) …
という感じ。依存ライブラリーは既にダウンロード済みなので、普通の速さで起動する。
一度ビルドすると、依存ライブラリーを変更しないかぎり次からはそのレイヤーが再利用されるからビルドに時間はかからない。
## Spring Boot Thin Launcherのオプション
Dockerfileの説明をする前にSpring Boot Thin Launcherのオプションについて触れておく。ここに書いてる
https://github.com/dsyer/spring-boot-thin-launcher#command-line-options
色々あって面白いんだけど、その中で今回使ってるやつをピックアップ
thin.dryrun
アプリケーションを起動せずに、依存関係のダウンロードだけをする。
thin.offline
オフラインモードになる。ローカルのリポジトリーにあるやつだけを使う。ローカルになければ例外になる。
thin.archive
普通に起動すると、その起動したJARを実行しようとするんだけど、それとは別のJARを対象にしたい場合に使う。これを使った理由は後で説明する。
thin.debug
デバッグ情報がでる。
thin.trace
めっちゃ色々でる。あ、これは確認するときに使ったってだけで、今日紹介する手順の中では使ってなかった。
## Dockerfile
はこうなってる。マルチステージビルドを使ってる。
FROM openjdk:11-jdk-slim COPY docker/spring-boot-thin-wrapper-1.0.15.RELEASE.jar /thin/wrapper.jar COPY pom.xml /thin/pom.xml WORKDIR /thin RUN jar cvf pom.jar pom.xml RUN java -jar wrapper.jar \ --thin.archive=/thin/pom.jar \ --thin.dryrun=true \ --thin.debug=true FROM openjdk:11-jre-slim COPY --from=0 /root/.m2 /root/.m2 COPY target/demo-thin-docker-0.0.1-SNAPSHOT.jar /app.jar ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
いっこずつ説明していく。
## FROM
FROM openjdk:11-jdk-slim
特に理由はないけど11を使ってみた。
## COPY wrapper.jar
COPY docker/spring-boot-thin-wrapper-1.0.15.RELEASE.jar /thin/wrapper.jar
対象のJARがまだない状態で、pom.xml
を元に依存ライブラリーだけダウンロードしてきたいなーと思ったので、その機能(ThinJarWrapper
)を持ってるwrapper.jar
をダウンロードしておいた。
## COPY pom.xml
COPY pom.xml /thin/pom.xml WORKDIR /thin RUN jar cvf pom.jar pom.xml
プロジェクトルートからpom.xml
をコピーしてJARに固める。wrapper.jar
でpom.xml
を直接読めたらいいなーって思ったんだけど、ソースを見てみたら、どうもJARじゃないとだめみたいなので、pom.xml
だけを持ったpom.jar
を作ることにした。
## dry-run
RUN java -jar wrapper.jar \ --thin.archive=/thin/pom.jar \ --thin.dryrun=true \ --thin.debug=true
dry-runモードでwrapper.jar
を実行する。でも対象はwrapper.jar
じゃなくてpom.jar
の中のpom.xml
にしたいので、thin.archive
で指定。
thin.root
オプションを指定していないので、デフォルトの.m2
ディレクトリに依存ライブラリーがダウンロードされる。
## COPY .m2
FROM openjdk:11-jre-slim COPY --from=0 /root/.m2 /root/.m2
依存ライブラリーのダウンロードが終わったら、その.m2
ディレクトリーだけがあればいい。wrapper.jar
やpom.jar
は要らないので、別のイメージをFROMにして.m2
だけを持ってくる。
## COPY app.jar and run
COPY target/demo-thin-docker-0.0.1-SNAPSHOT.jar /app.jar ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
で、あとはいつも通りアプリのJARをコピーしてきて、エントリーポイントを書いておく。
## Offline Mode
実行するときにダウンロードしてきてないことを確認するためにオフラインモードで起動してみた
❯ docker run -p 8080:8080 demo-thin-docker - thin.debug=true - thin.offline=true
実際にはここで何度かエラーが出て、試行錯誤したのであった(thin.properties
を使う方法があって、最初はそっちでやってたんだけど、それだとランチャーがダウンロードされてなくて、ここで「ランチャーがないから無理!」って怒られたのであった。ごにょっとしたらいけたんだけど、それより素直にpomを使うことにした。)
## という感じ!
今のところThin Launcherは使うつもりはないけど、何かで「依存ライブラリーを切り離したいな」って思ったときには、この記事を読みなおしてやってみるかもなぁというくらい。
いい感じの用途を思いついたら教えてください!これでThin Launcher遊びはおしまい!