Skip to content

Honour stop-services and remove-volumes when Compose Dev Services exit - #56463

Open
jnbdz wants to merge 1 commit into
quarkusio:mainfrom
SiteNetSoft:compose-devservices-ryuk-keeps-config
Open

Honour stop-services and remove-volumes when Compose Dev Services exit#56463
jnbdz wants to merge 1 commit into
quarkusio:mainfrom
SiteNetSoft:compose-devservices-ryuk-keeps-config

Conversation

@jnbdz

@jnbdz jnbdz commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

The compose project is registered with the Testcontainers Ryuk resource reaper by its com.docker.compose.project label. Ryuk removes every resource carrying that label when the application exits (containers, networks, volumes and images) and cannot spare some of them, so quarkus.compose.devservices.remove-volumes=false still lost the volumes and, as @ozangunalp noted, stop-services=false still had the services stopped. Reproduced with a compose file declaring a named volume: about fifteen seconds after a @QuarkusTest JVM exits, the container and the volume are gone despite remove-volumes=false.

While reproducing, a second thing showed up: the running compose service is closed through the curated application's close tasks, which do not run at the end of a test JVM, so in tests Ryuk was the only thing stopping the services; compose down never ran. Skipping Ryuk alone would therefore have left the containers running after tests.

Changes:

  • the project is registered with Ryuk only when both stop-services and remove-volumes are enabled, i.e. when everything Ryuk would remove is meant to be removed anyway; otherwise a log line says why Ryuk is not used;
  • in test mode, compose down is run from a JVM shutdown hook when stop-services is enabled, so services are stopped and volumes handled according to the configuration in every mode;
  • the property docs and the guide say what Ryuk does and that it is not used when either flag is off, and that keeping volumes across test runs needs a stable project name.

Verified with rootless Podman and a @QuarkusTest, checking podman ps -a / podman volume ls after the JVM exit:

configuration main this PR
default container and volume removed by Ryuk after ~15 s removed by compose down -v at exit (and Ryuk still registered)
remove-volumes=false container and volume removed by Ryuk container removed by compose down at exit, volume kept
stop-services=false services stopped by Ryuk after ~15 s services keep running, volume kept

ComposeProjectTest gets a case for the Ryuk condition; extensions/devservices/deployment is green (22). integration-tests/compose-devservices passed 5/6 with the change (the RabbitMQ test failed on a Podman API "Broken pipe" creating a Redis container and passes alone); a later rerun of that module fails the same way on main on this machine, so that is the local Podman service, not the change.

@quarkus-bot

This comment has been minimized.

@github-actions

github-actions Bot commented Sep 6, 2026

Copy link
Copy Markdown

🎊 PR Preview adc1eb1 has been successfully built and deployed to https://quarkus-pr-main-56463-preview.surge.sh/version/main/guides/

  • Images of blog posts older than 3 months are not available.
  • Newsletters older than 3 months are not available.

@quarkus-bot

This comment has been minimized.

The compose project was always registered with the Testcontainers Ryuk
resource reaper, which removes every resource labelled with the project
when the application exits: containers, networks, volumes and images,
with no way to spare some of them. So volumes were removed even with
quarkus.compose.devservices.remove-volumes=false, and services were
stopped even with stop-services=false.

Only register the project with Ryuk when the configuration asks for
the services and their volumes to be removed anyway, and say so in the
log otherwise. The running services are closed when the curated
application is closed, which does not happen at the end of a test run,
so Ryuk was also what stopped the services after tests: run compose
down from a JVM shutdown hook in test mode, so that the services are
stopped and the volumes handled according to the configuration in every
mode.

Fixes quarkusio#47980
@jnbdz
jnbdz force-pushed the compose-devservices-ryuk-keeps-config branch from 3d9878a to 47df5cc Compare September 7, 2026 15:33
@quarkus-bot

quarkus-bot Bot commented Sep 7, 2026

Copy link
Copy Markdown

Status for workflow Quarkus Documentation CI

This is the status report for running Quarkus Documentation CI on commit 47df5cc.

✅ The latest workflow run for the pull request has completed successfully.

It should be safe to merge provided you have a look at the other checks in the summary.

Warning

There are other workflow runs running, you probably need to wait for their status before merging.

@quarkus-bot

quarkus-bot Bot commented Sep 7, 2026

Copy link
Copy Markdown

Status for workflow Quarkus CI

This is the status report for running Quarkus CI on commit 47df5cc.

✅ The latest workflow run for the pull request has completed successfully.

It should be safe to merge provided you have a look at the other checks in the summary.

You can consult the Develocity build scans.


Flaky tests - Develocity

⚙️ JVM Tests - JDK 25

📦 extensions/redis-client/runtime

io.quarkus.redis.datasource.PubSubCommandsTest.testMultipleSubscribersAndBiConsumer - History

  • io.smallrye.mutiny.TimeoutException
Details
io.smallrye.mutiny.TimeoutException
	at io.smallrye.mutiny.operators.uni.UniBlockingAwait.await(UniBlockingAwait.java:65)
	at io.smallrye.mutiny.groups.UniAwait.atMost(UniAwait.java:76)
	at io.quarkus.redis.runtime.datasource.BlockingPubSubCommandsImpl.subscribe(BlockingPubSubCommandsImpl.java:76)
	at io.quarkus.redis.runtime.datasource.BlockingPubSubCommandsImpl.subscribe(BlockingPubSubCommandsImpl.java:53)
	at io.quarkus.redis.runtime.datasource.BlockingPubSubCommandsImpl.subscribe(BlockingPubSubCommandsImpl.java:31)
	at io.quarkus.redis.datasource.PubSubCommandsTest.testMultipleSubscribersAndBiConsumer(PubSubCommandsTest.java:148)

⚙️ JVM Tests - JDK 25 Semeru

📦 extensions/vertx-http/deployment

io.quarkus.vertx.http.http2.Http2RSTFloodProtectionTest.testRstFloodProtectionWithTlsEnabled - History

  • RST flood protection failed - org.opentest4j.AssertionFailedError
Details
org.opentest4j.AssertionFailedError: RST flood protection failed
	at org.junit.jupiter.api.Assertions.fail(Assertions.java:142)
	at io.quarkus.vertx.http.http2.Http2RSTFloodProtectionTest.run(Http2RSTFloodProtectionTest.java:112)
	at io.quarkus.vertx.http.http2.Http2RSTFloodProtectionTest.testRstFloodProtectionWithTlsEnabled(Http2RSTFloodProtectionTest.java:78)

⚙️ JVM Tests - JDK 21 Windows

📦 extensions/vertx-http/deployment

io.quarkus.vertx.http.filters.GracefulShutdownFilterTest.test - History

  • Timeout waiting for response - java.lang.RuntimeException
Details
java.lang.RuntimeException: Timeout waiting for response
	at io.quarkus.vertx.http.filters.GracefulShutdownFilterTest.testWithVertxHttpClientAndHttp2AfterShutdown(GracefulShutdownFilterTest.java:85)
	at io.quarkus.vertx.http.filters.GracefulShutdownFilterTest.test(GracefulShutdownFilterTest.java:59)

⚙️ JVM Integration Tests - JDK 25

📦 integration-tests/reactive-messaging-kafka

io.quarkus.it.kafka.KafkaConnectorTest.testDataForKeyed - History

  • Assertion condition defined as a Lambda expression in io.quarkus.it.kafka.KafkaConnectorTest expected: <3> but was: <0> within 10 seconds. - org.awaitility.core.ConditionTimeoutException
Details
org.awaitility.core.ConditionTimeoutException: Assertion condition defined as a Lambda expression in io.quarkus.it.kafka.KafkaConnectorTest expected: <3> but was: <0> within 10 seconds.
	at org.awaitility.core.ConditionAwaiter.await(ConditionAwaiter.java:167)
	at org.awaitility.core.AssertionCondition.await(AssertionCondition.java:119)
	at org.awaitility.core.AssertionCondition.await(AssertionCondition.java:31)
	at org.awaitility.core.ConditionFactory.until(ConditionFactory.java:1160)
	at org.awaitility.core.ConditionFactory.untilAsserted(ConditionFactory.java:790)
	at io.quarkus.it.kafka.KafkaConnectorTest.testDataForKeyed(KafkaConnectorTest.java:78)
Caused by: org.opentest4j.AssertionFailedError: expected: <3> but was: <0>

io.quarkus.it.kafka.KafkaConnectorTest.testDataWithMetadata - History

  • Assertion condition defined as a Lambda expression in io.quarkus.it.kafka.KafkaConnectorTest expected: <3> but was: <0> within 10 seconds. - org.awaitility.core.ConditionTimeoutException
Details
org.awaitility.core.ConditionTimeoutException: Assertion condition defined as a Lambda expression in io.quarkus.it.kafka.KafkaConnectorTest expected: <3> but was: <0> within 10 seconds.
	at org.awaitility.core.ConditionAwaiter.await(ConditionAwaiter.java:167)
	at org.awaitility.core.AssertionCondition.await(AssertionCondition.java:119)
	at org.awaitility.core.AssertionCondition.await(AssertionCondition.java:31)
	at org.awaitility.core.ConditionFactory.until(ConditionFactory.java:1160)
	at org.awaitility.core.ConditionFactory.untilAsserted(ConditionFactory.java:790)
	at io.quarkus.it.kafka.KafkaConnectorTest.testDataWithMetadata(KafkaConnectorTest.java:65)
Caused by: org.opentest4j.AssertionFailedError: expected: <3> but was: <0>

io.quarkus.it.kafka.KafkaConnectorTest.testPets - History

  • Assertion condition defined as a Lambda expression in io.quarkus.it.kafka.KafkaConnectorTest expected: <0> but was: <3> within 10 seconds. - org.awaitility.core.ConditionTimeoutException
Details
org.awaitility.core.ConditionTimeoutException: Assertion condition defined as a Lambda expression in io.quarkus.it.kafka.KafkaConnectorTest expected: <0> but was: <3> within 10 seconds.
	at org.awaitility.core.ConditionAwaiter.await(ConditionAwaiter.java:167)
	at org.awaitility.core.AssertionCondition.await(AssertionCondition.java:119)
	at org.awaitility.core.AssertionCondition.await(AssertionCondition.java:31)
	at org.awaitility.core.ConditionFactory.until(ConditionFactory.java:1160)
	at org.awaitility.core.ConditionFactory.untilAsserted(ConditionFactory.java:790)
	at io.quarkus.it.kafka.KafkaConnectorTest.testPets(KafkaConnectorTest.java:44)
Caused by: java.util.concurrent.TimeoutException
  • Assertion condition defined as a Lambda expression in io.quarkus.it.kafka.KafkaConnectorTest expected: <6> but was: <3> within 10 seconds. - org.awaitility.core.ConditionTimeoutException
Details
org.awaitility.core.ConditionTimeoutException: Assertion condition defined as a Lambda expression in io.quarkus.it.kafka.KafkaConnectorTest expected: <6> but was: <3> within 10 seconds.
	at org.awaitility.core.ConditionAwaiter.await(ConditionAwaiter.java:167)
	at org.awaitility.core.AssertionCondition.await(AssertionCondition.java:119)
	at org.awaitility.core.AssertionCondition.await(AssertionCondition.java:31)
	at org.awaitility.core.ConditionFactory.until(ConditionFactory.java:1160)
	at org.awaitility.core.ConditionFactory.untilAsserted(ConditionFactory.java:790)
	at io.quarkus.it.kafka.KafkaConnectorTest.testPets(KafkaConnectorTest.java:44)
Caused by: org.opentest4j.AssertionFailedError: expected: <6> but was: <3>

io.quarkus.it.kafka.KafkaConnectorTest.testRequestReply - History

  • iterable contents differ at index [0], expected: <reply-1> but was: <{"details":"Error id 5cf34bd9-35b4-4d5a-9515-01b1449507b4-1, org.jboss.resteasy.spi.UnhandledException: io.smallrye.reactive.messaging.kafka.reply.KafkaRequestReplyTimeoutException: Timeout waiting for a reply for request with correlation ID: 0f0ad6f8-be33-4254-bc84-af2f5f383cf3","stack":"org.jboss.resteasy.spi.UnhandledException: io.smallrye.reactive.messaging.kafka.reply.KafkaRequestReplyTimeoutException: Timeout waiting for a reply for request with correlation ID: 0f0ad6f8-be33-4254-bc84-af2f5f383cf3\n\tat org.jboss.resteasy.core.ExceptionHandler.handleApplicationException(ExceptionHandler.java:107)\n\tat org.jboss.resteasy.core.ExceptionHandler.handleException(ExceptionHandler.java:344)\n\tat org.jboss.resteasy.core.SynchronousDispatcher.writeException(SynchronousDispatcher.java:210)\n\tat org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:457)\n\tat org.jboss.resteasy.core.Synchron... - org.opentest4j.AssertionFailedError
Details
org.opentest4j.AssertionFailedError: iterable contents differ at index [0], expected: <reply-1> but was: <{"details":"Error id 5cf34bd9-35b4-4d5a-9515-01b1449507b4-1, org.jboss.resteasy.spi.UnhandledException: io.smallrye.reactive.messaging.kafka.reply.KafkaRequestReplyTimeoutException: Timeout waiting for a reply for request with correlation ID: 0f0ad6f8-be33-4254-bc84-af2f5f383cf3","stack":"org.jboss.resteasy.spi.UnhandledException: io.smallrye.reactive.messaging.kafka.reply.KafkaRequestReplyTimeoutException: Timeout waiting for a reply for request with correlation ID: 0f0ad6f8-be33-4254-bc84-af2f5f383cf3\n\tat org.jboss.resteasy.core.ExceptionHandler.handleApplicationException(ExceptionHandler.java:107)\n\tat org.jboss.resteasy.core.ExceptionHandler.handleException(ExceptionHandler.java:344)\n\tat org.jboss.resteasy.core.SynchronousDispatcher.writeException(SynchronousDispatcher.java:210)\n\tat org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:457)\n...

⚙️ JVM Integration Tests - JDK 25 Semeru

📦 integration-tests/keycloak-authorization

io.quarkus.it.keycloak.StaticTenantConfigPolicyEnforcerTest.testUserHasSuperUserRoleWebTenantWithMatrix - History

  • expected: <true> but was: <false> - org.opentest4j.AssertionFailedError
Details
org.opentest4j.AssertionFailedError: expected: <true> but was: <false>
	at io.quarkus.it.keycloak.AbstractPolicyEnforcerTest.testWebAppTenantAllowed(AbstractPolicyEnforcerTest.java:128)
	at io.quarkus.it.keycloak.AbstractPolicyEnforcerTest.testUserHasSuperUserRoleWebTenantWithMatrix(AbstractPolicyEnforcerTest.java:110)
	at java.base/java.lang.reflect.Method.invoke(Method.java:571)
	at io.quarkus.test.junit.QuarkusTestExtension.runExtensionMethod(QuarkusTestExtension.java:1005)
	at io.quarkus.test.junit.QuarkusTestExtension.interceptTestMethod(QuarkusTestExtension.java:852)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1604)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1604)

@gsmet
gsmet requested a review from ozangunalp September 8, 2026 13:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Compose Devservices config property misalignment.

1 participant