testcontainers/testcontainers-java · warning

Ryuk has been disabled. This can cause unexpected behavior…

Error message

Ryuk has been disabled. This can cause unexpected behavior in your environment.

What it means

ResourceReaper.instance() warns when Ryuk (the Testcontainers cleanup sidecar container) is disabled via ryuk.disabled=true. Without Ryuk, containers/volumes created by tests are only cleaned by JVM shutdown hooks, which don't run if the JVM is killed — leaving orphaned Docker resources and possibly rate-limit/disk pressure.

Solutions

  1. Re-enable Ryuk (remove TESTCONTAINERS_RYUK_DISABLED / ryuk.disabled) and fix whatever prevented the Ryuk container from starting
  2. If Ryuk cannot run, ensure the JVM shuts down cleanly (SIGTERM, not SIGKILL) so shutdown hooks reap resources
  3. Periodically run `docker system prune` or Testcontainers' ResourceReaper.instance().performCleanup() manually

Example fix

// before (testcontainers.properties)
ryuk.disabled=true
// after: remove the line, or set explicitly
ryuk.disabled=false
Defensive patterns

Strategy: fallback

Validate before calling

String ryukDisabled = System.getenv("TESTCONTAINERS_RYUK_DISABLED");
if ("true".equals(ryukDisabled)) {
    log.warn("Ryuk disabled — schedule docker system prune or clean shutdown hooks");
}

Try / catch

Runtime.getRuntime().addShutdownHook(new Thread(() -> {
    try {
        org.testcontainers.utility.ResourceReaper.instance().performCleanup();
    } catch (Exception e) {
        log.warn("manual cleanup failed", e);
    }
}));

Prevention

When it happens

Trigger: TESTCONTAINERS_RYUK_DISABLED=true env var or ryuk.disabled=true in testcontainers.properties when any Testcontainers resource is created and instance() initializes the reaper.

Common situations: CI environments disabling Ryuk to avoid privilege/socket-mount issues (e.g. some GitLab/Dind setups); devs copying CI config locally; environments where Ryuk container fails to start so users disable it.

Understand the failure class

Background: "not installed", "pip install", "required for": how missing-dependency errors surface across open-source libraries — this error's family across 34 libraries.

Related errors


AI-assisted analysis of testcontainers/testcontainers-java@8e549514e3 (2026-09-12). Data as JSON: /api/errors/93fcdaa3d3410e1e. Report an issue: GitHub.

Appendix: source

Thrown at core/src/main/java/org/testcontainers/utility/ResourceReaper.java:89

     * Internal constructor to avoid custom implementations
     */
    ResourceReaper() {}

    public static synchronized ResourceReaper instance() {
        if (instance == null) {
            boolean useRyuk = !Boolean.parseBoolean(System.getenv("TESTCONTAINERS_RYUK_DISABLED"));
            if (useRyuk) {
                //noinspection deprecation
                instance = new RyukResourceReaper();
            } else {
                String ryukDisabledMessage =
                    "\n" +
                    "********************************************************************************" +
                    "\n" +
                    "Ryuk has been disabled. This can cause unexpected behavior in your environment." +
                    "\n" +
                    "********************************************************************************";
                LOGGER.warn(ryukDisabledMessage);

                instance = new JVMHookResourceReaper();
            }
        }

        return instance;
    }

    /**
     * Perform a cleanup.
     * @deprecated no longer supported API, use {@link DockerClient} directly
     */
    @Deprecated
    public void performCleanup() {
        registeredContainers.forEach(this::removeContainer);
        registeredNetworks.forEach(this::removeNetwork);
        registeredImages.forEach(this::removeImage);
    }

View on GitHub (pinned to 8e549514e3)