testcontainers / testcontainers/testcontainers-java
ImageFromDockerfile(dockerImageName, deleteOnExit) failing to build container doesn't error usefully
まだ誰も着手していません。
- 主要言語
- Java
- スター
- 8.7k
- フォーク
- 1.9k
- 平均マージ
- 2日 17時間
- マージ済み PR(30日)
- 9
説明
I spent a couple of hours this morning chasing down an issue where a developer was able to use ImageFromDockerfile to build an image locally but it was failing in CI and on other machines despite running docker system prune -a on their machine to clear any possible cached images.
The stacktrace showed it oddly attempting to pull the image from Docker Hub and it failing because it doesn't exist there:
Container startup failed
org.testcontainers.containers.ContainerLaunchException: Container startup failed
at org.testcontainers.containers.GenericContainer.doStart(GenericContainer.java:330)
at org.testcontainers.containers.GenericContainer.start(GenericContainer.java:311)
at com.cloudnc.schedulesolver.services.integration.IntegrationTest.beforeSpec(IntegrationTest.kt:46)
at io.kotlintest.runner.jvm.spec.SpecRunner.executeBeforeSpec(SpecRunner.kt:40)
at io.kotlintest.runner.jvm.spec.SpecRunner.interceptSpec(SpecRunner.kt:26)
at io.kotlintest.runner.jvm.spec.SpecRunner.interceptSpec(SpecRunner.kt:53)
at io.kotlintest.runner.jvm.spec.SingleInstanceSpecRunner$execute$1.invokeSuspend(SingleInstanceSpecRunner.kt:53)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:274)
at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:86)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt:61)
at kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking$default(Builders.kt)
at kotlinx.coroutines.BuildersKt.runBlocking$default(Unknown Source)
at io.kotlintest.runner.jvm.spec.SingleInstanceSpecRunner.execute(SingleInstanceSpecRunner.kt:52)
at io.kotlintest.runner.jvm.spec.SpecExecutor$execute$$inlined$invoke$lambda$1.invoke(SpecExecutor.kt:54)
at io.kotlintest.runner.jvm.spec.SpecExecutor$execute$$inlined$invoke$lambda$1.invoke(SpecExecutor.kt:20)
at io.kotlintest.runner.jvm.spec.SpecExecutor.withExecutor(SpecExecutor.kt:31)
at io.kotlintest.runner.jvm.spec.SpecExecutor.execute(SpecExecutor.kt:37)
at io.kotlintest.runner.jvm.TestEngine$submitSpec$1.run(TestEngine.kt:111)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: org.testcontainers.containers.ContainerFetchException: Can't get Docker image: RemoteDockerImage(imageName=test/schedule-service:latest, imagePullPolicy=DefaultPullPolicy())
at org.testcontainers.containers.GenericContainer.getDockerImageName(GenericContainer.java:1286)
at org.testcontainers.containers.GenericContainer.logger(GenericContainer.java:615)
at org.testcontainers.containers.GenericContainer.doStart(GenericContainer.java:320)
... 25 more
Caused by: com.github.dockerjava.api.exception.NotFoundException: Status 404: {"message":"pull access denied for test/schedule-service, repository does not exist or may require 'docker login': denied: requested access to the resource is denied"}
at org.testcontainers.shaded.com.github.dockerjava.core.DefaultInvocationBuilder.execute(DefaultInvocationBuilder.java:241)
at org.testcontainers.shaded.com.github.dockerjava.core.DefaultInvocationBuilder.lambda$executeAndStream$1(DefaultInvocationBuilder.java:269)
... 1 more
com.cloudnc.schedulesolver.services.integration.IntegrationTest > initializationError FAILED
org.testcontainers.containers.ContainerLaunchException at IntegrationTest.kt:46
Caused by: org.testcontainers.containers.ContainerFetchException at IntegrationTest.kt:46
Caused by: com.github.dockerjava.api.exception.NotFoundException at DefaultInvocationBuilder.java:241
When I removed the dockerImageName and deleteOnExit arguments from the method then it gave me a much more useful error which showed the problem:
Container startup failed
org.testcontainers.containers.ContainerLaunchException: Container startup failed
at org.testcontainers.containers.GenericContainer.doStart(GenericContainer.java:330)
at org.testcontainers.containers.GenericContainer.start(GenericContainer.java:311)
at com.cloudnc.schedulesolver.services.integration.IntegrationTest.beforeSpec(IntegrationTest.kt:46)
at io.kotlintest.runner.jvm.spec.SpecRunner.executeBeforeSpec(SpecRunner.kt:40)
at io.kotlintest.runner.jvm.spec.SpecRunner.interceptSpec(SpecRunner.kt:26)
at io.kotlintest.runner.jvm.spec.SpecRunner.interceptSpec(SpecRunner.kt:53)
at io.kotlintest.runner.jvm.spec.SingleInstanceSpecRunner$execute$1.invokeSuspend(SingleInstanceSpecRunner.kt:53)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:274)
at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:86)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt:61)
at kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking$default(Builders.kt)
at kotlinx.coroutines.BuildersKt.runBlocking$default(Unknown Source)
at io.kotlintest.runner.jvm.spec.SingleInstanceSpecRunner.execute(SingleInstanceSpecRunner.kt:52)
at io.kotlintest.runner.jvm.spec.SpecExecutor$execute$$inlined$invoke$lambda$1.invoke(SpecExecutor.kt:54)
at io.kotlintest.runner.jvm.spec.SpecExecutor$execute$$inlined$invoke$lambda$1.invoke(SpecExecutor.kt:20)
at io.kotlintest.runner.jvm.spec.SpecExecutor.withExecutor(SpecExecutor.kt:31)
at io.kotlintest.runner.jvm.spec.SpecExecutor.execute(SpecExecutor.kt:37)
at io.kotlintest.runner.jvm.TestEngine$submitSpec$1.run(TestEngine.kt:111)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: org.testcontainers.containers.ContainerFetchException: Can't get Docker image: RemoteDockerImage(imageName=<resolving>, imagePullPolicy=DefaultPullPolicy())
at org.testcontainers.containers.GenericContainer.getDockerImageName(GenericContainer.java:1286)
at org.testcontainers.containers.GenericContainer.logger(GenericContainer.java:615)
at org.testcontainers.containers.GenericContainer.doStart(GenericContainer.java:320)
... 25 more
Caused by: com.github.dockerjava.api.exception.DockerClientException: Could not build image: COPY failed: file not found in build context or excluded by .dockerignore: stat build/libs/schedule-solver-app.jar: file does not exist
at com.github.dockerjava.api.command.BuildImageResultCallback.getImageId(BuildImageResultCallback.java:78)
at com.github.dockerjava.api.command.BuildImageResultCallback.awaitImageId(BuildImageResultCallback.java:50)
at org.testcontainers.images.builder.ImageFromDockerfile.resolve(ImageFromDockerfile.java:141)
at org.testcontainers.images.builder.ImageFromDockerfile.resolve(ImageFromDockerfile.java:37)
at org.testcontainers.utility.LazyFuture.getResolvedValue(LazyFuture.java:17)
at org.testcontainers.utility.LazyFuture.get(LazyFuture.java:39)
at org.testcontainers.shaded.com.google.common.util.concurrent.Futures$3.get(Futures.java:1332)
at org.testcontainers.images.RemoteDockerImage.getImageName(RemoteDockerImage.java:104)
at org.testcontainers.images.RemoteDockerImage.resolve(RemoteDockerImage.java:63)
at org.testcontainers.images.RemoteDockerImage.resolve(RemoteDockerImage.java:27)
at org.testcontainers.utility.LazyFuture.getResolvedValue(LazyFuture.java:17)
at org.testcontainers.utility.LazyFuture.get(LazyFuture.java:39)
at org.testcontainers.containers.GenericContainer.getDockerImageName(GenericContainer.java:1284)
... 27 more
The Dockerfile is attempting to copy in a jar that should have been built in an earlier step but was missed. It worked on the developer's local machine because they had the jar already built.
I'm not sure why passing the dockerImageName and deleteOnExit arguments to the method causes it to fail quietly and then attempt to run the image and so fetch from Docker Hub while the argumentless version gives me the more useful error message here?
コントリビューションガイド
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
調査の方向性
トレースに示されている ImageFromDockerfile.resolve と GenericContainer.getDockerImageName/RemoteDockerImage のパスから始め、引数なしのパスと比較してください。dockerImageName と deleteOnExit を使って build/libs/schedule-solver-app.jar がないケースを再現し、そのうえで、test/schedule-service:latest の pull を発生させるのではなく、基盤となる Docker build の失敗が表示されたままになることを確認してください。
索引モデルが issue の本文から書いたものです。
評価
- 技術スタック
- docker, java
- 領域
- testing
- issue の種類
- バグ
- 難易度
- 3/5
- 見積もり時間
- 1〜2日
- 活発さ
- 停滞
- 明瞭さ
- 説明が足りない
- 初心者へのやさしさ
- 35/100