or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

configuration.mdcontainer-lifecycle.mddocker-client.mddocker-compose.mdimage-building.mdimage-management.mdimage-pull-policies.mdindex.mdjunit-jupiter-integration.mdlifecycle.mdmodules-overview.mdnetwork-configuration.mdoutput-handling.mdstartup-checks.mdutility-classes.mdwait-strategies.md
tile.json

image-management.mddocs/

Image Management

Image pull policies and programmatic image building for Testcontainers. Provides control over when Docker images are pulled from registries and enables building custom images from Dockerfiles or using Google Jib.

See also:

  • Image Pull Policies - Detailed documentation on controlling image pulling behavior
  • Image Building - Programmatic Dockerfile construction and custom image building

Capabilities

RemoteDockerImage

Represents a Docker image that may need to be pulled from a registry.

/**
 * Represents a Docker image from a registry that will be pulled if needed.
 * Extends LazyFuture to support asynchronous image pulling.
 */
public class RemoteDockerImage extends LazyFuture<String> {
    /**
     * Create a remote Docker image reference.
     *
     * @param imageName the image name (e.g., "redis:7.0")
     * @deprecated Use {@link #RemoteDockerImage(DockerImageName)} instead
     */
    @Deprecated
    public RemoteDockerImage(String imageName);

    /**
     * Create a remote Docker image reference from repository and tag.
     *
     * @param repository the repository name
     * @param tag the image tag
     * @deprecated Use {@link #RemoteDockerImage(DockerImageName)} instead
     */
    @Deprecated
    public RemoteDockerImage(String repository, String tag);

    /**
     * Create a remote Docker image reference.
     *
     * @param imageName the parsed Docker image name
     */
    public RemoteDockerImage(DockerImageName imageName);

    /**
     * Create a remote Docker image reference from a Future.
     *
     * @param imageFuture future that resolves to an image name
     */
    public RemoteDockerImage(Future<String> imageFuture);

    /**
     * Set the image pull policy.
     *
     * @param imagePullPolicy the pull policy to use
     * @return this instance for method chaining
     */
    public RemoteDockerImage withImagePullPolicy(ImagePullPolicy imagePullPolicy);

    /**
     * Set the image name substitutor.
     *
     * @param imageNameSubstitutor the substitutor to use for transforming image names
     * @return this instance for method chaining
     */
    public RemoteDockerImage withImageNameSubstitutor(ImageNameSubstitutor imageNameSubstitutor);
}

Usage Example:

import org.testcontainers.images.RemoteDockerImage;
import org.testcontainers.utility.DockerImageName;

// Create a remote image reference
RemoteDockerImage image = new RemoteDockerImage(
    DockerImageName.parse("postgres:15-alpine")
);

// Use with GenericContainer
GenericContainer<?> container = new GenericContainer<>(image)
    .withExposedPorts(5432);

ImageFromDockerfile

Build a Docker image from a Dockerfile and use it in tests.

/**
 * Build a Docker image from a Dockerfile for use in tests.
 * Supports adding files from various sources and customizing the build.
 */
public class ImageFromDockerfile extends LazyFuture<String>
    implements BuildContextBuilderTrait, ClasspathTrait, FilesTrait,
               StringsTrait, DockerfileTrait {

    /**
     * Create an image builder with a temporary name.
     */
    public ImageFromDockerfile();

    /**
     * Create an image builder with a specific tag.
     *
     * @param imageTag the image tag (e.g., "myapp:test")
     */
    public ImageFromDockerfile(String imageTag);

    /**
     * Create an image builder with a tag and deletion policy.
     *
     * @param imageTag the image tag
     * @param deleteOnExit whether to delete the image when done
     */
    public ImageFromDockerfile(String imageTag, boolean deleteOnExit);

    /**
     * Set the Dockerfile path in the build context.
     *
     * @param path path to Dockerfile (relative to build context root)
     * @return this builder for method chaining
     * @deprecated Use {@link #withDockerfile(Path)} instead for better type safety
     */
    @Deprecated
    public ImageFromDockerfile withDockerfilePath(String path);

    /**
     * Set the Dockerfile using a Path object.
     *
     * @param dockerfile path to the Dockerfile
     * @return this builder for method chaining
     */
    public ImageFromDockerfile withDockerfile(Path dockerfile);

    /**
     * Add a file to the build context from a host path.
     *
     * @param containerPath path in build context (e.g., "app/config.json")
     * @param hostPath path on host filesystem
     * @return this builder for method chaining
     */
    public ImageFromDockerfile withFileFromPath(String containerPath, Path hostPath);

    /**
     * Add a file to the build context from a host path with specific file mode.
     *
     * @param path path in build context
     * @param filePath path on host filesystem
     * @param mode Unix file mode (e.g., 0755 for executable)
     * @return this builder for method chaining
     */
    public ImageFromDockerfile withFileFromPath(String path, Path filePath, Integer mode);

    /**
     * Add a file to the build context from a File object with specific file mode.
     *
     * @param path path in build context
     * @param file file to add
     * @param mode Unix file mode (e.g., 0755 for executable)
     * @return this builder for method chaining
     */
    public ImageFromDockerfile withFileFromFile(String path, File file, Integer mode);

    /**
     * Add a file to the build context from the classpath.
     *
     * @param containerPath path in build context
     * @param resourcePath classpath resource path
     * @return this builder for method chaining
     */
    public ImageFromDockerfile withFileFromClasspath(String containerPath, String resourcePath);

    /**
     * Add a file to the build context from a string.
     *
     * @param containerPath path in build context
     * @param content file content as string
     * @return this builder for method chaining
     */
    public ImageFromDockerfile withFileFromString(String containerPath, String content);

    /**
     * Add a file to the build context from a Transferable.
     *
     * @param containerPath path in build context
     * @param transferable transferable content
     * @return this builder for method chaining
     */
    public ImageFromDockerfile withFileFromTransferable(String containerPath, Transferable transferable);

    /**
     * Set a build argument.
     *
     * @param key argument name
     * @param value argument value
     * @return this builder for method chaining
     */
    public ImageFromDockerfile withBuildArg(String key, String value);

    /**
     * Set multiple build arguments.
     *
     * @param buildArgs map of build arguments
     * @return this builder for method chaining
     */
    public ImageFromDockerfile withBuildArgs(Map<String, String> buildArgs);

    /**
     * Set the build target for multi-stage Dockerfiles.
     *
     * @param target the target stage name
     * @return this builder for method chaining
     */
    public ImageFromDockerfile withTarget(String target);


    /**
     * Modify the Docker build command before execution.
     *
     * @param modifier consumer that modifies the BuildImageCmd
     * @return this builder for method chaining
     */
    public ImageFromDockerfile withBuildImageCmdModifier(Consumer<BuildImageCmd> modifier);
}

Usage Examples:

import org.testcontainers.images.builder.ImageFromDockerfile;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.utility.MountableFile;
import java.nio.file.Paths;

// Build from existing Dockerfile
ImageFromDockerfile simpleImage = new ImageFromDockerfile()
    .withDockerfilePath("Dockerfile")
    .withFileFromPath(".", Paths.get("./"));

GenericContainer<?> container1 = new GenericContainer<>(simpleImage)
    .withExposedPorts(8080);

// Build with inline Dockerfile (using withFileFromString for Dockerfile content)
ImageFromDockerfile inlineImage = new ImageFromDockerfile()
    .withFileFromString("Dockerfile",
        "FROM nginx:alpine\n" +
        "COPY index.html /usr/share/nginx/html/\n" +
        "EXPOSE 80"
    )
    .withFileFromClasspath("index.html", "web/index.html");

// Build with build arguments
ImageFromDockerfile withArgs = new ImageFromDockerfile("myapp:test", true)
    .withDockerfilePath("Dockerfile")
    .withBuildArg("VERSION", "1.0.0")
    .withBuildArg("ENVIRONMENT", "test")
    .withFileFromPath(".", Paths.get("./"));

// Multi-stage build targeting specific stage
ImageFromDockerfile multiStage = new ImageFromDockerfile()
    .withDockerfilePath("Dockerfile")
    .withTarget("development")
    .withFileFromPath(".", Paths.get("./"));

// Complex build with multiple files
ImageFromDockerfile complex = new ImageFromDockerfile("webapp:test")
    .withFileFromString("Dockerfile",
        "FROM openjdk:11-jre\n" +
        "WORKDIR /app\n" +
        "COPY app.jar .\n" +
        "COPY config.yml .\n" +
        "CMD [\"java\", \"-jar\", \"app.jar\"]"
    )
    .withFileFromPath("app.jar", Paths.get("target/app.jar"))
    .withFileFromString("config.yml", "port: 8080\nenv: test");

GenericContainer<?> app = new GenericContainer<>(complex)
    .withExposedPorts(8080);

DockerfileBuilder

Programmatically build Dockerfile content using a fluent API.

/**
 * Programmatic Dockerfile builder with fluent API.
 * Supports all standard Dockerfile instructions.
 */
public class DockerfileBuilder {
    /**
     * FROM instruction - set base image.
     *
     * @param baseImage the base image
     * @return this builder for method chaining
     */
    public DockerfileBuilder from(String baseImage);

    /**
     * RUN instruction - execute command during build.
     *
     * @param command the command to run
     * @return this builder for method chaining
     */
    public DockerfileBuilder run(String... command);

    /**
     * CMD instruction - default command to run.
     *
     * @param command the command
     * @return this builder for method chaining
     */
    public DockerfileBuilder cmd(String... command);

    /**
     * ENTRYPOINT instruction - executable to run.
     *
     * @param entrypoint the entrypoint
     * @return this builder for method chaining
     */
    public DockerfileBuilder entryPoint(String... entrypoint);

    /**
     * EXPOSE instruction - expose ports.
     *
     * @param ports the ports to expose
     * @return this builder for method chaining
     */
    public DockerfileBuilder expose(Integer... ports);

    /**
     * ENV instruction - set environment variable.
     *
     * @param key variable name
     * @param value variable value
     * @return this builder for method chaining
     */
    public DockerfileBuilder env(String key, String value);

    /**
     * ADD instruction - add file to image.
     *
     * @param source source path
     * @param destination destination path
     * @return this builder for method chaining
     */
    public DockerfileBuilder add(String source, String destination);

    /**
     * COPY instruction - copy file to image.
     *
     * @param source source path
     * @param destination destination path
     * @return this builder for method chaining
     */
    public DockerfileBuilder copy(String source, String destination);

    /**
     * VOLUME instruction - create mount point.
     *
     * @param volumes volume paths
     * @return this builder for method chaining
     */
    public DockerfileBuilder volume(String... volumes);

    /**
     * USER instruction - set user.
     *
     * @param user the user name or UID
     * @return this builder for method chaining
     */
    public DockerfileBuilder user(String user);

    /**
     * WORKDIR instruction - set working directory.
     *
     * @param workdir the working directory
     * @return this builder for method chaining
     */
    public DockerfileBuilder workDir(String workdir);

    /**
     * LABEL instruction - add metadata label.
     *
     * @param key label key
     * @param value label value
     * @return this builder for method chaining
     */
    public DockerfileBuilder label(String key, String value);

    /**
     * Build the Dockerfile as a string.
     *
     * @return the Dockerfile content
     */
    public String build();
}

Usage Example:

import org.testcontainers.images.builder.dockerfile.DockerfileBuilder;
import org.testcontainers.images.builder.ImageFromDockerfile;

// Build Dockerfile programmatically
String dockerfile = new DockerfileBuilder()
    .from("openjdk:11-jre")
    .workDir("/app")
    .copy("app.jar", ".")
    .expose(8080)
    .env("JAVA_OPTS", "-Xmx512m")
    .cmd("java", "-jar", "app.jar")
    .build();

// The build() method returns a String containing the generated Dockerfile:
// FROM openjdk:11-jre
// WORKDIR /app
// COPY app.jar .
// EXPOSE 8080
// ENV "JAVA_OPTS"="-Xmx512m"
// CMD ["java","-jar","app.jar"]

// Use with ImageFromDockerfile
ImageFromDockerfile image = new ImageFromDockerfile()
    .withFileFromString("Dockerfile", dockerfile)
    .withFileFromPath("app.jar", Paths.get("target/app.jar"));

GenericContainer<?> container = new GenericContainer<>(image)
    .withExposedPorts(8080);

Output Format Notes:

The build() method returns a String containing Dockerfile instructions. Note the following formatting:

  • ENV: Produces quoted format: ENV "KEY"="value"
  • LABEL: Produces quoted format: LABEL "key"="value"
  • CMD: Produces JSON array format: CMD ["executable","param1","param2"]
  • ENTRYPOINT: Produces JSON array format: ENTRYPOINT ["executable","param1"]
  • RUN: Single string arguments are used as-is; multiple arguments are formatted as shell commands
  • EXPOSE: Space-separated list of ports: EXPOSE 8080 8081
  • Other instructions (FROM, WORKDIR, USER, VOLUME, etc.): Standard Dockerfile format

Image Builder Traits

Testcontainers uses a trait-based design pattern for composable behavior in image builders. Traits are interfaces that add specific functionality through default methods.

ImageFromDockerfile Build Context Traits

These traits provide methods for adding files to the Docker build context.

BuildContextBuilderTrait

Base trait for adding files to build context from various sources.

/**
 * Base trait for BuildContextBuilder functionality.
 */
public interface BuildContextBuilderTrait<SELF extends BuildContextBuilderTrait<SELF>> {
    /**
     * Add a file to the build context from a Transferable.
     *
     * @param path path in the build context
     * @param transferable the transferable content
     * @return this builder for method chaining
     */
    SELF withFileFromTransferable(String path, Transferable transferable);
}

ClasspathTrait

Add files from Java classpath resources.

/**
 * Trait for adding classpath resources to build context.
 */
public interface ClasspathTrait<SELF extends ClasspathTrait<SELF>
    & BuildContextBuilderTrait<SELF> & FilesTrait<SELF>> {

    /**
     * Add a file from classpath to the build context.
     *
     * @param path destination path in build context
     * @param resourcePath classpath resource path
     * @return this builder for method chaining
     */
    default SELF withFileFromClasspath(String path, String resourcePath);
}

Usage:

new ImageFromDockerfile()
    .withFileFromClasspath("config.json", "/resources/config.json")

FilesTrait

Add files from filesystem paths.

/**
 * Trait for adding files from filesystem to build context.
 */
public interface FilesTrait<SELF extends FilesTrait<SELF> & BuildContextBuilderTrait<SELF>> {
    /**
     * Add a file from filesystem path to the build context.
     *
     * @param path destination path in build context
     * @param filePath source file path
     * @return this builder for method chaining
     */
    default SELF withFileFromPath(String path, Path filePath);
}

Usage:

new ImageFromDockerfile()
    .withFileFromPath("app.jar", Paths.get("target/app.jar"))

StringsTrait

Add files from string content.

/**
 * Trait for adding string content as files to build context.
 */
public interface StringsTrait<SELF extends StringsTrait<SELF> & BuildContextBuilderTrait<SELF>> {
    /**
     * Add a file from string content to the build context.
     *
     * @param path destination path in build context
     * @param content string content
     * @return this builder for method chaining
     */
    default SELF withFileFromString(String path, String content);
}

Usage:

new ImageFromDockerfile()
    .withFileFromString("Dockerfile", "FROM nginx:latest\nCOPY index.html /usr/share/nginx/html/")

DockerfileTrait

Add or customize Dockerfile content.

/**
 * Trait for working with Dockerfiles.
 */
public interface DockerfileTrait<SELF extends DockerfileTrait<SELF> & StringsTrait<SELF> & BuildContextBuilderTrait<SELF>> {
    /**
     * Set the Dockerfile path (relative to build context).
     *
     * @param relativePathFromBuildRoot path to Dockerfile
     * @return this builder for method chaining
     * @deprecated Use withDockerfile(Path) instead
     */
    @Deprecated
    SELF withDockerfilePath(String relativePathFromBuildRoot);

    /**
     * Provide Dockerfile content from a Consumer that uses DockerfileBuilder.
     *
     * @param builderConsumer consumer that builds Dockerfile programmatically
     * @return this builder for method chaining
     */
    default SELF withDockerfileFromBuilder(Consumer<DockerfileBuilder> builderConsumer);
}

Usage:

new ImageFromDockerfile()
    .withDockerfileFromBuilder(builder -> builder
        .from("openjdk:11-jre")
        .copy("app.jar", "/app/")
        .cmd("java", "-jar", "/app/app.jar")
    )

DockerfileBuilder Statement Traits

These traits provide Dockerfile instruction methods for DockerfileBuilder.

FromStatementTrait

public interface FromStatementTrait<SELF extends FromStatementTrait<SELF> & DockerfileBuilderTrait<SELF>> {
    /**
     * Add FROM instruction.
     * @param dockerImageName base image name
     */
    default SELF from(String dockerImageName);
}

RunStatementTrait

public interface RunStatementTrait<SELF extends RunStatementTrait<SELF> & DockerfileBuilderTrait<SELF>> {
    /**
     * Add RUN instruction (exec form).
     * @param commandParts the command parts
     */
    default SELF run(String... commandParts);

    /**
     * Add RUN instruction (shell form).
     * @param command the shell command
     */
    default SELF run(String command);
}

CmdStatementTrait

public interface CmdStatementTrait<SELF extends CmdStatementTrait<SELF> & DockerfileBuilderTrait<SELF>> {
    /**
     * Add CMD instruction (shell form).
     * @param command the shell command
     */
    default SELF cmd(String command);

    /**
     * Add CMD instruction (exec form).
     * @param commandParts command arguments
     */
    default SELF cmd(String... commandParts);
}

EntryPointStatementTrait

public interface EntryPointStatementTrait<SELF extends EntryPointStatementTrait<SELF> & DockerfileBuilderTrait<SELF>> {
    /**
     * Add ENTRYPOINT instruction (shell form).
     * @param command the shell command
     */
    default SELF entryPoint(String command);

    /**
     * Add ENTRYPOINT instruction (exec form).
     * @param commandParts entrypoint arguments
     */
    default SELF entryPoint(String... commandParts);
}

ExposeStatementTrait

public interface ExposeStatementTrait<SELF extends ExposeStatementTrait<SELF> & DockerfileBuilderTrait<SELF>> {
    /**
     * Add EXPOSE instruction.
     * @param ports ports to expose
     */
    default SELF expose(Integer... ports);
}

EnvStatementTrait

public interface EnvStatementTrait<SELF extends EnvStatementTrait<SELF> & DockerfileBuilderTrait<SELF>> {
    /**
     * Add ENV instruction.
     * @param key environment variable name
     * @param value environment variable value
     */
    default SELF env(String key, String value);
}

AddStatementTrait

public interface AddStatementTrait<SELF extends AddStatementTrait<SELF> & DockerfileBuilderTrait<SELF>> {
    /**
     * Add ADD instruction.
     * @param source source path
     * @param destination destination path
     */
    default SELF add(String source, String destination);
}

CopyStatementTrait

public interface CopyStatementTrait<SELF extends CopyStatementTrait<SELF> & DockerfileBuilderTrait<SELF>> {
    /**
     * Add COPY instruction.
     * @param source source path
     * @param destination destination path
     */
    default SELF copy(String source, String destination);
}

VolumeStatementTrait

public interface VolumeStatementTrait<SELF extends VolumeStatementTrait<SELF> & DockerfileBuilderTrait<SELF>> {
    /**
     * Add VOLUME instruction.
     * @param volumes volume mount points
     */
    default SELF volume(String... volumes);
}

UserStatementTrait

public interface UserStatementTrait<SELF extends UserStatementTrait<SELF> & DockerfileBuilderTrait<SELF>> {
    /**
     * Add USER instruction.
     * @param user username or UID
     */
    default SELF user(String user);
}

WorkdirStatementTrait

public interface WorkdirStatementTrait<SELF extends WorkdirStatementTrait<SELF> & DockerfileBuilderTrait<SELF>> {
    /**
     * Add WORKDIR instruction.
     * @param workDir working directory path
     */
    default SELF workDir(String workDir);
}

LabelStatementTrait

public interface LabelStatementTrait<SELF extends LabelStatementTrait<SELF> & DockerfileBuilderTrait<SELF>> {
    /**
     * Add LABEL instruction.
     * @param key label key
     * @param value label value
     */
    default SELF label(String key, String value);
}

Trait Composition Example

// ImageFromDockerfile implements all build context traits
ImageFromDockerfile image = new ImageFromDockerfile()
    // StringsTrait
    .withFileFromString("Dockerfile", "...")
    // ClasspathTrait
    .withFileFromClasspath("config.yml", "/config.yml")
    // FilesTrait
    .withFileFromPath("app.jar", Paths.get("target/app.jar"))
    // BuildContextBuilderTrait
    .withFileFromTransferable("script.sh", Transferable.of("#!/bin/bash\necho hello"));

// DockerfileBuilder implements all statement traits
String dockerfile = new DockerfileBuilder()
    // FromStatementTrait
    .from("openjdk:11-jre")
    // WorkdirStatementTrait
    .workdir("/app")
    // CopyStatementTrait
    .copy("app.jar", ".")
    // EnvStatementTrait
    .env("JAVA_OPTS", "-Xmx512m")
    // ExposeStatementTrait
    .expose(8080)
    // CmdStatementTrait
    .cmd("java", "-jar", "app.jar")
    .build();

Transferable Interface

The Transferable interface provides a flexible way to add content to Docker build contexts with precise control over file permissions.

/**
 * Represents content that can be transferred into a container or Docker build context.
 * Supports both file and byte array content with customizable Unix file permissions.
 */
public interface Transferable {
    /**
     * Default file mode for regular files (0644 = rw-r--r--).
     */
    int DEFAULT_FILE_MODE = 0100644;

    /**
     * Default directory mode (040755 = rwxr-xr-x).
     */
    int DEFAULT_DIR_MODE = 040755;

    /**
     * Create a Transferable from string content with default file permissions.
     *
     * @param string the string content
     * @return Transferable instance with default file mode
     */
    static Transferable of(String string);

    /**
     * Create a Transferable from string content with custom file permissions.
     *
     * @param string the string content
     * @param mode Unix file mode (e.g., 0755 for executable)
     * @return Transferable instance with specified mode
     */
    static Transferable of(String string, int mode);

    /**
     * Create a Transferable from byte array with default file permissions.
     *
     * @param bytes the byte array content
     * @return Transferable instance with default file mode
     */
    static Transferable of(byte[] bytes);

    /**
     * Create a Transferable from byte array with custom file permissions.
     *
     * @param bytes the byte array content
     * @param mode Unix file mode (e.g., 0755 for executable)
     * @return Transferable instance with specified mode
     */
    static Transferable of(byte[] bytes, int mode);

    /**
     * Get the file mode for this transferable.
     *
     * @return Unix file mode
     */
    int getFileMode();

    /**
     * Get the size of the content in bytes.
     *
     * @return size in bytes
     */
    long getSize();

    /**
     * Get the content as a byte array.
     * Default implementation returns empty byte array.
     *
     * @return byte array of the content
     */
    default byte[] getBytes();

    /**
     * Get a human-readable description of this transferable.
     * Default implementation returns empty string.
     *
     * @return description string
     */
    default String getDescription();
}

Usage Examples:

import org.testcontainers.images.builder.Transferable;
import org.testcontainers.images.builder.ImageFromDockerfile;

// Create executable script with custom permissions
Transferable script = Transferable.of(
    "#!/bin/bash\necho 'Hello from script'",
    0755  // Make executable
);

ImageFromDockerfile image = new ImageFromDockerfile()
    .withFileFromString("Dockerfile",
        "FROM ubuntu:22.04\n" +
        "COPY startup.sh /usr/local/bin/\n" +
        "CMD [\"/usr/local/bin/startup.sh\"]"
    )
    .withFileFromTransferable("startup.sh", script);

// Create read-only configuration file
Transferable config = Transferable.of(
    "setting1=value1\nsetting2=value2",
    0444  // Read-only
);

// Use default permissions (0644)
Transferable readme = Transferable.of("# README\nProject documentation");

// Binary content with custom mode
byte[] binaryData = loadBinaryData();
Transferable binary = Transferable.of(binaryData, 0755);

File Mode Reference:

Common Unix file modes (octal notation):

  • 0644 (rw-r--r--) - Default for regular files, owner can write
  • 0755 (rwxr-xr-x) - Executable files, owner can write
  • 0444 (r--r--r--) - Read-only for all users
  • 0600 (rw-------) - Private file, only owner can read/write
  • 0777 (rwxrwxrwx) - Full permissions for all (use with caution)

Image Pull Policies

Control when Docker images are pulled from registries.

/**
 * Policy interface for determining when images should be pulled.
 */
public interface ImagePullPolicy {
    /**
     * Determine if an image should be pulled.
     *
     * @param imageData metadata about the image
     * @return true if the image should be pulled
     */
    boolean shouldPull(DockerImageName imageName);
}

/**
 * Image metadata for pull policy decisions.
 * Generated by Lombok @Value and @Builder annotations.
 * Only contains creation timestamp; image name is passed separately.
 */
@Value
@Builder
public class ImageData {
    /**
     * Get when the image was created.
     * Field is accessible via Lombok-generated getter.
     *
     * @return image creation timestamp
     */
    public Instant getCreatedAt();

    /**
     * Get a builder for creating ImageData instances.
     * Generated by Lombok @Builder annotation.
     *
     * @return Builder for ImageData
     */
    public static ImageDataBuilder builder();

    /**
     * Create ImageData from Docker inspect response.
     * NOTE: This is a package-private internal API, not part of the public API.
     *
     * @param inspectImageResponse Docker image inspection response
     * @return ImageData instance
     */
    static ImageData from(InspectImageResponse inspectImageResponse);

    /**
     * Create ImageData from Docker image object.
     * NOTE: This is a package-private internal API, not part of the public API.
     *
     * @param image Docker image object
     * @return ImageData instance
     */
    static ImageData from(Image image);
}

PullPolicy Factory

Factory class for creating common pull policies.

/**
 * Factory for creating image pull policies.
 */
public class PullPolicy {
    /**
     * Get the default pull policy.
     * Pulls if image doesn't exist locally or has no version tag.
     *
     * @return default pull policy
     */
    public static ImagePullPolicy defaultPolicy();

    /**
     * Always pull images from registry.
     *
     * @return always pull policy
     */
    public static ImagePullPolicy alwaysPull();

    /**
     * Pull images older than the specified age.
     *
     * @param maxAge maximum age before pulling
     * @return age-based pull policy
     */
    public static ImagePullPolicy ageBased(Duration maxAge);
}

Usage Examples:

import org.testcontainers.containers.GenericContainer;
import org.testcontainers.images.PullPolicy;
import org.testcontainers.utility.DockerImageName;
import java.time.Duration;

// Use default policy
GenericContainer<?> container1 = new GenericContainer<>(DockerImageName.parse("redis:7.0"))
    .withImagePullPolicy(PullPolicy.defaultPolicy());

// Always pull fresh image
GenericContainer<?> container2 = new GenericContainer<>(DockerImageName.parse("nginx:latest"))
    .withImagePullPolicy(PullPolicy.alwaysPull());

// Pull if image is older than 7 days
GenericContainer<?> container3 = new GenericContainer<>(DockerImageName.parse("postgres:15"))
    .withImagePullPolicy(PullPolicy.ageBased(Duration.ofDays(7)));

Built-in Pull Policy Implementations

NOTE: The following classes (DefaultPullPolicy, AlwaysPullPolicy, AgeBasedPullPolicy) are package-private implementation classes used internally by the PullPolicy factory. They are not part of the public API. Use the factory methods in PullPolicy class instead (e.g., PullPolicy.defaultPolicy(), PullPolicy.alwaysPull(), PullPolicy.ageBased()).

/**
 * Default pull policy implementation.
 * Pulls images without a version tag or if not present locally.
 * Package-private - use PullPolicy.defaultPolicy() instead.
 */
class DefaultPullPolicy extends AbstractImagePullPolicy {
    @Override
    public boolean shouldPull(DockerImageName imageName);

    @Override
    protected boolean shouldPullCached(DockerImageName imageName, ImageData localImageData);
}

/**
 * Always pull images from registry.
 * Package-private - use PullPolicy.alwaysPull() instead.
 */
class AlwaysPullPolicy implements ImagePullPolicy {
    @Override
    public boolean shouldPull(DockerImageName imageName);
}

/**
 * Pull images based on age threshold.
 * Package-private - use PullPolicy.ageBased(Duration) instead.
 */
class AgeBasedPullPolicy extends AbstractImagePullPolicy {
    /**
     * Create an age-based pull policy.
     *
     * @param maxAge maximum age before pulling
     */
    public AgeBasedPullPolicy(Duration maxAge);

    @Override
    public boolean shouldPull(DockerImageName imageName);

    @Override
    protected boolean shouldPullCached(DockerImageName imageName, ImageData localImageData);
}

/**
 * Abstract base class for custom pull policies.
 */
public abstract class AbstractImagePullPolicy implements ImagePullPolicy {
    @Override
    public boolean shouldPull(DockerImageName imageName);

    /**
     * Decide whether to pull an image that exists locally.
     * Override this method in custom policies to implement custom pull logic.
     *
     * @param imageName the Docker image name
     * @param localImageData metadata about the locally available image
     * @return true if the locally available image should be pulled again
     */
    protected abstract boolean shouldPullCached(DockerImageName imageName, ImageData localImageData);
}

Custom Pull Policy Example:

import org.testcontainers.images.AbstractImagePullPolicy;
import org.testcontainers.images.ImageData;
import java.time.Duration;
import java.time.Instant;

// Custom policy: pull development images daily, production images weekly
public class EnvironmentBasedPullPolicy extends AbstractImagePullPolicy {
    @Override
    protected boolean shouldPullCached(DockerImageName imageName, ImageData imageData) {
        String tag = imageName.getVersionPart();
        Instant createdAt = imageData.getCreatedAt();
        Instant now = Instant.now();

        if (tag.contains("dev") || tag.contains("snapshot")) {
            // Pull if older than 1 day
            return Duration.between(createdAt, now).compareTo(Duration.ofDays(1)) > 0;
        } else {
            // Pull if older than 7 days
            return Duration.between(createdAt, now).compareTo(Duration.ofDays(7)) > 0;
        }
    }
}

// Usage
GenericContainer<?> container = new GenericContainer<>(DockerImageName.parse("myapp:dev"))
    .withImagePullPolicy(new EnvironmentBasedPullPolicy());

JibImage

Build images using Google Jib (Java Image Builder) for Java applications.

/**
 * Build container images using Google Jib.
 * Provides faster builds and better layer optimization for Java apps.
 */
public class JibImage extends LazyFuture<String> {
    /**
     * Create a Jib image builder.
     *
     * @param baseImage the base image name
     * @param jibContainerBuilderFn function to configure the Jib container builder
     */
    public JibImage(String baseImage, Function<JibContainerBuilder, JibContainerBuilder> jibContainerBuilderFn);
}

Usage Example:

import org.testcontainers.jib.JibImage;
import org.testcontainers.containers.GenericContainer;
import com.google.cloud.tools.jib.api.Jib;
import com.google.cloud.tools.jib.api.buildplan.AbsoluteUnixPath;
import java.nio.file.Paths;
import java.util.List;

// Build Java application image with Jib
JibImage jibImage = new JibImage(
    "eclipse-temurin:11-jre",
    builder -> builder
        .addLayer(
            List.of(Paths.get("target/app.jar")),
            AbsoluteUnixPath.get("/app/app.jar")
        )
        .setEntrypoint("java", "-jar", "/app/app.jar")
        .addExposedPort(8080)
);

GenericContainer<?> container = new GenericContainer<>(jibImage)
    .withExposedPorts(8080);

ParsedDockerfile

Parse and analyze Dockerfile content to extract metadata such as base image dependencies.

/**
 * Representation of a Dockerfile, with partial parsing for extraction of a minimal set of data.
 */
@Slf4j
public class ParsedDockerfile {
    /**
     * Constructor that parses a Dockerfile from a path.
     *
     * @param dockerFilePath path to the Dockerfile
     */
    public ParsedDockerfile(Path dockerFilePath);

    /**
     * Get all base images referenced in the Dockerfile FROM statements.
     *
     * @return set of dependency image names as strings
     */
    public Set<String> getDependencyImageNames();
}

Usage Example:

// Parse a Dockerfile to extract dependencies
Path dockerfilePath = Paths.get("./Dockerfile");
ParsedDockerfile parsed = new ParsedDockerfile(dockerfilePath);

// Get all base images from FROM statements
Set<String> baseImages = parsed.getDependencyImageNames();
System.out.println("Base images: " + baseImages);
// Output: Base images: [openjdk:11-jre, nginx:alpine]

Image Pull Callbacks

Testcontainers provides specialized callbacks for monitoring and controlling image pull operations.

LoggedPullImageResultCallback

Callback with improved logging of pull progress, showing layer download status and statistics.

/**
 * PullImageResultCallback with improved logging of pull progress.
 * Package-private - used internally by Testcontainers.
 */
class LoggedPullImageResultCallback extends PullImageResultCallback {
    /**
     * Constructor with logger.
     *
     * @param logger the logger to use for progress messages
     */
    LoggedPullImageResultCallback(Logger logger);

    @Override
    public void onStart(Closeable stream);

    @Override
    public void onNext(PullResponseItem item);

    @Override
    public void onComplete();
}

Features:

  • Logs layer download progress with detailed statistics
  • Tracks pending, downloaded, and extracted layers
  • Shows download speed and total size
  • Provides human-readable progress messages

TimeLimitedLoggedPullImageResultCallback

Enhanced pull callback with a watchdog timer to prevent hanging pulls.

/**
 * PullImageResultCallback with improved logging of pull progress and a 'watchdog'
 * which will abort the pull if progress is not being made, to prevent a hanging test.
 */
public class TimeLimitedLoggedPullImageResultCallback extends LoggedPullImageResultCallback {
    /**
     * Constructor with logger.
     *
     * @param logger the logger to use for progress messages
     */
    public TimeLimitedLoggedPullImageResultCallback(Logger logger);

    @Override
    public TimeLimitedLoggedPullImageResultCallback awaitCompletion() throws InterruptedException;

    @Override
    public boolean awaitCompletion(long timeout, TimeUnit timeUnit) throws InterruptedException;

    @Override
    public void onNext(PullResponseItem item);

    @Override
    public void onStart(Closeable stream);

    @Override
    public void onError(Throwable throwable);

    @Override
    public void onComplete();
}

Features:

  • All features of LoggedPullImageResultCallback
  • Watchdog timer to detect stalled pulls (default: 30 seconds of no progress)
  • Automatically aborts pull and interrupts waiting threads on timeout
  • Configurable timeout via testcontainers.pull.pause.timeout property
  • Prevents tests from hanging indefinitely on network issues

Usage Note:

These callbacks are used internally by Testcontainers when pulling images. The timeout behavior can be configured:

// Configure pull pause timeout in testcontainers.properties:
// testcontainers.pull.pause.timeout=60

// Or via system property:
System.setProperty("testcontainers.pull.pause.timeout", "60");

Complete Usage Example

import org.testcontainers.containers.GenericContainer;
import org.testcontainers.images.builder.ImageFromDockerfile;
import org.testcontainers.images.builder.dockerfile.DockerfileBuilder;
import org.testcontainers.images.PullPolicy;
import org.testcontainers.utility.DockerImageName;
import java.nio.file.Paths;
import java.time.Duration;

public class ImageManagementExample {

    public void testWithCustomImage() {
        // Build custom image with inline Dockerfile
        String dockerfile = new DockerfileBuilder()
            .from("nginx:alpine")
            .copy("nginx.conf", "/etc/nginx/nginx.conf")
            .copy("html", "/usr/share/nginx/html")
            .expose(80)
            .build();

        ImageFromDockerfile customImage = new ImageFromDockerfile("test-nginx:latest", true)
            .withFileFromString("Dockerfile", dockerfile)
            .withFileFromClasspath("nginx.conf", "nginx/nginx.conf")
            .withFileFromPath("html", Paths.get("src/test/resources/html"));

        GenericContainer<?> nginx = new GenericContainer<>(customImage)
            .withExposedPorts(80);

        nginx.start();
        // Use container
        nginx.stop();
    }

    public void testWithPullPolicies() {
        // Production container - use cached images
        GenericContainer<?> database = new GenericContainer<>(
                DockerImageName.parse("postgres:15.2"))
            .withImagePullPolicy(PullPolicy.defaultPolicy())
            .withExposedPorts(5432);

        // Development container - always pull latest
        GenericContainer<?> devApp = new GenericContainer<>(
                DockerImageName.parse("myapp:dev"))
            .withImagePullPolicy(PullPolicy.alwaysPull())
            .withExposedPorts(8080);

        // Test container - pull if older than 3 days
        GenericContainer<?> testApp = new GenericContainer<>(
                DockerImageName.parse("myapp:test"))
            .withImagePullPolicy(PullPolicy.ageBased(Duration.ofDays(3)))
            .withExposedPorts(8080);
    }

    public void testMultiStageDockerfile() {
        // Build from multi-stage Dockerfile, targeting specific stage
        ImageFromDockerfile devImage = new ImageFromDockerfile()
            .withDockerfilePath("Dockerfile")
            .withTarget("development")
            .withBuildArg("BUILD_ENV", "test")
            .withFileFromPath(".", Paths.get("."));

        GenericContainer<?> container = new GenericContainer<>(devImage)
            .withExposedPorts(8080, 9090);

        container.start();
    }
}