## File: README.md

# Testcontainers



[](https://app.netlify.com/sites/testcontainers/deploys)

[](https://github.com/codespaces/new?hide_repo_select=true&ref=main&repo=33816473&machine=standardLinux32gb&devcontainer_path=.devcontainer%2Fdevcontainer.json&location=EastUs)

[](https://community.develocity.cloud/scans?search.rootProjectNames=testcontainers-java)

> Testcontainers is a Java library that supports JUnit tests, providing lightweight, throwaway instances of common databases, Selenium web browsers, or anything else that can run in a Docker container.



# [Read the documentation here](https://java.testcontainers.org)

## License

See [LICENSE](LICENSE).

## Copyright

Copyright (c) 2015 - 2021 Richard North and other authors.

MS SQL Server module is (c) 2017 - 2021 G DATA Software AG and other authors.

Hashicorp Vault module is (c) 2017 - 2021 Capital One Services, LLC and other authors.

See [contributors](https://github.com/testcontainers/testcontainers-java/graphs/contributors) for all contributors.

---

## File: core/testlib/README.md

This directory contains a synthetic JAR (`fakejar.jar`) that is needed for `org.testcontainers.utility.MountableFileTest`.

The `create_fakejar.sh` script may be used to recreate it.

---

## File: docs/features/advanced_options.md

# Advanced options

## Container labels

To add a custom label to the container, use `withLabel`:


[Adding a single label](../examples/junit4/generic/src/test/java/generic/ContainerLabelTest.java) inside_block:single_label


Additionally, multiple labels may be applied together from a map:


[Adding multiple labels](../examples/junit4/generic/src/test/java/generic/ContainerLabelTest.java) inside_block:multiple_labels


## Image Pull Policy

By default, the container image is retrieved from the local Docker images cache.
This works well when running against a specific version, but for images with a static tag (i.e. 'latest') this may lead to a newer version not being pulled.

It is possible to specify an Image Pull Policy to determine at runtime whether an image should be pulled or not:


[Setting image pull policy](../../core/src/test/java/org/testcontainers/images/ImagePullPolicyTest.java) inside_block:built_in_image_pull_policy


... or providing a function:


[Custom image pull policy](../../core/src/test/java/org/testcontainers/images/ImagePullPolicyTest.java) inside_block:custom_image_pull_policy


You can also configure Testcontainers to use your custom implementation by using `pull.policy`

=== "`src/test/resources/testcontainers.properties`"
    ```text
    pull.policy=com.mycompany.testcontainers.ExampleImagePullPolicy
    ```

You can also use the provided implementation to always pull images

=== "`src/test/resources/testcontainers.properties`"
    ```text
    pull.policy=org.testcontainers.images.AlwaysPullPolicy
    ```


Please see [the documentation on configuration mechanisms](./configuration.md) for more information.

## Customizing the container

### Using docker-java

It is possible to use the [`docker-java`](https://github.com/docker-java/docker-java) API directly to customize containers before creation. This is useful if there is a need to use advanced Docker features that are not exposed by the Testcontainers API. Any customizations you make using `withCreateContainerCmdModifier` will be applied _on top_ of the container definition that Testcontainers creates, but before it is created.

For example, this can be used to change the container hostname:


[Using modifier to change hostname](../examples/junit4/generic/src/test/java/generic/CmdModifierTest.java) inside_block:hostname


... or modify container memory (see [this](https://fabiokung.com/2014/03/13/memory-inside-linux-containers/) if it does not appear to work):


[Using modifier to change memory limits](../examples/junit4/generic/src/test/java/generic/CmdModifierTest.java) inside_block:memory


!!! note
    It is recommended to use this sparingly, and follow changes to the `docker-java` API if you choose to use this. 
    It is typically quite stable, though.

For what is possible, consult the [`docker-java CreateContainerCmd` source code](https://github.com/docker-java/docker-java/blob/3.2.1/docker-java-api/src/main/java/com/github/dockerjava/api/command/CreateContainerCmd.java).

### Using CreateContainerCmdModifier

Testcontainers provides a `CreateContainerCmdModifier` to customize [`docker-java CreateContainerCmd`](https://github.com/docker-java/docker-java/blob/3.2.1/docker-java-api/src/main/java/com/github/dockerjava/api/command/CreateContainerCmd.java)
via Service Provider Interface (SPI) mechanism.


[CreateContainerCmd example implementation](../../core/src/test/java/org/testcontainers/custom/TestCreateContainerCmdModifier.java)


The previous implementation should be registered in `META-INF/services/org.testcontainers.core.CreateContainerCmdModifier` file.

!!! warning
    `CreateContainerCmdModifier` implementation will apply to all containers created by Testcontainers.

## Parallel Container Startup

Usually, containers are started sequentially when more than one container is used.
Using `Startables.deepStart(container1, container2, ...).join()` will start all containers in parallel. 
This can be advantageous to reduce the impact of the container startup overhead.

---

## File: docs/features/commands.md

# Executing commands

## Container startup command

By default the container will execute whatever command is specified in the image's Dockerfile. To override this, and specify a different command, use `withCommand`. For example:


[Specifying a startup command](../examples/junit4/generic/src/test/java/generic/CommandsTest.java) inside_block:startupCommand


## Executing a command

Your test can execute a command inside a running container, similar to a `docker exec` call:


[Executing a command inside a running container](../examples/junit4/generic/src/test/java/generic/ExecTest.java) inside_block:standaloneExec


This can be useful for software that has a command line administration tool. You can also get the output (stdout/stderr) and exit code from the command - for example:


[Executing a command inside a running container and reading the result](../examples/junit4/generic/src/test/java/generic/ExecTest.java) inside_block:execReadingStdout


## Environment variables

To add environment variables to the container, use `withEnv`:
```java
new GenericContainer(...)
		.withEnv("API_TOKEN", "foo")
```

---

## File: docs/features/configuration.md

# Custom configuration

You can override some default properties if your environment requires that.

## Configuration locations
The configuration will be loaded from multiple locations. Properties are considered in the following order:

1. Environment variables
2. `.testcontainers.properties` in user's home folder. Example locations:  
**Linux:** `/home/myuser/.testcontainers.properties`  
**Windows:** `C:/Users/myuser/.testcontainers.properties`  
**macOS:** `/Users/myuser/.testcontainers.properties`
3. `testcontainers.properties` on the classpath.

Note that when using environment variables, configuration property names should be set in upper 
case with underscore separators, preceded by `TESTCONTAINERS_` - e.g. `checks.disable` becomes 
`TESTCONTAINERS_CHECKS_DISABLE`.

The classpath `testcontainers.properties` file may exist within the local codebase (e.g. within the `src/test/resources` directory) or within library dependencies that you may have. 
Any such configuration files will have their contents merged.
If any keys conflict, the value will be taken on the basis of the first value found in:

* 'local' classpath (i.e. where the URL of the file on the classpath begins with `file:`), then
* other classpath locations (i.e. JAR files) - considered in _alphabetical order of path_  to provide deterministic ordering.

## Disabling the startup checks
> **checks.disable = [true|false]**

Before running any containers Testcontainers will perform a set of startup checks to ensure that your environment is configured correctly. Usually they look like this:
```
        ℹ︎ Checking the system...
        ✔ Docker version should be at least 1.6.0
        ✔ File should be mountable
        ✔ A port exposed by a docker container should be accessible
```
It takes a couple of seconds, but if you want to speed up your tests, you can disable the checks once you have everything configured. Add `checks.disable=true` to your `$HOME/.testcontainers.properties` to completely disable them.

## Customizing images

!!! note
    This approach is discouraged and deprecated, but is documented for completeness.
    Overriding individual image names via configuration may be removed in 2021.
    See [Image Name Substitution](./image_name_substitution.md) for other strategies for substituting image names to pull from other registries.


Testcontainers uses public Docker images to perform different actions like startup checks, VNC recording and others. 
Some companies disallow the usage of Docker Hub, but you can override `*.image` properties with your own images from your private registry to workaround that.

> **ryuk.container.image = testcontainers/ryuk:0.3.3**
> Performs fail-safe cleanup of containers, and always required (unless [Ryuk is disabled](#disabling-ryuk))

> **tinyimage.container.image = alpine:3.17**  
> Used to check whether images can be pulled at startup, and always required (unless [startup checks are disabled](#disabling-the-startup-checks))

> **sshd.container.image = testcontainers/sshd:1.4.0**  
> Required if [exposing host ports to containers](./networking.md#exposing-host-ports-to-the-container)

> **vncrecorder.container.image = testcontainers/vnc-recorder:1.3.0**
> Used by VNC recorder in Testcontainers' Selenium integration

> **socat.container.image = alpine/socat**  
> **compose.container.image = docker/compose:1.8.0**  
> Required if using [Docker Compose](../modules/docker_compose.md)

> **kafka.container.image = confluentinc/cp-kafka**  
> Used by KafkaContainer 

> **localstack.container.image = localstack/localstack**  
> Used by LocalStack

> **pulsar.container.image = apachepulsar/pulsar:2.2.0**  
> Used by Apache Pulsar

## Customizing Ryuk resource reaper

> **ryuk.container.image = testcontainers/ryuk:0.3.3**
> The resource reaper is responsible for container removal and automatic cleanup of dead containers at JVM shutdown

> **ryuk.container.privileged = true**
> In some environments ryuk must be started in privileged mode to work properly (--privileged flag)

### Disabling Ryuk
Ryuk must be started as a privileged container.  
If your environment already implements automatic cleanup of containers after the execution,
but does not allow starting privileged containers, you can turn off the Ryuk container by setting
`TESTCONTAINERS_RYUK_DISABLED` **environment variable** to `true`.

!!!tip
    Note that Testcontainers will continue doing the cleanup at JVM's shutdown, unless you `kill -9` your JVM process.

## Customizing image pull behaviour

> **pull.timeout = 120**
> By default Testcontainers will timeout if pull takes more than this duration (in seconds)

> **pull.pause.timeout = 30**
> By default Testcontainers will abort the pull of an image if the pull appears stalled (no data transferred) for longer than this duration (in seconds).

## Customizing client ping behaviour

> **client.ping.timeout = 10**
> Specifies for how long Testcontainers will try to connect to the Docker client to obtain valid info about the client before giving up and trying next strategy, if applicable (in seconds).

## Customizing Docker host detection

Testcontainers will attempt to detect the Docker environment and configure everything to work automatically.

However, sometimes customization is required. Testcontainers will respect the following **environment variables**:

> **DOCKER_HOST** = unix:///var/run/docker.sock  
> See [Docker environment variables](https://docs.docker.com/engine/reference/commandline/cli/#environment-variables)
>
> **TESTCONTAINERS_DOCKER_SOCKET_OVERRIDE**  
> Path to Docker's socket. Used by Ryuk, Docker Compose, and a few other containers that need to perform Docker actions.  
> Example: `/var/run/docker-alt.sock`
> 
> **TESTCONTAINERS_HOST_OVERRIDE**  
> Docker's host on which ports are exposed.  
> Example: `docker.svc.local`

For advanced users, the Docker host connection can be configured **via configuration** in `~/.testcontainers.properties`.
Note that these settings require use of the `EnvironmentAndSystemPropertyClientProviderStrategy`. The example below 
illustrates usage:

```properties
docker.client.strategy=org.testcontainers.dockerclient.EnvironmentAndSystemPropertyClientProviderStrategy
docker.host=tcp\://my.docker.host\:1234     # Equivalent to the DOCKER_HOST environment variable. Colons should be escaped.
docker.tls.verify=1                         # Equivalent to the DOCKER_TLS_VERIFY environment variable
docker.cert.path=/some/path                 # Equivalent to the DOCKER_CERT_PATH environment variable
```
In addition, you can deactivate this behaviour by specifying:
```properties
dockerconfig.source=autoIgnoringUserProperties # 'auto' by default
```

---

## File: docs/features/container_logs.md

# Accessing container logs

It is possible to capture container output using:
 
 * the `getLogs()` method, which simply returns a `String` snapshot of a container's entire log output
 * the `followOutput()` method. This method accepts a Consumer and (optionally)
a varargs list stating which of STDOUT, STDERR, or both, should be followed. If not specified, both will be followed.

At present, container output will always begin from the time of container creation.

## Reading all logs (from startup time to present)

`getLogs()` is the simplest mechanism for accessing container logs, and can be used as follows:

 
[Accessing all output (stdout and stderr)](../../core/src/test/java/org/testcontainers/containers/output/ContainerLogsTest.java) inside_block:docsGetAllLogs


 
[Accessing just stdout](../../core/src/test/java/org/testcontainers/containers/output/ContainerLogsTest.java) inside_block:docsGetStdOut


 
[Accessing just stderr](../../core/src/test/java/org/testcontainers/containers/output/ContainerLogsTest.java) inside_block:docsGetStdErr


## Streaming logs

Testcontainers includes some out-of-the-box Consumer implementations that can be used with the streaming `followOutput()` model; examples follow.

### Streaming container output to an SLF4J logger

Given an existing SLF4J logger instance named LOGGER:
```java
Slf4jLogConsumer logConsumer = new Slf4jLogConsumer(LOGGER);
container.followOutput(logConsumer);
```

By default both standard out and standard error will both be emitted at INFO level. 
Standard error may be emitted at ERROR level, if desired:

```java
Slf4jLogConsumer logConsumer = new Slf4jLogConsumer(LOGGER).withSeparateOutputStreams();
```

The [Mapped Diagnostic Context (MDC)](http://logback.qos.ch/manual/mdc.html) for emitted messages may be configured using the `withMdc(...)` option:

```java
Slf4jLogConsumer logConsumer = new Slf4jLogConsumer(LOGGER).withMdc("key", "value");
```

or using an existing map of key-value pairs:

```java
Slf4jLogConsumer logConsumer = new Slf4jLogConsumer(LOGGER).withMdc(map);
```

### Capturing container output as a String

To stream logs live or customize the decoding, `ToStringConsumer` may be used:

```java
ToStringConsumer toStringConsumer = new ToStringConsumer();
container.followOutput(toStringConsumer, OutputType.STDOUT);

String utf8String = toStringConsumer.toUtf8String();

// Or if the container output is not UTF-8
String otherString = toStringConsumer.toString(CharSet.forName("ISO-8859-1"));
```

### Waiting for container output to contain expected content

`WaitingConsumer` will block until a frame of container output (usually a line) matches a provided predicate.

A timeout may be specified, as shown in this example.
```java
WaitingConsumer consumer = new WaitingConsumer();

container.followOutput(consumer, STDOUT);

consumer.waitUntil(frame -> 
    frame.getUtf8String().contains("STARTED"), 30, TimeUnit.SECONDS);
```

Additionally, as the Java 8 Consumer functional interface is used, Consumers may be composed together. This is
useful, for example, to capture all the container output but only when a matching string has been found. e.g.:
```java
WaitingConsumer waitingConsumer = new WaitingConsumer();
ToStringConsumer toStringConsumer = new ToStringConsumer();

Consumer<OutputFrame> composedConsumer = toStringConsumer.andThen(waitingConsumer);
container.followOutput(composedConsumer);

waitingConsumer.waitUntil(frame -> 
    frame.getUtf8String().contains("STARTED"), 30, TimeUnit.SECONDS);

String utf8String = toStringConsumer.toUtf8String();
```

---

## File: docs/features/creating_container.md

# Creating a container

## Creating a generic container based on an image

Testcontainers' generic container support offers the most flexibility, and makes it easy to use virtually any container
images as temporary test dependencies. For example, if you might use it to test interactions with:

* NoSQL databases or other data stores (e.g. redis, elasticsearch, mongo)
* Web servers/proxies (e.g. nginx, apache)
* Log services (e.g. logstash, kibana)
* Other services developed by your team/organization which are already dockerized

With a generic container, you set the container image using a parameter to the rule constructor, e.g.:
```java
new GenericContainer(DockerImageName.parse("jboss/wildfly:9.0.1.Final"))
```

### Specifying an image

Many Container classes in Testcontainers have historically supported: 

* a no-args constructor - for example `new GenericContainer()` and `new ElasticsearchContainer()`. With these constructors, Testcontainers has traditionally used a default image name (including a fixed image tag/version). This has caused a conflict between the need to keep the defaults sane (i.e. up to date) and the need to avoid silently upgrading these dependencies along with new versions of Testcontainers. 
* a single string-argument constructor, which has taken either a version or an image name as a String. This has caused some ambiguity and confusion.

Since v1.15.0, both of these constructor types have been deprecated, for the reasons given above.

Instead, it is highly recommended that _all containers_ be constructed using a constructor that accepts a `DockerImageName` object.
The `DockerImageName` class is an unambiguous reference to a docker image.

It is suggested that developers treat `DockerImageName`s as you would any other potentially-constant value - consider defining a constant in your test codebase that matches the production version of the dependency you are using.

### Examples

A generic container rule can be used with any public docker image; for example:

 
[Creating a Redis container](../examples/junit5/redis/src/test/java/quickstart/RedisBackedCacheIntTest.java) inside_block:container


The container, as `@Container`, will be started before any tests in the class run, and will be destroyed after all
tests have run.

---

## File: docs/features/creating_images.md

# Creating images on-the-fly

## Overview

In situations where there is no pre-existing Docker image, Testcontainers can create a new temporary image on-the-fly
from a Dockerfile. For example, when the component under test is the Docker image itself, or when an existing base
image needs to be customized for specific test(s).

Simply pass a configured instance of `ImageFromDockerfile` as a constructor parameter to `GenericContainer`.
Testcontainers will `docker build` a temporary container image, and will use it when creating the container.

## Dockerfile from String, file or classpath resource

`ImageFromDockerfile` accepts arbitrary files, strings or classpath resources to be used as files in the build context.
At least one of these needs to be a `Dockerfile`.

```java
GenericContainer container = new GenericContainer(
    new ImageFromDockerfile()
            .withFileFromString("folder/someFile.txt", "hello")
            .withFileFromClasspath("test.txt", "mappable-resource/test-resource.txt")
            .withFileFromClasspath("Dockerfile", "mappable-dockerfile/Dockerfile"))
```

The following methods may be used to provide the `Dockerfile` and any other required build context files:

* `withFileFromString(buildContextPath, content)`
* `withFileFromClasspath(buildContextPath, classpathPath)`
* `withFileFromPath(buildContextPath, filesystemPath)`
* `withFileFromFile(buildContextPath, filesystemFile)`

!!! info
    In older versions of Testcontainers (before 1.3.0) it was necessary to explicitly declare each file that needed to 
    be present in the Docker build context.
    This can be replaced with the following syntax:
     
    [Passing an entire directory of files to the Dockerfile build context](../../core/src/test/java/org/testcontainers/images/builder/DockerfileBuildTest.java) inside_block:docsShowRecursiveFileInclusion
    
    
    Where `RESOURCE_PATH` is the path to a directory containing a `Dockerfile` and any files that it needs to refer to.
    Doing this is equivalent to `docker build RESOURCE_PATH` on the command line.
    
    To mimic `docker build .`, `RESOURCE_PATH` would simply be set to `.` as well.

## Dockerfile DSL

If a static Dockerfile is not sufficient (e.g. your test needs to cover many variations that are best generated
programmatically), there is a DSL available to allow Dockerfiles to be defined in code. e.g.:
```java
new GenericContainer(
        new ImageFromDockerfile()
                .withDockerfileFromBuilder(builder ->
                        builder
                                .from("alpine:3.17")
                                .run("apk add --update nginx")
                                .cmd("nginx", "-g", "daemon off;")
                                .build()))
                .withExposedPorts(80);
```

See `ParameterizedDockerfileContainerTest` for a very basic example of using this in conjunction with JUnit
parameterized testing.

## Automatic deletion

Temporary container images will be automatically removed when the test JVM shuts down. If this is not desired and
the image should be retained between tests, pass a stable image name and `false` flag to the `ImageFromDockerfile`
constructor.

Retaining the image between tests will use Docker's image cache to accelerate subsequent test runs.

By default the no-args constructor will use an image name of the form `testcontainers/` + random string:

* `public ImageFromDockerfile()`
* `public ImageFromDockerfile(String dockerImageName)`
* `public ImageFromDockerfile(String dockerImageName, boolean deleteOnExit)`

## Alternative Dockerfiles

Normally Docker will automatically build an image from any `/Dockerfile` that it finds in the root of the build context.
To override this behaviour, use `.withDockerfilePath("./Name-Of-Other-Dockerfile")`.

## Build Args

[Build Args](https://docs.docker.com/engine/reference/builder/#arg) may be used to allow lightweight parameterization.

To specify build args, use `.withBuildArg("varname", "value")` or provide a `Map` of args using `.withBuildArgs(map)`.

---

## File: docs/features/files.md

# Files and volumes

## Copying files

Files can be copied into the container before startup, or can be copied from the container after the container has started.

!!! note
    This is the recommended approach for portability cross-docker environments.

### Copying to a container before startup


[Copying files using MountableFile](../../core/src/test/java/org/testcontainers/junit/CopyFileToContainerTest.java) inside_block:copyToContainer


Using `Transferable`, file content will be placed in the specified location.


[Copying files using Transferable](../../core/src/test/java/org/testcontainers/containers/GenericContainerTest.java) inside_block:transferableFile


Setting file mode is also possible. 


[Copying files using Transferable with file mode](../../core/src/test/java/org/testcontainers/containers/GenericContainerTest.java) inside_block:transferableWithFileMode


### Copying a file from a running container


[Copying files from a container](../../core/src/test/java/org/testcontainers/junit/CopyFileToContainerTest.java) inside_block:copyFileFromContainer

---

## File: docs/features/image_name_substitution.md

# Image name substitution

Testcontainers supports automatic substitution of Docker image names.

This allows replacement of an image name specified in test code with an alternative name - for example, to replace the 
name of a Docker Hub image dependency with an alternative hosted on a private image registry.

This is advisable to avoid [Docker Hub rate limiting](../supported_docker_environment/image_registry_rate_limiting.md), and some companies will prefer this for policy reasons.

This page describes four approaches for image name substitution:

* [Manual substitution](#manual-substitution) - not relying upon an automated approach
* Using an Image Name Substitutor:
    * [Developing a custom function for transforming image names on the fly](#developing-a-custom-function-for-transforming-image-names-on-the-fly)
    * [Overriding image names individually in configuration](#overriding-image-names-individually-in-configuration)

It is assumed that you have already set up a private registry hosting [all the Docker images your build requires](../supported_docker_environment/image_registry_rate_limiting.md#which-images-are-used-by-testcontainers).




## Manual substitution

Consider this if:

* You use only a few images and updating code is not a chore
* All developers and CI machines in your organisation have access to a common registry server
* You also use one of the automated mechanisms to substitute [the images that Testcontainers itself requires](../supported_docker_environment/image_registry_rate_limiting.md#which-images-are-used-by-testcontainers)

This approach simply entails modifying test code manually, e.g. changing:

For example, you may have a test that uses the `mysql` container image from Docker Hub:

 
[Direct Docker Hub image name](../examples/junit4/generic/src/test/java/generic/ImageNameSubstitutionTest.java) inside_block:directDockerHubReference


to:

 
[Private registry image name](../examples/junit4/generic/src/test/java/generic/ImageNameSubstitutionTest.java) inside_block:hardcodedMirror






## Automatically modifying Docker Hub image names

Testcontainers can be configured to modify Docker Hub image names on the fly to apply a prefix string.

Consider this if:

* Developers and CI machines need to use different image names. For example, developers are able to pull images from Docker Hub, but CI machines need to pull from a private registry
* Your private registry has copies of images from Docker Hub where the names are predictable, and just adding a prefix is enough. 
  For example, `registry.mycompany.com/mirror/mysql:8.0.36` can be derived from the original Docker Hub image name (`mysql:8.0.36`) with a consistent prefix string: `registry.mycompany.com/mirror/`

In this case, image name references in code are **unchanged**.
i.e. you would leave as-is:

 
[Unchanged direct Docker Hub image name](../examples/junit4/generic/src/test/java/generic/ImageNameSubstitutionTest.java) inside_block:directDockerHubReference


You can then configure Testcontainers to apply the prefix `registry.mycompany.com/mirror/` to every image that it tries to pull from Docker Hub.
This can be done in one of two ways:

* Setting environment variables `TESTCONTAINERS_HUB_IMAGE_NAME_PREFIX=registry.mycompany.com/mirror/`
* Via config file, setting `hub.image.name.prefix` in either:
    * the `~/.testcontainers.properties` file in your user home directory, or
    * a file named `testcontainers.properties` on the classpath
    
Testcontainers will automatically apply the prefix to every image that it pulls from Docker Hub - please verify that all [the required images](../supported_docker_environment/image_registry_rate_limiting.md#which-images-are-used-by-testcontainers) exist in your registry.

Testcontainers will not apply the prefix to:

* non-Hub image names (e.g. where another registry is set)
* Docker Hub image names where the hub registry is explicitly part of the name (i.e. anything with a `docker.io` or `registry.hub.docker.com` host part)



## Developing a custom function for transforming image names on the fly

Consider this if:

* You have complex rules about which private registry images should be used as substitutes, e.g.:
    * non-deterministic mapping of names meaning that a [name prefix](#automatically-modifying-docker-hub-image-names) cannot be used
    * rules depending upon developer identity or location
* or you wish to add audit logging of images used in the build
* or you wish to prevent accidental usage of images that are not on an approved list

In this case, image name references in code are **unchanged**.
i.e. you would leave as-is:

 
[Unchanged direct Docker Hub image name](../examples/junit4/generic/src/test/java/generic/ImageNameSubstitutionTest.java) inside_block:directDockerHubReference


You can implement a custom image name substitutor by:

* subclassing `org.testcontainers.utility.ImageNameSubstitutor`
* configuring Testcontainers to use your custom implementation

The following is an example image substitutor implementation:

 
[Example Image Substitutor](../examples/junit4/generic/src/test/java/generic/ExampleImageNameSubstitutor.java) block:ExampleImageNameSubstitutor


Testcontainers can be configured to find it at runtime via configuration.
To do this, create or modify a file on the classpath named `testcontainers.properties`.

For example:

=== "`src/test/resources/testcontainers.properties`"
    ```text
    image.substitutor=com.mycompany.testcontainers.ExampleImageNameSubstitutor
    ``` 

Note that it is also possible to provide this same configuration property:

* in a `testcontainers.properties` file at the root of a library JAR file (useful if you wish to distribute a drop-in image substitutor JAR within an organization) 
* in a properties file in the user's home directory (`~/.testcontainers.properties`; note the leading `.`)
* or as an environment variable (e.g. `TESTCONTAINERS_IMAGE_SUBSTITUTOR=com.mycompany.testcontainers.ExampleImageNameSubstitutor`).

Please see [the documentation on configuration mechanisms](./configuration.md) for more information.

Also, you can use the `ServiceLoader` mechanism to provide the fully qualified class name of the `ImageNameSubstitutor` implementation:

=== "`src/test/resources/META-INF/services/org.testcontainers.utility.ImageNameSubstitutor`"
    ```text
    com.mycompany.testcontainers.ExampleImageNameSubstitutor
    ```


## Overriding image names individually in configuration

!!! note
    This approach is discouraged and deprecated, but is documented for completeness.
    Please consider one of the other approaches outlined in this page instead.
    Overriding individual image names via configuration may be removed in the future. 

Consider this if:

* You have many references to image names in code and changing them is impractical, and
* None of the other options are practical for you

In this case, image name references in code are left **unchanged**.
i.e. you would leave as-is:

 
[Unchanged direct Docker Hub image name](../examples/junit4/generic/src/test/java/generic/ImageNameSubstitutionTest.java) inside_block:directDockerHubReference


You can force Testcontainers to substitute in a different image [using a configuration file](./configuration.md), which allows some (but not all) container names to be substituted.