diff --git a/core/src/main/java/org/testcontainers/utility/RyukResourceReaper.java b/core/src/main/java/org/testcontainers/utility/RyukResourceReaper.java index 7e1b7802fb0..a9be4dc371c 100644 --- a/core/src/main/java/org/testcontainers/utility/RyukResourceReaper.java +++ b/core/src/main/java/org/testcontainers/utility/RyukResourceReaper.java @@ -77,18 +77,20 @@ private synchronized void maybeStart() { ryukContainer.start(); - Runtime - .getRuntime() - .addShutdownHook( - new Thread( - DockerClientFactory.TESTCONTAINERS_THREAD_GROUP, - () -> { - this.dockerClient.killContainerCmd(this.ryukContainer.getContainerId()) - .withSignal("SIGTERM") - .exec(); - } - ) - ); + if (TestcontainersConfiguration.getInstance().isRyukShutdownHookEnabled()) { + Runtime + .getRuntime() + .addShutdownHook( + new Thread( + DockerClientFactory.TESTCONTAINERS_THREAD_GROUP, + () -> { + this.dockerClient.killContainerCmd(this.ryukContainer.getContainerId()) + .withSignal("SIGTERM") + .exec(); + } + ) + ); + } CountDownLatch ryukScheduledLatch = new CountDownLatch(1); diff --git a/core/src/main/java/org/testcontainers/utility/TestcontainersConfiguration.java b/core/src/main/java/org/testcontainers/utility/TestcontainersConfiguration.java index 921e36f80cd..37c887950ba 100644 --- a/core/src/main/java/org/testcontainers/utility/TestcontainersConfiguration.java +++ b/core/src/main/java/org/testcontainers/utility/TestcontainersConfiguration.java @@ -179,6 +179,10 @@ public boolean isDisableChecks() { return Boolean.parseBoolean(getEnvVarOrUserProperty("checks.disable", "false")); } + public boolean isRyukShutdownHookEnabled() { + return Boolean.parseBoolean(getEnvVarOrUserProperty("ryuk.container.shutdownhook", "false")); + } + @UnstableAPI public boolean environmentSupportsReuse() { // specifically not supported as an environment variable or classpath property diff --git a/core/src/test/java/org/testcontainers/utility/TestcontainersConfigurationTest.java b/core/src/test/java/org/testcontainers/utility/TestcontainersConfigurationTest.java index fcc0a654ef5..80163859b82 100644 --- a/core/src/test/java/org/testcontainers/utility/TestcontainersConfigurationTest.java +++ b/core/src/test/java/org/testcontainers/utility/TestcontainersConfigurationTest.java @@ -225,6 +225,35 @@ public void shouldTrimImageNames() { .isEqualTo("testcontainers/ryuk:0.3.2"); } + @Test + public void shouldNotReadRyukShutdownHookClasspathProperties() { + assertThat(newConfig().isRyukShutdownHookEnabled()).as("Ryuk shutdown hook disabled by default").isFalse(); + + classpathProperties.setProperty("ryuk.container.shutdownhook", "true"); + assertThat(newConfig().isRyukShutdownHookEnabled()) + .as("Ryuk shutdown hook is not affected by classpath properties") + .isFalse(); + } + + @Test + public void shouldReadRyukShutdownHookFromUserProperties() { + assertThat(newConfig().isRyukShutdownHookEnabled()).as("Ryuk shutdown hook disabled by default").isFalse(); + + userProperties.setProperty("ryuk.container.shutdownhook", "true"); + assertThat(newConfig().isRyukShutdownHookEnabled()) + .as("Ryuk shutdown hook enabled via user properties") + .isTrue(); + } + + @Test + public void shouldReadRyukShutdownHookFromEnvironment() { + assertThat(newConfig().isRyukShutdownHookEnabled()).as("Ryuk shutdown hook disabled by default").isFalse(); + + userProperties.remove("ryuk.container.shutdownhook"); + environment.put("TESTCONTAINERS_RYUK_CONTAINER_SHUTDOWNHOOK", "true"); + assertThat(newConfig().isRyukShutdownHookEnabled()).as("Ryuk shutdown hook enabled via env var").isTrue(); + } + private TestcontainersConfiguration newConfig() { return new TestcontainersConfiguration(userProperties, classpathProperties, environment); } diff --git a/docs/features/configuration.md b/docs/features/configuration.md index d874b16ad7b..55dad090969 100644 --- a/docs/features/configuration.md +++ b/docs/features/configuration.md @@ -79,13 +79,16 @@ Some companies disallow the usage of Docker Hub, but you can override `*.image` > **ryuk.container.privileged = true** > In some environments ryuk must be started in privileged mode to work properly (--privileged flag) +> **ryuk.container.shutdownhook = true** +> In order to improve the termination process you may configure a shutdown hook which will send a SIGTERM to the Ryuk container causing it to finish sooner. + ### Disabling Ryuk Ryuk must be started as a privileged container. If your environment already implements automatic cleanup of containers after the execution, but does not allow starting privileged containers, you can turn off the Ryuk container by setting `TESTCONTAINERS_RYUK_DISABLED` **environment variable** to `true`. -!!!tip +!!! tip Note that Testcontainers will continue doing the cleanup at JVM's shutdown, unless you `kill -9` your JVM process. ## Customizing image pull behaviour