Container Networking in Testcontainers
Testcontainers can place multiple containers on a shared Docker network so they can communicate using stable container aliases instead of host-specific addresses. This is useful for integration tests that reproduce interactions between services such as an application, database, and message broker.
A Docker network provides an isolated virtual network for containers. When several Testcontainers containers are attached to the same network, they can communicate directly without exposing their service ports to the host machine.
In Java Testcontainers, create a `Network` and attach containers to it with `withNetwork(network)`. Give containers predictable aliases with `withNetworkAliases("database")`, then another container can connect to that service using the alias as its hostname.
The hostname used between containers is the network alias, not `localhost`. `localhost` inside a container refers to that same container, so an application container using `localhost:5432` will not reach PostgreSQL running in a different container.
Host port mappings such as `withExposedPorts(5432)` and `getHost()` plus `getMappedPort()` are primarily useful when the test JVM needs to access a container. For container-to-container traffic on a shared network, use the target container's network alias and its internal listening port.
A shared network therefore separates two connection paths: test code running on the host talks through the mapped host port, while containers talk directly across the Docker network. This distinction is important when configuring a multi-container integration test.
Key points
- Create a shared `Network` and attach participating containers to it.
- Use `withNetworkAliases` to provide stable DNS names between containers.
- Inside a container, `localhost` refers to that container, not another service.
- Container-to-container connections use the target's internal port, not its dynamically mapped host port.
- Use mapped ports when the Java test process itself needs to connect to a container.
Interview questions
How would you make two Testcontainers communicate with each other?
I would create a shared `Network` and attach both containers to it with `withNetwork`. I would assign the target service a stable alias using `withNetworkAliases`. The client container can then connect to that alias using the target service's internal port. I would not use `localhost` because that points to the client container itself.
What is the difference between `withExposedPorts` and a Testcontainers network alias?
`withExposedPorts` establishes a port mapping that allows access through the Docker host, with Testcontainers selecting a host port dynamically. A network alias gives other containers on the same Docker network a hostname for reaching the container. A container-to-container connection normally uses the service's internal port rather than the mapped host port. The two mechanisms solve different networking paths.
Why is using `localhost` usually wrong when configuring an application container to access PostgreSQL in another Testcontainer?
Each container has its own network namespace, so `localhost` inside the application container refers to the application container itself. PostgreSQL is in a different container and therefore needs to be addressed through the shared Docker network. The application should use the PostgreSQL container's network alias as its hostname and PostgreSQL's internal listening port as the port. This avoids dependence on dynamically assigned host ports.
Why can host port mappings be inconvenient for service-to-service integration tests?
Host mappings introduce a host-side address and a dynamically allocated port, which are unnecessary when both services already share a Docker network. Service containers can instead discover each other through network aliases and communicate over their normal internal ports. This more closely models service-to-service networking and avoids wiring host port values into the application configuration. Host mappings remain useful for traffic originating from the test JVM.