Unable to Instantiate Docker Client for Testcontainers in Gradle Build

I'm working on a Kotlin project that uses Spring Boot, JOOQ for database code generation, and Testcontainers for integration testing with PostgreSQL. My build is managed with Gradle, and I am encountering an issue related to the Testcontainers setup.

Here is a portion of my build.gradle.kts configuration:

import org.jetbrains.kotlin.gradle.internal.KaptGenerateStubsTask
import org.testcontainers.containers.PostgreSQLContainer

val dbUsername = properties["db.username"] as? String ?: "user"
val dbPassword = properties["db.password"] as? String ?: "test"

plugins {
    id("org.springframework.boot") version "3.0.13"
    id("io.spring.dependency-management") version "1.1.5"
    kotlin("jvm") version "1.9.24"
    kotlin("plugin.spring") version "1.9.24"
    id("org.jooq.jooq-codegen-gradle") version "3.19.7"
    java
    idea
    application
}

group = "fr.test.data"
version = "0.0.1-SNAPSHOT"

java {
    sourceCompatibility = JavaVersion.VERSION_17
}

kotlin {
    jvmToolchain(17)
}

repositories {
    mavenLocal()
    mavenCentral()
}

dependencies {
    runtimeOnly("org.springframework.boot:spring-boot-devtools")

    implementation("org.springframework.boot:spring-boot-starter")
    implementation("org.springframework.boot:spring-boot-starter-jdbc")
    implementation("org.jooq:jooq:3.19.7")
    implementation("org.jooq:jooq-kotlin:3.19.7")
    implementation("org.jooq:jooq-jackson-extensions:3.19.7")

    implementation("org.postgresql:postgresql:42.7.3")
    implementation("org.jetbrains.kotlin:kotlin-reflect")
    implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")

    testImplementation("org.springframework.boot:spring-boot-starter-test") {
        exclude(group = "org.mockito")
    }

    implementation("org.springframework.boot:spring-boot-starter-logging")

    implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.14.3")
    implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.14.3")

    implementation("org.apache.commons:commons-collections4:4.5.0-M2")
    implementation("org.apache.commons:commons-compress:1.26.2")

    testImplementation("org.junit.jupiter:junit-jupiter:5.4.2")
    testImplementation("org.junit.platform:junit-platform-suite:1.9.2")
    testImplementation("org.junit.platform:junit-platform-launcher:1.9.2")
    testImplementation("org.testcontainers:testcontainers:1.19.7")
    testImplementation("org.testcontainers:junit-jupiter:1.19.7")
    testImplementation("org.testcontainers:postgresql:1.19.7")
    jooqCodegen("org.postgresql:postgresql:42.7.3")
    jooqCodegen("org.jooq:jooq-meta-extensions:3.19.7")
}

tasks.withType<Test> {
    useJUnitPlatform()
}

abstract class Containers : BuildService<Containers.Params>, AutoCloseable {

    interface Params : BuildServiceParameters {
        fun getUsername(): Property<String>
        fun getPassword(): Property<String>
    }

    val instance: PostgreSQLContainer<*> = PostgreSQLContainer("postgres:14-alpine")
        .withUsername(parameters.getUsername().get())
        .withPassword(parameters.getPassword().get())

    init {
        println("Starting containers...")
        instance.start()
        instance.execInContainer("bash", "-c", "printf '\\set AUTOCOMMIT on\\n CREATE DATABASE test;' | psql -U postgres")
    }

    override fun close() {
        println("Stopping containers...")
        instance.close()
    }
}

val containerProvider = project.gradle.sharedServices
    .registerIfAbsent("containers", Containers::class.java) {
        parameters.getUsername().set(dbUsername)
        parameters.getPassword().set(dbPassword)
    }

jooq {
    executions {
        create("test") {
            configuration {
                jdbc {
                    println("JOOQ is parsing its configuration...!")
                    username = dbUsername
                    password = dbPassword
                    url = containerProvider.get().instance.jdbcUrl + "/test"
                }
                generator {
                    name = "org.jooq.codegen.KotlinGenerator"
                    database {
                        name = "org.jooq.meta.postgres.PostgresDatabase"
                        inputSchema = "public"
                        includes = """
                            test_domain
                            """.trimIndent()
                            |eco_record_log|eco_record|eco_recipient|otc_storage_file|eco_record_object
                            """.trimIndent()
                    }
                    generate {
                        isRelations = true
                        isRoutines = true
                    }
                    target {
                        packageName = "fr.test.generated.jooq"
                    }
                }
            }
        }
    }
}

tasks.jooqCodegen {
    usesService(containerProvider)
    dependsOn("configureTestContainers", "update")
    mustRunAfter("configureTestContainers", "update")
    outputs.cacheIf { _ -> true }
}

tasks.register("update") {
    doLast {
        println("Running update task...")
        // Custom update logic here
    }
}

tasks.compileKotlin {
    dependsOn("jooqCodegen")
    mustRunAfter("jooqCodegen")
}

tasks.withType(KaptGenerateStubsTask::class.java).configureEach {
    dependsOn("jooqCodegen")
    mustRunAfter("jooqCodegen")
}

The Problem: When I run my build, I encounter the following error message related to the Docker environment used by Testcontainers:

Can't instantiate a strategy from org.testcontainers.dockerclient.NpipeSocketClientProviderStrategy (ClassNotFoundException). This probably means that cached configuration refers to a client provider class that is not available in this version of Testcontainers. Other strategies will be tried instead. 3 actionable tasks: 2 executed, 1 up-to-date Could not find a valid Docker environment. Please check configuration. Attempted configurations were: As no valid configuration was found, execution cannot continue. See https://java.testcontainers.org/on_failure.html for more details.

FAILURE: Build failed with an exception.

Failed to create service 'containers'. Could not create an instance of type Build_gradle$Containers. > Could not find a valid Docker environment. Please see logs and check configuration

Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights. Get more help at https://help.gradle.org.

BUILD FAILED in 571ms

Question: What could be causing this issue with Testcontainers failing to find a valid Docker environment, and how can I resolve it to successfully run my build?

Docker Setup: Verified that Docker is installed and running correctly on my machine. Testcontainers Version: Checked that the Testcontainers version is compatible with the Docker version. Environment Variables: Confirmed that DOCKER_HOST and other related environment variables are correctly set. Gradle Caching: Cleared Gradle caches with ./gradlew clean and retried the build.

Upvotes: 1

Views: 77

Answers (0)

Related Questions