1. Help Center
  2. Compatibility with Docker

How to set fixed ports to debug development services?

To get started, download version 1.4.4 of the desktop app, or later and simply click "open config location" in the "Services" sub-menu and update .toml file

Part of the magic of Testcontainers libraries is that they dynamically map the container’s ports onto random ports on the host machine to avoid conflicts, ensuring that automated tests run reliably. However, this can make it harder to connect local debugging tools such as an IDE plugin to inspect a datastore, or k9s to manage a Kubernetes cluster.

You can now configure the Testcontainers desktop app to also proxy these random ports to a fixed port on your machine, available to debug Testcontainers services. To do so, simply click "open config location" in the "Services" sub-menu. You can then clone the sample configuration file and rename it to my-service.toml, where "my-service" is whatever your service is actually called, and finally pick a fixed port that should always be available to debug the service. Once you save the file, it's detected and reloaded automatically.

For example, here we've defined a service called redis-cache and therefore the file is called redis-cache.toml. We've configured the service to always be available at port 6379.

In the Java example below we spin up a redis container, write to it, then test that we can read the value. The test relies on a dynamically mapped port, and therefore port 6379 wouldn't usually be available on the host machine (i.e. your laptop). But we've added the label com.testcontainers.desktop.service with value redis-cache, which means that this container is now exposed on port 6379 as per our service's configuration above.

@Test
public void canWriteAndReadFromRedisCache() {
try (
GenericContainer<?> container = new GenericContainer<>(DockerImageName.parse("redis:6.0.5"))
// this label includes the container in the `redis-cache` service
.withLabel("com.testcontainers.desktop.service", "redis-cache")
// this port is exposed from the perspective of the container.
.withExposedPorts(6379);) {
container.start();

// The test remains reliable as it relies on a dynamically mapped port
int mappedPort = container.getFirstMappedPort();
Jedis jedis = new Jedis(container.getHost(), mappedPort);
jedis.set("foo", "bar");
String value = jedis.get("foo");

// Set a breakpoint here to connect to the database
// When the test completes, the container is cleaned up automatically
assertThat(value)
.as("Redis key foo equals bar")
.isEqualTo("bar");
}
}

We can test that this works by connecting our IDE plugin for redis and checking that it contains the k/v "foo: bar" as expected.