diff --git a/core/src/main/java/org/testcontainers/images/builder/ImageFromDockerfile.java b/core/src/main/java/org/testcontainers/images/builder/ImageFromDockerfile.java index b36779f1b9e..277c546c7cb 100644 --- a/core/src/main/java/org/testcontainers/images/builder/ImageFromDockerfile.java +++ b/core/src/main/java/org/testcontainers/images/builder/ImageFromDockerfile.java @@ -32,6 +32,7 @@ import java.util.Map; import java.util.Optional; import java.util.Set; +import java.util.regex.Matcher; import java.util.zip.GZIPOutputStream; @Slf4j @@ -167,15 +168,31 @@ private void prePullDependencyImages(Set imagesToPull) { final DockerClient dockerClient = DockerClientFactory.instance().client(); imagesToPull.forEach(imageName -> { + String resolvedImageName = resolveImageNameFromBuildArgs(imageName); try { - log.info("Pre-emptively checking local images for '{}', referenced via a Dockerfile. If not available, it will be pulled.", imageName); - DockerClientFactory.instance().checkAndPullImage(dockerClient, imageName); + log.info("Pre-emptively checking local images for '{}', referenced via a Dockerfile. If not available, it will be pulled.", resolvedImageName); + DockerClientFactory.instance().checkAndPullImage(dockerClient, resolvedImageName); } catch (Exception e) { - log.warn("Unable to pre-fetch an image ({}) depended upon by Dockerfile - image build will continue but may fail. Exception message was: {}", imageName, e.getMessage()); + log.warn("Unable to pre-fetch an image ({}) depended upon by Dockerfile - image build will continue but may fail. Exception message was: {}", resolvedImageName, e.getMessage()); } }); } + private String resolveImageNameFromBuildArgs(final String imageName) { + Optional imageBuildArg = buildArgs.keySet() + .stream() + .filter(arg -> imageName.contains(arg)) + .findFirst(); + if (imageBuildArg.isPresent()) { + String buildArg = imageBuildArg.get(); + return imageName.replaceAll("\\$\\{" + buildArg + "\\}", + Matcher.quoteReplacement(buildArgs.get(buildArg))); + } + else { + return imageName; + } + } + public ImageFromDockerfile withBuildArg(final String key, final String value) { this.buildArgs.put(key, value); return this; diff --git a/core/src/test/java/org/testcontainers/images/builder/DockerfileBuildTest.java b/core/src/test/java/org/testcontainers/images/builder/DockerfileBuildTest.java index 9a9d647d71b..d568cd54da6 100644 --- a/core/src/test/java/org/testcontainers/images/builder/DockerfileBuildTest.java +++ b/core/src/test/java/org/testcontainers/images/builder/DockerfileBuildTest.java @@ -52,6 +52,15 @@ public static Object[][] parameters() { .withFileFromPath(".", RESOURCE_PATH) .withDockerfile(RESOURCE_PATH.resolve("Dockerfile-alt")) }, + + // Dockerfile build using build args in FROM statements + new Object[]{"test1234", + new ImageFromDockerfile() + .withFileFromPath(".", RESOURCE_PATH) + .withDockerfile(RESOURCE_PATH.resolve("Dockerfile-from-buildarg")) + .withBuildArg("BUILD_IMAGE", "alpine:3.6") + .withBuildArg("BASE_IMAGE_TAG", "3.12") + }, }; } diff --git a/core/src/test/resources/dockerfile-build-test/Dockerfile-from-buildarg b/core/src/test/resources/dockerfile-build-test/Dockerfile-from-buildarg new file mode 100644 index 00000000000..b24eab4ce5f --- /dev/null +++ b/core/src/test/resources/dockerfile-build-test/Dockerfile-from-buildarg @@ -0,0 +1,8 @@ +ARG BUILD_IMAGE +ARG BASE_IMAGE_TAG + +FROM ${BUILD_IMAGE} AS build +COPY localfile.txt /test-build.txt + +FROM alpine:${BASE_IMAGE_TAG} AS base +COPY --from=build /test-build.txt /test.txt