最小のNode.jsのDockerイメージを目指すスレでNode.jsのマルチステージビルドをやったので、今度はJavaでもマルチステージビルドをやってみます。
Javaは大学1年の授業で書いたっきりで17年ぐらいまともに書いてないし、当時はIntelliJ IDEAはおろか、Eclipseもなくて、NEWS上のEmacsじゃなくてMuleでコードを書いた記憶あります。世間ではVisual Age for Javaとか、シマンテックとかボーランドのIDEとか、Visual J++の時代でしたね。BeOSで動かない言語はこの世に存在しない言語と思っていました。Gradleはかなり良い感じですね(CMakeに比べて)。
src/main/java以下がコード置き場のルートらしいので、その下のhelloパッケージとしてコードをおきます。
package hello;
public class HelloWorld {
public static void main(String[] args) {
System.out.println("🆒");
}
}
Gradle用のビルド設定ファイルを作成します。
apply plugin: 'java'
apply plugin: 'application'
mainClassName = 'hello.HelloWorld'
applicationName = 'HelloWorld'
jar.baseName = 'helloworld'
distributions {
main {
baseName = 'HelloWorld'
}
}
Dockerファイルはこんな感じにしました。
公式パッケージにはjavaというのもあれば、gradleもあります。gradleはJavaの方に依存しています。ビルドする方のイメージではgradleのイメージを使います。
実行環境と合わせるためにAlpineベースのイメージにしていますが、その中に入ってビルドとか開発したいなら通常のDebianベースの方にするとか、ローカルのビルドの設定とかソースはマウントしたローカルのボリュームを参照するようにした方が良いと思います。
FROM gradle:jdk8-alpine as builder
ADD --chown=gradle:gradle build.gradle .
ADD --chown=gradle:gradle src src
RUN gradle installDist
FROM java:8-jre-alpine as runner
RUN addgroup -S -g 1000 app \
&& adduser -D -S -G app -u 1000 -s /bin/ash app
USER app
WORKDIR /home/app
COPY --from=builder --chown=app:app /home/gradle/build/install .
CMD HelloWorld/bin/HelloWorld
この前のNode.jsよりも少し複雑になっていますが、理由は権限です。
- gradleイメージはgradleユーザーで動き、ホームも/home/gradle
- ビルドイメージの方であとでイメージに入って試行錯誤できるように、gradleユーザー権限でファイルコピーするようにした
- 実行環境の方も、ユーザーを追加して、root以外で動くようにした
- ユーザー作成のRUN/USERコマンドでユーザー指定、WORKDIRでワークフォルダ作成が追加
はい。これでdocker build .
すれば、イメージができます。ビルド環境は180MB、実行環境のイメージは100MBです。少し小さくなりました。実行もできました。
$ docker run -it --rm イメージ
🆒