TestContainers does not wait for all services started with Docker Compose to be ready.
This happens with JUnit 5, TestContainers 1.15.0 and a PostgreSQL container.
I have made a minimal reproducer at https://github.com/jponge/bug-testcontainers-and-docker-compose-fail-nov2020
@BeforeAll method is entered the connection to PostgreSQL fails.https://www.testcontainers.org/features/startup_and_waits/
you need to implement wait strategies
The default wait strategy is to wait for container ports to be ready. Making this explicit in the reproducer does not fix the problem:
@Container
private static final DockerComposeContainer CONTAINERS = new DockerComposeContainer(new File("docker-compose.yml"))
.waitingFor("postgres", Wait.forListeningPort());
@jponge have you tried adding .withExposedService("postgres_1", 5432), as per the docs?
Indeed this works thanks @bsideup
@Container
private static final DockerComposeContainer CONTAINERS = new DockerComposeContainer(new File("docker-compose.yml"))
.withExposedService("postgres_1", 5432);
That being said I find it counter-intuitive, I'd expect all containers to be waited for rather than having to manually specify all of them.
WDYT?
@jponge well, withExposedService is essential because otherwise you won't be able to access the service unless you get lucky and the host is "localhost" (not the case in case of docker-in-docker, for example) and port is not allocated yet.
We generally discourage the use of fixed host/ports because it is unreliable.
Also, we can't easily iterate all services in Docker Compose and know them in advance because there is no API for that. Docker Compose is quite limited, and I would always recommend using GenericContainers instead, even for local development.
Also, we can't easily iterate all services in Docker Compose and know them in advance because there is no API for that.
Well I think you can parse the YAML and spot service port declarations.
Closing this, works as @bsideup suggested, thanks.
Unfortunately it isn't that simple and we would end up re-implementing a major piece of Docker Compose 馃槄 Given how limiting it is, I would rather focus on TC's core functionality :)