testcontainers-java
testcontainers-java copied to clipboard
[Bug]: Unable to start container with mount as GraalVM native image
Module
Core
Testcontainers version
1.20.6
Using the latest Testcontainers version?
Yes
Host OS
Windows/WLS
Host Arch
x86
Docker version
Client:
Version: 28.0.4
API version: 1.48
Go version: go1.23.7
Git commit: b8034c0
Built: Tue Mar 25 15:06:08 2025
OS/Arch: linux/amd64
Context: default
Server: Docker Desktop 4.0.0 ()
Engine:
Version: 28.0.4
API version: 1.48 (minimum version 1.24)
Go version: go1.23.7
Git commit: 6430e49
Built: Tue Mar 25 15:07:22 2025
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: 1.7.26
GitCommit: 753481ec61c7c8955a23d6ff7bc8e4daed455734
runc:
Version: 1.2.5
GitCommit: v1.2.5-0-g59923ef
docker-init:
Version: 0.19.0
GitCommit: de40ad0
What happened?
Hi,
please take a look at repo to reproduce at https://github.com/bedla/reproduce-graalvm-native-springboot-testcontainers
You can see that when running GraalVM native image, check for mount is failing.
It looks like that it is becase of prefix resource:.
Seems that there is missing pefix removal at org.testcontainers.utility.MountableFile#unencodeResourceURIToFilePath method?
Thank you
Ivos
Relevant log output
2025-04-22T13:50:55.790Z DEBUG 1 --- [demo] [ main] org.testcontainers.DockerClientFactory : Failure while checking for mountable file support
com.github.dockerjava.api.exception.InternalServerErrorException: Status 500: mount denied:
the source path "resource:/org/testcontainers/utility/ResourceReaper.class:/dummy:ro"
too many colons
at org.testcontainers.shaded.com.github.dockerjava.core.DefaultInvocationBuilder.execute(DefaultInvocationBuilder.java:247) ~[na:na]
at org.testcontainers.shaded.com.github.dockerjava.core.DefaultInvocationBuilder.post(DefaultInvocationBuilder.java:124) ~[na:na]
at org.testcontainers.shaded.com.github.dockerjava.core.exec.CreateContainerCmdExec.execute(CreateContainerCmdExec.java:37) ~[na:na]
at org.testcontainers.shaded.com.github.dockerjava.core.exec.CreateContainerCmdExec.execute(CreateContainerCmdExec.java:13) ~[na:na]
at org.testcontainers.shaded.com.github.dockerjava.core.exec.AbstrSyncDockerCmdExec.exec(AbstrSyncDockerCmdExec.java:21) ~[cz.publicstaticvoidmain.reproduce.demo.DemoApplicationKt:1.20.6]
at org.testcontainers.shaded.com.github.dockerjava.core.command.AbstrDockerCmd.exec(AbstrDockerCmd.java:33) ~[cz.publicstaticvoidmain.reproduce.demo.DemoApplicationKt:1.20.6]
at org.testcontainers.shaded.com.github.dockerjava.core.command.CreateContainerCmdImpl.exec(CreateContainerCmdImpl.java:608) ~[cz.publicstaticvoidmain.reproduce.demo.DemoApplicationKt:1.20.6]
at org.testcontainers.DockerClientFactory.runInsideDocker(DockerClientFactory.java:364) ~[na:na]
at org.testcontainers.DockerClientFactory.runInsideDocker(DockerClientFactory.java:351) ~[na:na]
at org.testcontainers.DockerClientFactory.checkMountableFile(DockerClientFactory.java:293) ~[na:na]
at org.testcontainers.DockerClientFactory.isFileMountingSupported(DockerClientFactory.java:99) ~[na:na]
at org.testcontainers.containers.ContainerDef.applyTo(ContainerDef.java:117) ~[cz.publicstaticvoidmain.reproduce.demo.DemoApplicationKt:1.20.6]
at org.testcontainers.containers.GenericContainer.applyConfiguration(GenericContainer.java:783) ~[cz.publicstaticvoidmain.reproduce.demo.DemoApplicationKt:1.20.6]
at org.testcontainers.containers.GenericContainer.tryStart(GenericContainer.java:381) ~[cz.publicstaticvoidmain.reproduce.demo.DemoApplicationKt:1.20.6]
at org.testcontainers.containers.GenericContainer.lambda$doStart$0(GenericContainer.java:346) ~[cz.publicstaticvoidmain.reproduce.demo.DemoApplicationKt:1.20.6]
at org.rnorth.ducttape.unreliables.Unreliables.retryUntilSuccess(Unreliables.java:81) ~[na:na]
at org.testcontainers.containers.GenericContainer.doStart(GenericContainer.java:336) ~[cz.publicstaticvoidmain.reproduce.demo.DemoApplicationKt:1.20.6]
at org.testcontainers.containers.GenericContainer.start(GenericContainer.java:322) ~[cz.publicstaticvoidmain.reproduce.demo.DemoApplicationKt:1.20.6]
at cz.publicstaticvoidmain.reproduce.demo.MyCommandLineRunner.run(DemoApplication.kt:54) ~[cz.publicstaticvoidmain.reproduce.demo.DemoApplicationKt:na]
at org.springframework.boot.SpringApplication.lambda$callRunner$5(SpringApplication.java:788) ~[cz.publicstaticvoidmain.reproduce.demo.DemoApplicationKt:3.4.4]
at org.springframework.util.function.ThrowingConsumer$1.acceptWithException(ThrowingConsumer.java:82) ~[na:na]
at org.springframework.util.function.ThrowingConsumer.accept(ThrowingConsumer.java:60) ~[cz.publicstaticvoidmain.reproduce.demo.DemoApplicationKt:6.2.5]
at org.springframework.util.function.ThrowingConsumer$1.accept(ThrowingConsumer.java:86) ~[na:na]
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:796) ~[cz.publicstaticvoidmain.reproduce.demo.DemoApplicationKt:3.4.4]
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:787) ~[cz.publicstaticvoidmain.reproduce.demo.DemoApplicationKt:3.4.4]
at org.springframework.boot.SpringApplication.lambda$callRunners$3(SpringApplication.java:772) ~[cz.publicstaticvoidmain.reproduce.demo.DemoApplicationKt:3.4.4]
at [email protected]/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184) ~[na:na]
at [email protected]/java.util.stream.SortedOps$SizedRefSortingSink.end(SortedOps.java:357) ~[na:na]
at [email protected]/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:510) ~[cz.publicstaticvoidmain.reproduce.demo.DemoApplicationKt:na]
at [email protected]/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499) ~[cz.publicstaticvoidmain.reproduce.demo.DemoApplicationKt:na]
at [email protected]/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151) ~[cz.publicstaticvoidmain.reproduce.demo.DemoApplicationKt:na]
at [email protected]/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174) ~[na:na]
at [email protected]/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[cz.publicstaticvoidmain.reproduce.demo.DemoApplicationKt:na]
at [email protected]/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596) ~[cz.publicstaticvoidmain.reproduce.demo.DemoApplicationKt:na]
at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:772) ~[cz.publicstaticvoidmain.reproduce.demo.DemoApplicationKt:3.4.4]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:325) ~[cz.publicstaticvoidmain.reproduce.demo.DemoApplicationKt:3.4.4]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1361) ~[cz.publicstaticvoidmain.reproduce.demo.DemoApplicationKt:3.4.4]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1350) ~[cz.publicstaticvoidmain.reproduce.demo.DemoApplicationKt:3.4.4]
at cz.publicstaticvoidmain.reproduce.demo.DemoApplicationKt.main(DemoApplication.kt:109) ~[cz.publicstaticvoidmain.reproduce.demo.DemoApplicationKt:na]
at [email protected]/java.lang.invoke.LambdaForm$DMH/sa346b79c.invokeStaticInit(LambdaForm$DMH) ~[na:na]
2025-04-22T13:50:55.790Z WARN 1 --- [demo] [ main] o.t.containers.ContainerDef : Unable to mount a file from test host into a running container. This may be a misconfiguration or limitation of your Docker environment. Some features might not work.
Additional Information
No response
related URLs to this topic
- https://github.com/testcontainers/testcontainers-java/issues/7954
- https://github.com/oracle/graal/issues/7682
- https://github.com/Kehrlann/native-image-resource-fs/blob/main/src/test/java/wf/garnier/nativeimage/FilesystemTests.java
Seems that file (or dir tree) embedded into GraalVM native-image has to be extracted to temp-dir and mounted, like currently org.testcontainers.utility.MountableFile#extractClassPathResourceToTempLocation is doing the same with files inside .jar.