Connecting to Testcontainers Services using Testcontainers Desktop

The Testcontainers Desktop app is a free companion app for open source Testcontainers libraries that makes local development and testing with real dependencies simple.

You can refer to the Testcontainers Desktop docs to learn various features offered by Testcontainers Desktop app. In this article, you will learn how to connect to the database(s) started by Testcontainers from any of your favorite database client tools.

Banner connecting to testcontainers services using testcontainers desktop

Whether you run containers locally using container runtimes like Docker Desktop, OrbStack, etc., or on the cloud using Testcontainers Cloud, you can connect to the containerized services like databases, and message brokers using the Testcontainers Desktop port forwarding feature.

You might be working on a microservices-based application where each service has its own database. And, you might want to run multiple microservices and connect to multiple databases to inspect the data.

In this blog post, we’ll see how to use the Testcontainers Desktop port-forwarding feature to connect to multiple containers of the same type (i.e., PostgreSQL).

Imagine we have two Spring Boot microservices — product-service, and promotion-service — which are using PostgreSQL as their database. We can use Spring Boot’s Testcontainers support to start PostgreSQL containers for both services. Now, we will learn how to use Testcontainers Desktop port-forwarding feature to connect to the databases created by Testcontainers.

You can find the source code for this article at GitHub. 

Create product-service

You can create product-service using Spring Initializr by selecting Spring Web, Spring Data JPA, Flyway Migration, PostgreSQL Drive, and Testcontainers starters.

In the generated project, you can see TestProductServiceApplication.java under src/test/java as follows:

package com.testcontainers.products;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.context.annotation.Bean;
import org.testcontainers.containers.PostgreSQLContainer;
import org.testcontainers.utility.DockerImageName;
@TestConfiguration(proxyBeanMethods = false)
public class TestProductServiceApplication {
  @Bean
  @ServiceConnection
  PostgreSQLContainer<?> postgresContainer() {
      return new PostgreSQLContainer<>(DockerImageName.parse("postgres:16-alpine"));
  }
  public static void main(String[] args) {
      SpringApplication
              .from(ProductServiceApplication::main)
              .with(TestProductServiceApplication.class)
              .run(args);
  }
}

Now you can run TestProductServiceApplication.java from your IDE to start the application. It will start a PostgreSQL database container using Testcontainers, configure the application to use that database, and apply the database migration script using Flyway.

Connecting to product-service database

When Testcontainers starts the PostgreSQL database container, it will map the database container’s port 5432 to a random available port on the host. So, it will be tedious to check every time what the mapped port is for the database container and then connect to it. Instead, we can use the Testcontainers Desktop port-forwarding feature to map the container’s port to a fixed port on the host and connect to it.

Select Testcontainers Desktop > select Services > Open config location. In the opened directory, there should be a postgres.toml.example file.

Rename this to products-postgres.toml file and update it to have the following configuration:

ports = [
  {local-port = 15432, container-port = 5432},
]
selector.image-names = ["postgres"]

In the above configuration, we have mapped the container’s port 5432 to the host’s port 15432. 

Now when you restart the application, you should be able to connect to the database using the following details:

host: localhost
port: 15432
database: test
username: test
password: test

Connecting to multiple containers of the same type

Now you might be thinking, what if I have another microservice, say promotion-service, which also uses PostgreSQL as its database?

In the previous port-forwarding configuration, we just configured the image selector as postgres, which will match any PostgreSQL container. So, if you start the promotion-service, it will also use the same port mapping as product-service. This is where the labels selector comes into the picture.

Using the labels selector

Let’s update the PostgreSQL container configuration in TestProductServiceApplication.java as follows:

@Bean
@ServiceConnection
PostgreSQLContainer<?> postgresContainer() {
  return new PostgreSQLContainer<>(
          DockerImageName.parse("postgres:16-alpine"))
          .withLabel("com.testcontainers.desktop.service", "products-postgres");
}

We have added a label com.testcontainers.desktop.service with the value products-postgres to the container. Now we can update the port forwarding configuration in products-postgres.toml file to match this label.

ports = [
{local-port = 15432, container-port = 5432},
]
selector.image-names = ["postgres"]
[selector.labels]
"com.testcontainers.desktop.service" = "products-postgres"

In addition to the image selector, we have added a label selector to match the label com.testcontainers.desktop.service with the value products-postgres.

Now, assume that you have created the promotion-service, which uses PostgreSQL similar to product-service, and you have TestPromotionServiceApplication.java under src/test/java as follows:

package com.testcontainers.promotions;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.context.annotation.Bean;
import org.testcontainers.containers.PostgreSQLContainer;
import org.testcontainers.utility.DockerImageName;
@TestConfiguration(proxyBeanMethods = false)
public class TestPromotionServiceApplication {
  @Bean
  @ServiceConnection
  PostgreSQLContainer<?> postgresContainer() {
      return new PostgreSQLContainer<>(
              DockerImageName.parse("postgres:16-alpine"))
              .withLabel("com.testcontainers.desktop.service", "promotion-postgres");
  }
  public static void main(String[] args) {
      SpringApplication
              .from(PromotionServiceApplication::main)
              .with(TestPromotionServiceApplication.class)
              .run(args);
  }
}

Now you can create a promotion-postgres.toml file next to products-postgres.toml file with the following configuration:

ports = [
{local-port = 25432, container-port = 5432},
]
selector.image-names = ["postgres"]
[selector.labels]
"com.testcontainers.desktop.service" = "promotion-postgres"

In the above configuration, we have mapped the container’s port 5432 to the host’s port 25432. 

Now when you start the promotion-service application, you should be able to connect to the promotion-service database using the following details:

host: localhost
port: 25432
database: test
username: test
password: test

Although we have demonstrated connecting to the PostgreSQL database container, the same approach works for any other container, such as Kafka, RabbitMQ, MongoDB, etc.

Summary

We have explored the Testcontainers Desktop port-forwarding feature with a realistic scenario. We have demonstrated how to use Testcontainers Desktop features using Java/Spring Boot examples, but it works for other Testcontainers supported languages (Go, .NET, Node.js, Python, etc) as well.

You can download the Testcontainers Desktop application and start using it for your application’s local development and testing.

Learn more