question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Using `DockerComposeContainer` as a base class with spring boot not working across multiple test classes

See original GitHub issue

I’m using the DockerComposeContainer in a base class with Spring Boot. The docker compose file contains Kafka/Zookeeper (please don’t ask why I’m not just using the KafkaContainer - I have my reasons and I cannot change to it).

My base class looks like this:

@DirtiesContext
@Testcontainers
public abstract class DockerComposeBase {
	@Container
	static final DockerComposeContainer<?> DOCKER_COMPOSE =
		new DockerComposeContainer<>(new File("docker-compose.yaml"))
			.withExposedService("zookeeper", 1, 2181, Wait.forListeningPort())
			.withExposedService("kafka", 1, 9092, Wait.forListeningPort());

	@DynamicPropertySource
	static void registerDynamicProperties(DynamicPropertyRegistry registry) {
		registry.add("spring.cloud.stream.kafka.binder.brokers", DockerComposeBase::getKafkaBrokers);
	}

	private static String getKafkaBrokers() {
		return String.format("%s:%s", DOCKER_COMPOSE.getServiceHost("kafka", 9092), DOCKER_COMPOSE.getServicePort("kafka", 9092));
	}
}

This is the docker-compose.yaml file:

version: '2'
services:
  zookeeper:
    image: quay.io/strimzi/kafka:0.29.0-kafka-3.1.1
    command: [
      "sh", "-c",
      "bin/zookeeper-server-start.sh config/zookeeper.properties"
    ]
    ports:
      - "2181:2181"
    environment:
      LOG_DIR: /tmp/logs

  kafka:
    image: quay.io/strimzi/kafka:0.29.0-kafka-3.1.1
    command: [
      "sh", "-c",
      "bin/kafka-server-start.sh config/server.properties --override listeners=$${KAFKA_LISTENERS} --override advertised.listeners=$${KAFKA_ADVERTISED_LISTENERS} --override zookeeper.connect=$${KAFKA_ZOOKEEPER_CONNECT}"
    ]
    depends_on:
      - zookeeper
    ports:
      - "9092:9092"
    environment:
      LOG_DIR: "/tmp/logs"
      KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://localhost:9092
      KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:9092
      KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181

And then I’m extending this class in several other classes. The issue is that after the 1st test class runs & the 2nd test class tries to run it seems that it attempts to re-use the old container.

Here are some logs

1st test class cleaning up

2022-06-01 10:31:54.465  INFO 70769 --- [           main] 🐳 [docker/compose:1.29.2]               : Docker Compose container is running for command: down -v
2022-06-01 10:31:54.467  INFO 70769 --- [ream--704437905] 🐳 [docker/compose:1.29.2]               : STDERR: Stopping c2lkjr47cacj_kafka_1     ... 
2022-06-01 10:31:54.467  INFO 70769 --- [ream--704437905] 🐳 [docker/compose:1.29.2]               : STDERR: Stopping c2lkjr47cacj_zookeeper_1 ... 
2022-06-01 10:31:54.467  INFO 70769 --- [ream--704437905] 🐳 [docker/compose:1.29.2]               : STDERR: Stopping c2lkjr47cacj_kafka_1     ... done
2022-06-01 10:31:54.467  INFO 70769 --- [ream--704437905] 🐳 [docker/compose:1.29.2]               : STDERR: Stopping c2lkjr47cacj_zookeeper_1 ... done
2022-06-01 10:31:54.467  INFO 70769 --- [ream--704437905] 🐳 [docker/compose:1.29.2]               : STDERR: Removing c2lkjr47cacj_kafka_1     ... 
2022-06-01 10:31:54.468  INFO 70769 --- [ream--704437905] 🐳 [docker/compose:1.29.2]               : STDERR: Removing c2lkjr47cacj_zookeeper_1 ... 
2022-06-01 10:31:54.468  INFO 70769 --- [ream--704437905] 🐳 [docker/compose:1.29.2]               : STDERR: Removing c2lkjr47cacj_zookeeper_1 ... done
2022-06-01 10:31:54.468  INFO 70769 --- [ream--704437905] 🐳 [docker/compose:1.29.2]               : STDERR: Removing c2lkjr47cacj_kafka_1     ... done
2022-06-01 10:31:54.468  INFO 70769 --- [ream--704437905] 🐳 [docker/compose:1.29.2]               : STDERR: Removing network c2lkjr47cacj_default
2022-06-01 10:31:54.470  INFO 70769 --- [           main] 🐳 [docker/compose:1.29.2]               : Docker Compose has finished running

2nd test class starting up

2022-06-01 10:32:01.344  INFO 70769 --- [           main] 🐳 [docker/compose:1.29.2]               : Docker Compose container is running for command: up -d
2022-06-01 10:32:01.346  INFO 70769 --- [ream--492279488] 🐳 [docker/compose:1.29.2]               : STDERR: Creating network "c2lkjrlr6um5_default" with the default driver
2022-06-01 10:32:01.346  INFO 70769 --- [ream--492279488] 🐳 [docker/compose:1.29.2]               : STDERR: Creating c2lkjrlr6um5_zookeeper_1 ... 
2022-06-01 10:32:01.346  INFO 70769 --- [ream--492279488] 🐳 [docker/compose:1.29.2]               : STDERR: Creating c2lkjrlr6um5_zookeeper_1 ... done
2022-06-01 10:32:01.346  INFO 70769 --- [ream--492279488] 🐳 [docker/compose:1.29.2]               : STDERR: Creating c2lkjrlr6um5_kafka_1     ... 
2022-06-01 10:32:01.346  INFO 70769 --- [ream--492279488] 🐳 [docker/compose:1.29.2]               : STDERR: Creating c2lkjrlr6um5_kafka_1     ... done
2022-06-01 10:32:01.346  INFO 70769 --- [           main] 🐳 [docker/compose:1.29.2]               : Docker Compose has finished running
2022-06-01 10:32:01.347  INFO 70769 --- [           main] 🐳 [alpine/socat:1.7.4.3-r0]             : Creating container for image: alpine/socat:1.7.4.3-r0
2022-06-01 10:32:01.350 ERROR 70769 --- [           main] 🐳 [alpine/socat:1.7.4.3-r0]             : Could not start container

org.testcontainers.containers.ContainerLaunchException: Aborting attempt to link to container c2lkjr47cacj_kafka_1 as it is not running
        at org.testcontainers.containers.GenericContainer.applyConfiguration(GenericContainer.java:812)
        at org.testcontainers.containers.GenericContainer.tryStart(GenericContainer.java:374)
        at org.testcontainers.containers.GenericContainer.lambda$doStart$0(GenericContainer.java:340)
        at org.rnorth.ducttape.unreliables.Unreliables.retryUntilSuccess(Unreliables.java:81)
        at org.testcontainers.containers.GenericContainer.doStart(GenericContainer.java:338)
        at org.testcontainers.containers.GenericContainer.start(GenericContainer.java:326)
        at org.testcontainers.containers.DockerComposeContainer.startAmbassadorContainers(DockerComposeContainer.java:331)
        at org.testcontainers.containers.DockerComposeContainer.start(DockerComposeContainer.java:177)
        at org.testcontainers.junit.jupiter.TestcontainersExtension$StoreAdapter.start(TestcontainersExtension.java:242)
        at org.testcontainers.junit.jupiter.TestcontainersExtension$StoreAdapter.access$200(TestcontainersExtension.java:229)
        at org.testcontainers.junit.jupiter.TestcontainersExtension.lambda$null$1(TestcontainersExtension.java:59)
        at org.junit.jupiter.engine.execution.ExtensionValuesStore.lambda$getOrComputeIfAbsent$4(ExtensionValuesStore.java:86)
        at org.junit.jupiter.engine.execution.ExtensionValuesStore$MemoizingSupplier.computeValue(ExtensionValuesStore.java:223)
        at org.junit.jupiter.engine.execution.ExtensionValuesStore$MemoizingSupplier.get(ExtensionValuesStore.java:211)
        at org.junit.jupiter.engine.execution.ExtensionValuesStore$StoredValue.evaluate(ExtensionValuesStore.java:191)
        at org.junit.jupiter.engine.execution.ExtensionValuesStore$StoredValue.access$100(ExtensionValuesStore.java:171)
        at org.junit.jupiter.engine.execution.ExtensionValuesStore.getOrComputeIfAbsent(ExtensionValuesStore.java:89)
        at org.junit.jupiter.engine.execution.NamespaceAwareStore.getOrComputeIfAbsent(NamespaceAwareStore.java:53)
        at org.testcontainers.junit.jupiter.TestcontainersExtension.lambda$beforeAll$2(TestcontainersExtension.java:59)
        at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
        at org.testcontainers.junit.jupiter.TestcontainersExtension.beforeAll(TestcontainersExtension.java:59)
        at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeBeforeAllCallbacks$10(ClassBasedTestDescriptor.java:381)
        at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.invokeBeforeAllCallbacks(ClassBasedTestDescriptor.java:381)
        at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.before(ClassBasedTestDescriptor.java:205)
        at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.before(ClassBasedTestDescriptor.java:80)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:148)
        at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
        at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
        at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
        at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
        at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
        at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
        at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
        at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
        at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
        at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
        at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
        at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:220)
        at org.junit.platform.launcher.core.DefaultLauncher.lambda$execute$6(DefaultLauncher.java:188)
        at org.junit.platform.launcher.core.DefaultLauncher.withInterceptedStreams(DefaultLauncher.java:202)
        at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:181)
        at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:128)
        at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.invokeAllTests(JUnitPlatformProvider.java:150)
        at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.invoke(JUnitPlatformProvider.java:124)
        at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:384)
        at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:345)
        at org.apache.maven.surefire.booter.ForkedBooter.execute(ForkedBooter.java:126)
        at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:418)

You can see that the 2nd run is attempting to connect to the c2lkjr47cacj_kafka_1 container, which was the container name from the 1st run. Instead it should be trying to connect to c2lkjrlr6um5_kafka_1.

Is there some setting i’m missing in the configuration?

Issue Analytics

  • State:closed
  • Created a year ago
  • Reactions:1
  • Comments:28 (10 by maintainers)

github_iconTop GitHub Comments

1reaction
kiviewcommented, Oct 21, 2022

I don’t see a reason why it should not work with a non-confluent Kafka image, that follows a similar structure as the Confluent Kafka image. And since we are Testcontainers maintainers, it’s fine to at least try it out if we recommend it, the docs just mention the default image that will be used (and against which we test and integrate).

In Spring-Boot, but can use Testcontainers in a very convenient way for running your app locally following this pattern: https://bsideup.github.io/posts/local_development_with_testcontainers/

If you absolutely have to use Docker Compose, you have to somehow code your own abstraction that ensures the same stability as the KafkaContainer implementation (you can check the implementation: https://github.com/testcontainers/testcontainers-java/blob/main/modules/kafka/src/main/java/org/testcontainers/containers/KafkaContainer.java#L104).

1reaction
edeandreacommented, Oct 21, 2022

That may be a winner!

Read more comments on GitHub >

github_iconTop Results From Across the Web

How to reuse Testcontainers between multiple ...
You can't use the JUnit Jupiter annotation @Container if you want to have reusable containers. This annotation ensures to stop the container ...
Read more >
DB Integration Tests with Spring Boot and Testcontainers
Learn how to create powerful integration tests with Spring Boot and Testcontainers that connect to a dockerized database image.
Read more >
Waiting for containers to start or be ready - Testcontainers
Startup check Strategies. Ordinarily Testcontainers will check that the container has reached the running state and has not exited. In order to do...
Read more >
Use Docker Compose to work with multiple containers
Develop a multi-container app running in a Docker containers using Docker Compose and Visual Studio Code.
Read more >
Getting started with Testcontainers - Callista Enterprise AB
Spring Boot and Testcontainers; I can't run my application locally ... but many of them can be used without problems in your applications....
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found