Skip to content

Commit ed5b8a1

Browse files
committed
Add replacement of build args in Dockerfile FROM statements
1 parent f47b078 commit ed5b8a1

File tree

3 files changed

+48
-5
lines changed

3 files changed

+48
-5
lines changed

core/src/main/java/org/testcontainers/images/builder/ImageFromDockerfile.java

+19-3
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import java.util.Map;
3636
import java.util.Optional;
3737
import java.util.Set;
38+
import java.util.regex.Matcher;
3839
import java.util.zip.GZIPOutputStream;
3940

4041
@Slf4j
@@ -185,24 +186,39 @@ protected void configure(BuildImageCmd buildImageCmd) {
185186

186187
private void prePullDependencyImages(Set<String> imagesToPull) {
187188
imagesToPull.forEach(imageName -> {
189+
String resolvedImageName = applyBuildArgsToImageName(imageName);
188190
try {
189191
log.info(
190192
"Pre-emptively checking local images for '{}', referenced via a Dockerfile. If not available, it will be pulled.",
191-
imageName
193+
resolvedImageName
192194
);
193-
new RemoteDockerImage(DockerImageName.parse(imageName))
195+
new RemoteDockerImage(DockerImageName.parse(resolvedImageName))
194196
.withImageNameSubstitutor(ImageNameSubstitutor.noop())
195197
.get();
196198
} catch (Exception e) {
197199
log.warn(
198200
"Unable to pre-fetch an image ({}) depended upon by Dockerfile - image build will continue but may fail. Exception message was: {}",
199-
imageName,
201+
resolvedImageName,
200202
e.getMessage()
201203
);
202204
}
203205
});
204206
}
205207

208+
/**
209+
* See {@code filterForEnvironmentVars()} in {@link com.github.dockerjava.core.dockerfile.DockerfileStatement}.
210+
*/
211+
private String applyBuildArgsToImageName(String imageName) {
212+
for (Map.Entry<String, String> entry : buildArgs.entrySet()) {
213+
String value = Matcher.quoteReplacement(entry.getValue());
214+
// handle: $VARIABLE case
215+
imageName = imageName.replace("$" + entry.getKey(), value);
216+
// handle ${VARIABLE} case
217+
imageName = imageName.replace("${" + entry.getKey() + "}", value);
218+
}
219+
return imageName;
220+
}
221+
206222
public ImageFromDockerfile withBuildArg(final String key, final String value) {
207223
this.buildArgs.put(key, value);
208224
return this;

core/src/test/java/org/testcontainers/images/builder/DockerfileBuildTest.java

+20-2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
import java.nio.file.Path;
1010
import java.nio.file.Paths;
11+
import java.util.HashMap;
12+
import java.util.Map;
1113

1214
import static org.assertj.core.api.Assertions.assertThat;
1315

@@ -22,6 +24,13 @@ public class DockerfileBuildTest {
2224

2325
@Parameterized.Parameters
2426
public static Object[][] parameters() {
27+
Map<String, String> buildArgs = new HashMap<>(4);
28+
buildArgs.put("BUILD_IMAGE", "alpine:3.16");
29+
buildArgs.put("BASE_IMAGE", "alpine");
30+
buildArgs.put("BASE_IMAGE_TAG", "3.12");
31+
buildArgs.put("UNUSED", "ignored");
32+
33+
//noinspection deprecation
2534
return new Object[][] {
2635
// Dockerfile build without explicit per-file inclusion
2736
new Object[] {
@@ -38,14 +47,22 @@ public static Object[][] parameters() {
3847
"test4567",
3948
new ImageFromDockerfile().withFileFromPath(".", RESOURCE_PATH).withDockerfilePath("./Dockerfile-alt"),
4049
},
41-
// Dockerfile build using build args
50+
// Dockerfile build using withBuildArg()
4251
new Object[] {
4352
"test7890",
4453
new ImageFromDockerfile()
4554
.withFileFromPath(".", RESOURCE_PATH)
4655
.withDockerfilePath("./Dockerfile-buildarg")
4756
.withBuildArg("CUSTOM_ARG", "test7890"),
4857
},
58+
// Dockerfile build using withBuildArgs() with build args in FROM statement
59+
new Object[] {
60+
"test1234",
61+
new ImageFromDockerfile()
62+
.withFileFromPath(".", RESOURCE_PATH)
63+
.withDockerfile(RESOURCE_PATH.resolve("Dockerfile-from-buildarg"))
64+
.withBuildArgs(buildArgs),
65+
},
4966
// Dockerfile build using withDockerfile(File)
5067
new Object[] {
5168
"test4567",
@@ -62,9 +79,10 @@ public DockerfileBuildTest(String expectedFileContent, ImageFromDockerfile image
6279
}
6380

6481
@Test
82+
@SuppressWarnings("resource")
6583
public void performTest() {
6684
try (
67-
final GenericContainer container = new GenericContainer(image)
85+
final GenericContainer<?> container = new GenericContainer<>(image)
6886
.withStartupCheckStrategy(new OneShotStartupCheckStrategy())
6987
.withCommand("cat", "/test.txt")
7088
) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
ARG BUILD_IMAGE
2+
ARG BASE_IMAGE
3+
ARG BASE_IMAGE_TAG
4+
5+
FROM ${BUILD_IMAGE} AS build
6+
COPY localfile.txt /test-build.txt
7+
8+
FROM $BASE_IMAGE:${BASE_IMAGE_TAG} AS base
9+
COPY --from=build /test-build.txt /test.txt

0 commit comments

Comments
 (0)