Testcontainers (Java)
The official Testcontainers module ships a dedicated MiniStackContainer class. It starts MiniStack, waits for /_ministack/health, and exposes the mapped endpoint and credentials for wiring any AWS SDK for Java v2 client.
Install
Maven
<dependency> <groupId>org.ministack</groupId> <artifactId>testcontainers-ministack</artifactId> <version>0.1.5</version> <scope>test</scope> </dependency>
Gradle
testImplementation 'org.ministack:testcontainers-ministack:0.1.5'
The module pulls the ministackorg/ministack image and requires a running Docker daemon, like any Testcontainers module. Check Maven Central for the latest release.
Quick start
Start the container, read getEndpoint(), and point an SDK client at it. The default credentials are test / test and the default region is us-east-1.
try (MiniStackContainer ministack = new MiniStackContainer()) {
ministack.start();
String endpoint = ministack.getEndpoint();
S3Client s3 = S3Client.builder()
.endpointOverride(URI.create(endpoint))
.region(Region.of(ministack.getRegion()))
.credentialsProvider(StaticCredentialsProvider.create(
AwsBasicCredentials.create(ministack.getAccessKey(), ministack.getSecretKey())))
.forcePathStyle(true)
.build();
s3.createBucket(b -> b.bucket("my-bucket"));
}
The accessor methods available on the container are getEndpoint(), getPort(), getRegion(), getAccessKey(), getSecretKey(), and getMiniStackVersion(). Use forcePathStyle(true) for S3 — MiniStack serves path-style URLs by default.
Configuration
The builder methods set the corresponding MiniStack environment variables on the container:
MiniStackContainer ministack = new MiniStackContainer("1.3.42")
.withRegion("eu-west-1") // MINISTACK_REGION
.withCredentials("AKIAEXAMPLE000000000", "secret") // AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY
.withPersistence() // PERSIST_STATE=1 + S3_PERSIST=1
.withImdsV2Required(); // MINISTACK_IMDS_V2_REQUIRED=1
Version pinning
Pass a tag to pin a specific MiniStack release instead of the default image tag:
MiniStackContainer ministack = new MiniStackContainer("1.4.5");
Gate tests on capability with getMiniStackVersion(), which returns the image tag verbatim:
assumeTrue(ministack.getMiniStackVersion().compareTo("1.3.42") >= 0,
"test requires MiniStack 1.3.42+");
"1.3.42" sort lexicographically as expected, but "latest" and "nightly" do not. Pin a specific version tag when you need precise capability gating.
Private registry
The module automatically forwards Testcontainers' hub.image.name.prefix into the container as MINISTACK_IMAGE_PREFIX. This means nested real-infrastructure images (RDS postgres/mysql/mariadb, ElastiCache redis/memcached, EKS k3s, Lambda runtimes) route through the same private registry or proxy as the MiniStack image itself — important in air-gapped or proxy-only environments where a bare docker.io / public.ecr.aws pull would fail. No configuration is needed; set the standard Testcontainers prefix and it propagates.
Real infrastructure
Call withRealInfrastructure() to let MiniStack spin up real backend containers (RDS, ElastiCache, ECS, EKS) by bind-mounting the host Docker socket into the MiniStack container:
try (MiniStackContainer ministack = new MiniStackContainer()) {
ministack.withRealInfrastructure();
ministack.start();
RdsClient rds = RdsClient.builder()
.endpointOverride(URI.create(ministack.getEndpoint()))
.region(Region.of(ministack.getRegion()))
.credentialsProvider(StaticCredentialsProvider.create(
AwsBasicCredentials.create(ministack.getAccessKey(), ministack.getSecretKey())))
.build();
rds.createDBInstance(b -> b
.dbInstanceIdentifier("postgres")
.dbInstanceClass("db.t3.micro")
.engine("postgres")
.masterUsername("admin")
.masterUserPassword("password")
.dbName("postgresdb")
.allocatedStorage(20));
// MiniStack spawns a real Postgres container. Poll DescribeDBInstances
// until it reports `available` before opening a JDBC connection.
Awaitility.await()
.atMost(Duration.ofMinutes(2))
.pollInterval(Duration.ofSeconds(2))
.until(() -> "available".equals(
rds.describeDBInstances(b -> b.dbInstanceIdentifier("postgres"))
.dbInstances().get(0).dbInstanceStatus()));
}
withRealInfrastructure() bind-mounts the host Docker socket into the MiniStack container. Anything running inside MiniStack — including arbitrary code in Lambda handlers or RDS init scripts — gains root-equivalent control of the host's container engine. Use only on trusted developer machines or isolated CI runners.