Skip to main content
Every self-hosted System-X service in TNB uses a default Docker image. You can override these images without modifying source code using system properties.

Default images

Each service that implements WithDockerImage interface defines a default image:
public abstract class MongoDB implements Service, WithDockerImage {
    public String defaultImage() {
        return "quay.io/mongodb/mongodb-community-server:7.0";
    }
}
This default is used unless overridden by configuration.

Overriding Docker images

Using system properties

Override the image for any service using the property format tnb.<service>.image:
# Override MongoDB image
tnb.mongodb.image=mongo:7.0

# Override Kafka image
tnb.kafka.image=confluentinc/cp-kafka:7.5.0

# Override PostgreSQL image
tnb.postgresql.image=postgres:16-alpine

# Override MySQL image
tnb.mysql.image=mysql:8.2

Property naming convention

The property name is derived from the service class name:
Service classProperty nameExample
MongoDBtnb.mongodb.imagemongo:7.0
PostgreSQLtnb.postgresql.imagepostgres:16
Kafkatnb.kafka.imageconfluentinc/cp-kafka:7.5.0
MySQLtnb.mysql.imagemysql:8.2
Redistnb.redis.imageredis:7-alpine
Elasticsearchtnb.elasticsearch.imageelasticsearch:8.11.0
The service name is converted to lowercase: MongoDBmongodb, PostgreSQLpostgresql

How image resolution works

TNB resolves the image to use with this logic:
1

Check system property

Look for tnb.<servicename>.image system property
2

Use default if not found

If property not set, use the value from defaultImage() method
3

Apply to deployment

Use resolved image in TestContainers (local) or OpenShift deployment
public interface WithDockerImage {
    String SYSTEM_PROPERTY_FORMAT = "tnb.%s.image";

    default String image() {
        return TestConfiguration.getProperty(
            String.format(SYSTEM_PROPERTY_FORMAT, 
                ReflectionUtil.getSuperClassName(this.getClass()).toLowerCase()),
            defaultImage()
        );
    }

    String defaultImage();
}

Common use cases

Testing with specific versions

Test your application against multiple service versions:
# Test with MongoDB 6.0
tnb.mongodb.image=mongo:6.0

# Test with MongoDB 7.0
tnb.mongodb.image=mongo:7.0
# Run test suite with different versions
mvn test -Dtnb.mongodb.image=mongo:6.0
mvn test -Dtnb.mongodb.image=mongo:7.0

Using private registries

Pull images from private container registries:
# Private registry with authentication
tnb.kafka.image=registry.company.com/kafka:3.6.0
tnb.mongodb.image=registry.company.com/mongodb:7.0

# Artifactory/Nexus registry
tnb.postgresql.image=artifactory.company.com/docker/postgres:16
Ensure Docker/Podman is authenticated to your private registry:
docker login registry.company.com

Using specific distributions

Choose between different distributions of the same service:
# Official MongoDB image
tnb.mongodb.image=mongo:7.0

# Red Hat MongoDB image
tnb.mongodb.image=registry.access.redhat.com/rhscl/mongodb-36-rhel7

# Bitnami MongoDB image
tnb.mongodb.image=bitnami/mongodb:7.0

Platform-specific images

Use architecture-specific images for ARM/M1 Macs:
# ARM64-compatible images
tnb.mongodb.image=mongo:7.0  # Multi-arch
tnb.postgresql.image=postgres:16-alpine  # Multi-arch
tnb.redis.image=redis:7-alpine  # Multi-arch

# Explicit ARM64 image
tnb.mysql.image=arm64v8/mysql:8.2

Connecting to external services

Instead of deploying a service, connect to an external instance:

Using external host property

Specify the hostname of an external service:
# Connect to external Kafka
tnb.kafka.host=kafka.example.com:9092

# Connect to external MongoDB
tnb.mongodb.host=mongodb.example.com:27017

# Connect to external PostgreSQL
tnb.postgresql.host=postgres.example.com:5432
When tnb.<service>.host is set, TNB skips deployment and connects to the specified host.
The service must be accessible from your test environment. Ensure network connectivity and firewall rules allow access.

Example usage

# Use external Kafka cluster
tnb.kafka.host=kafka-prod.company.com:9092

# Other services deployed locally
tnb.mongodb.image=mongo:7.0
tnb.postgresql.image=postgres:16

OpenShift deployments

Image overrides work with OpenShift deployments too:
# Deploy to OpenShift
test.use.openshift=true

# Use custom images in OpenShift
tnb.kafka.image=registry.redhat.io/amq-streams/kafka-36-rhel8:2.6.0
tnb.mongodb.image=registry.access.redhat.com/rhscl/mongodb-36-rhel7

# OpenShift connection
openshift.kubeconfig=~/.kube/config
openshift.namespace=test-services
When deploying to OpenShift, ensure the image is:
  • Accessible from the OpenShift cluster
  • Compatible with OpenShift security constraints
  • Available in a registry the cluster can pull from

Service configuration

Some services have additional configuration options beyond images.

Using ConfigurableService

Services extending ConfigurableService can be configured via code:
import software.tnb.common.service.ServiceFactory;
import software.tnb.splunk.service.Splunk;
import software.tnb.splunk.service.configuration.SplunkConfiguration.SplunkProtocol;

@RegisterExtension
public static Splunk splunk = ServiceFactory.create(
    Splunk.class, 
    config -> config.protocol(SplunkProtocol.HTTP)
);

Available configurations

Check service-specific documentation for configuration options:
  • Splunk: Protocol (HTTP/HTTPS), HEC token
  • Kafka: Number of brokers, replication factor
  • Elasticsearch: Cluster name, heap size
  • MySQL: Root password, database name
Example:
// Kafka with custom configuration
@RegisterExtension
public static Kafka kafka = ServiceFactory.create(
    Kafka.class,
    config -> config
        .brokers(3)
        .replicationFactor(2)
);

Best practices

Pin versions

Use specific version tags instead of latest for reproducible tests:
tnb.mongodb.image=mongo:7.0.4

Test multiple versions

Create test profiles for different service versions:
mvn test -Ppostgres-15
mvn test -Ppostgres-16

Use official images

Prefer official images from verified publishers for security and reliability.

Document overrides

Keep a test.properties.template documenting all available overrides for your team.

Cache images locally

Pre-pull images to speed up test execution:
docker pull mongo:7.0
docker pull postgres:16

Monitor image sizes

Use Alpine or slim variants when possible to reduce download time and disk usage.

Troubleshooting

Verify the image exists and is accessible:
docker pull mongo:7.0
Check image name spelling and version tag:
# Wrong
tnb.mongodb.image=mongo:70

# Correct
tnb.mongodb.image=mongo:7.0
For private registries, authenticate Docker:
docker login registry.company.com
For OpenShift, create image pull secret:
oc create secret docker-registry registry-secret \
  --docker-server=registry.company.com \
  --docker-username=user \
  --docker-password=pass
On ARM Macs, ensure images support ARM64:
# Check image platforms
docker manifest inspect mongo:7.0 | grep architecture
Use multi-arch images or explicit ARM64 variants:
tnb.mongodb.image=mongo:7.0  # Multi-arch
Verify property name matches service class name:
# Check service class
grep "class.*MongoDB" -r system-x/services/

# Use lowercase service name
tnb.mongodb.image=mongo:7.0
Ensure property is loaded:
mvn test -Dtnb.mongodb.image=mongo:7.0 -X | grep mongodb.image
Some image versions may not be compatible with TNB’s client libraries.Check service logs for errors:
docker logs <container-id>
Try using the default image first, then upgrade incrementally.

Examples

postgres-15.properties
test.use.openshift=false
tnb.postgresql.image=postgres:15-alpine
postgres-16.properties
test.use.openshift=false
tnb.postgresql.image=postgres:16-alpine
# Test with PostgreSQL 15
mvn test -Dtest.properties=postgres-15.properties

# Test with PostgreSQL 16
mvn test -Dtest.properties=postgres-16.properties

Build docs developers (and LLMs) love