これは、なにをしたくて書いたもの?
JibでローカルにしかないDockerイメージをベースイメージにしようとして、少しハマったのでメモしておきます。
通常はどこかのDockerレジストリーに登録すると思うので、ちょっとした確認用途などでしか使わないと思いますが。
結論としては、使用するベースイメージの名前の前にdocker://
接頭辞を付けるようにします。
環境
今回の環境はこちら。
$ java --version openjdk 21.0.6 2025-01-21 OpenJDK Runtime Environment (build 21.0.6+7-Ubuntu-124.04.1) OpenJDK 64-Bit Server VM (build 21.0.6+7-Ubuntu-124.04.1, mixed mode, sharing) $ mvn --version Apache Maven 3.9.9 (8e8579a9e76f7d015ee5ec7bfcdc97d260186937) Maven home: $HOME/.sdkman/candidates/maven/current Java version: 21.0.6, vendor: Ubuntu, runtime: /usr/lib/jvm/java-21-openjdk-amd64 Default locale: ja_JP, platform encoding: UTF-8 OS name: "linux", version: "6.8.0-53-generic", arch: "amd64", family: "unix"
Docker。
$ docker version Client: Docker Engine - Community Version: 28.0.0 API version: 1.48 Go version: go1.23.6 Git commit: f9ced58 Built: Wed Feb 19 22:11:04 2025 OS/Arch: linux/amd64 Context: default Server: Docker Engine - Community Engine: Version: 28.0.0 API version: 1.48 (minimum version 1.24) Go version: go1.23.6 Git commit: af898ab Built: Wed Feb 19 22:11:04 2025 OS/Arch: linux/amd64 Experimental: false containerd: Version: 1.7.25 GitCommit: bcc810d6b9066471b0b6fa75f557a15a1cbf31bb runc: Version: 1.2.4 GitCommit: v1.2.4-0-g6c52b3f docker-init: Version: 0.19.0 GitCommit: de40ad0
サンプルアプリケーションを作る
本題に入る前に、サンプルアプリケーションを作成します。この時点でJib Maven Pluginも導入しておきます。
RESTEasyを使って、Jakarta RESTful Web ServicesのSeBootstrapで簡単なサンプルを作成。
<properties> <maven.compiler.release>21</maven.compiler.release> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> </properties> <dependencies> <dependency> <groupId>org.jboss.resteasy</groupId> <artifactId>resteasy-core</artifactId> <version>6.2.11.Final</version> </dependency> <dependency> <groupId>org.jboss.resteasy</groupId> <artifactId>resteasy-undertow-cdi</artifactId> <version>6.2.11.Final</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>com.google.cloud.tools</groupId> <artifactId>jib-maven-plugin</artifactId> <version>3.4.4</version> <executions> <execution> <phase>package</phase> <goals> <goal>dockerBuild</goal> </goals> </execution> </executions> <configuration> <from> <image>eclipse-temurin:21.0.6_7-jdk-noble</image> </from> <to> <image>kazuhira/app</image> </to> <container> <ports> <port>8080</port> </ports> </container> </configuration> </plugin> </plugins> </build>
ベースイメージは、Eclipse Temurinにしておきます。
<from> <image>eclipse-temurin:21.0.6_7-jdk-noble</image> </from>
またmvn package
でDockerイメージをビルドするようにしています。
<executions> <execution> <phase>package</phase> <goals> <goal>dockerBuild</goal> </goals> </execution> </executions>
src/main/java/org/littlewings/jib/HelloResource.java
package org.littlewings.jib; import jakarta.ws.rs.GET; import jakarta.ws.rs.Path; import jakarta.ws.rs.Produces; import jakarta.ws.rs.core.MediaType; @Path("/hello") public class HelloResource { @GET @Produces(MediaType.TEXT_PLAIN) public String message() { return "Hello World!!"; } }
src/main/java/org/littlewings/jib/RestApplication.java
package org.littlewings.jib; import java.util.Set; import jakarta.ws.rs.ApplicationPath; import jakarta.ws.rs.core.Application; @ApplicationPath("/") public class RestApplication extends Application { @Override public Set<Class<?>> getClasses() { return Set.of(HelloResource.class); } }
src/main/java/org/littlewings/jib/App.java
package org.littlewings.jib; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import jakarta.ws.rs.SeBootstrap; public class App { public static void main(String... args) throws ExecutionException, InterruptedException { SeBootstrap.Configuration configuration = SeBootstrap .Configuration .builder() .host("0.0.0.0") .port(8080) .build(); SeBootstrap .start(new RestApplication(), configuration) .toCompletableFuture() .get(); while (true) { try { TimeUnit.SECONDS.sleep(1L); } catch (InterruptedException e) { // ignore } } } }
Dockerイメージを作成。
$ mvn package
できました。
$ docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE kazuhira/app latest 22e4fb026093 55 years ago 457MB
起動。
$ docker container run -it --rm --name app -p 8080:8080 kazuhira/app:latest
動作確認。
$ curl localhost:8080/hello Hello World!!
OKですね。
ベースイメージをローカルにしかないものにしてみる
先ほどは、Eclipse Temurinをベースイメージにしました。
<from> <image>eclipse-temurin:21.0.6_7-jdk-noble</image> </from>
ここを、ローカルにしかないイメージに差し替えてみます。
特に内容には凝らないので、単に名前を変えるくらいのものにしてみます。
Dockerfile
FROM eclipse-temurin:21.0.6_7-jdk-noble
ビルド。
$ docker image build -t kazuhira/my-temurin:21.0.6_7-jdk-noble .
では、このイメージを使うようにJib Maven Pluginの設定を変更してみます。
<from> <!-- <image>eclipse-temurin:21.0.6_7-jdk-noble</image> --> <image>kazuhira/my-temurin:21.0.6_7-jdk-noble</image> </from>
パッケージング。
$ mvn package
すると、DockerHubを見に行ってしまうのでビルドに失敗します。
[ERROR] Failed to execute goal com.google.cloud.tools:jib-maven-plugin:3.4.4:dockerBuild (default) on project local-base-image: Build to Docker daemon failed, perhaps you should make sure your credentials for 'registry-1.docker.io/kazuhira/my-temurin' are set up correctly. See https://github.com/GoogleContainerTools/jib/blob/master/docs/faq.md#what-should-i-do-when-the-registry-responds-with-unauthorized for help: Unauthorized for registry-1.docker.io/kazuhira/my-temurin: 401 Unauthorized [ERROR] GET https://registry-1.docker.io/v2/kazuhira/my-temurin/manifests/21.0.6_7-jdk-noble [ERROR] {"errors":[{"code":"UNAUTHORIZED","message":"authentication required","detail":[{"Type":"repository","Class":"","Name":"kazuhira/my-temurin","Action":"pull"}]}]} [ERROR] -> [Help 1]
よく見ると以下のヘルプが案内されているのですが、これはレジストリーの認証がうまくいかない場合のトラブルシュートです。
Frequently Asked Questions (FAQ) / What should I do when the registry responds with UNAUTHORIZED?
今回はローカルにしかないイメージを使いたいので、見るべきなのはこちらですね。
Jib - Containerize your Maven project / Extended Usage / Example / Setting the Base Image
こちらを見ると、docker://
接頭辞を付けてDockerデーモンからイメージを取得するようにするのが正解でしょう。
Retrieves the base image from the Docker daemon.
というわけで、こう変更。
<from> <image>docker://kazuhira/my-temurin:21.0.6_7-jdk-noble</image> </from>
再度Dockerイメージをビルド。
$ mvn package
今度はうまくビルドできました。
[INFO] --- jib:3.4.4:dockerBuild (default) @ local-base-image --- [INFO] [INFO] Containerizing application to Docker daemon as kazuhira/app... [WARNING] Base image 'kazuhira/my-temurin:21.0.6_7-jdk-noble' does not use a specific image digest - build may not be reproducible [INFO] [INFO] Container entrypoint set to [java, -cp, @/app/jib-classpath-file, org.littlewings.jib.App] [INFO] [INFO] Built image to Docker daemon as kazuhira/app [INFO] Executing tasks: [INFO] [==============================] 100.0% complete [INFO] [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 12.599 s [INFO] Finished at: 2025-02-22T18:32:12+09:00 [INFO] ------------------------------------------------------------------------
おわりに
JibでローカルのDockerイメージをベースイメージにする場合に、どうしたらいいのか調べてみました。
意外とハマりそうな気がするので、使う機会は少ないでしょうけれど覚えておきましょう。