testcontainers/testcontainers-java · warning

Testcontainers may not be able to clean up networks spawned…

Error message

Testcontainers may not be able to clean up networks spawned using Docker Compose v2.0 files. Please see https://github.com/testcontainers/moby-ryuk/issues/2, and specify 'version: "2.1"' or higher in {}

What it means

ParsedDockerComposeFile.parseAndValidate() warns when a compose file declares `version: "2.0"`. Compose 2.0 files lack the network metadata Testcontainers' resource reaper (moby-ryuk) needs, so networks spawned from such files may be leaked and never cleaned up. The warning points users to pin version 2.1 or higher.

Solutions

  1. Edit the compose file to declare version: "2.1" or higher (or omit `version` entirely for Compose v2 spec files).
  2. Verify the container definitions still work under the newer compose file format.
  3. Re-run the tests and confirm Ryuk can clean up the spawned networks.

Example fix

# before
version: "2.0"
services:
  db:
    image: postgres:13
# after
version: "2.4"
services:
  db:
    image: postgres:13
Defensive patterns

Strategy: validation

Validate before calling

final String version = (String) yaml.get("version");
if ("2.0".equals(version)) {
    throw new IllegalStateException("Compose file uses deprecated 2.0; bump to 2.1+ for Ryuk network cleanup");
}

Prevention

When it happens

Trigger: Parsing (constructing ParsedDockerComposeFile, which calls parseAndValidate) a docker-compose file whose YAML top-level `version` key equals the string "2.0".

Common situations: Old projects with legacy compose files pinned to "2.0" used with DockerComposeContainer; copies of very old example compose files; files copied from tutorials predating 2.1.

Related errors


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

Appendix: source

Thrown at core/src/main/java/org/testcontainers/containers/ParsedDockerComposeFile.java:82

        }
        this.composeFileName = composeFile.getAbsolutePath();
        this.composeFile = composeFile;
        parseAndValidate();
    }

    @VisibleForTesting
    ParsedDockerComposeFile(Map<String, Object> testContent) {
        this.composeFileContent = testContent;
        this.composeFileName = "";
        this.composeFile = new File(".");

        parseAndValidate();
    }

    private void parseAndValidate() {
        final Map<String, ?> servicesMap;
        if (composeFileContent.containsKey("version") && "2.0".equals(composeFileContent.get("version"))) {
            log.warn(
                "Testcontainers may not be able to clean up networks spawned using Docker Compose v2.0 files. " +
                "Please see https://github.com/testcontainers/moby-ryuk/issues/2, and specify 'version: \"2.1\"' or " +
                "higher in {}",
                composeFileName
            );
        }

        if (composeFileContent.containsKey("services")) {
            final Object servicesElement = composeFileContent.get("services");
            if (servicesElement == null) {
                log.debug(
                    "Compose file {} has an unknown format: 'version' is set but 'services' is not defined",
                    composeFileName
                );
                return;
            }
            if (!(servicesElement instanceof Map)) {
                log.debug("Compose file {} has an unknown format: 'services' is not Map", composeFileName);

View on GitHub (pinned to 8e549514e3)