You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在JUnit Testcontainers中为OpenSearch使用自定义Dockerfile

解决方案:在Testcontainers中使用带analysis-phonetic插件的自定义OpenSearch镜像

方法一:预构建自定义镜像并复用

这是最直接的方案,基于官方镜像构建自定义镜像后,直接用OpenSearchContainer引用,保留官方容器的所有便捷特性。

  1. 构建自定义镜像
    在Dockerfile所在目录执行命令:
docker build -t my-opensearch:2.11.1-phonetic .
  1. 修改测试配置代码
class TestConfiguration : ApplicationContextInitializer<ConfigurableApplicationContext> {
    val container = OpensearchContainer(
        DockerImageName.parse("my-opensearch:2.11.1-phonetic")
    )

    override fun initialize(applicationContext: ConfigurableApplicationContext) {
        container.start()

        TestPropertySourceUtils.addInlinedPropertiesToEnvironment(
            applicationContext,
            "opensearch.username=${container.username}",
            "opensearch.password=${container.password}",
            "opensearch.host=${container.host}",
            "opensearch.scheme=http",
            "opensearch.port=${container.firstMappedPort}",
        )
    }
}

自定义镜像基于官方镜像构建,因此OpenSearchContainer的username、password等便捷方法完全可用,和官方镜像用法一致。

方法二:Testcontainers动态构建自定义镜像

如果不想预先手动构建镜像,可让Testcontainers自动构建并缓存镜像。

方案A:结合ImageFromDockerfile与OpenSearchContainer

class TestConfiguration : ApplicationContextInitializer<ConfigurableApplicationContext> {
    // 动态生成自定义镜像
    val customImage = ImageFromDockerfile()
        .withDockerfileContent("""
            FROM opensearchproject/opensearch:2.11.1
            RUN bin/opensearch-plugin install analysis-phonetic
        """.trimIndent())
        .withTag("my-opensearch:test")

    val container = OpensearchContainer(customImage)

    override fun initialize(applicationContext: ConfigurableApplicationContext) {
        container.start()

        TestPropertySourceUtils.addInlinedPropertiesToEnvironment(
            applicationContext,
            "opensearch.username=${container.username}",
            "opensearch.password=${container.password}",
            "opensearch.host=${container.host}",
            "opensearch.scheme=http",
            "opensearch.port=${container.firstMappedPort}",
        )
    }
}

Testcontainers会自动构建镜像并缓存,后续测试直接复用缓存版本,无需重复构建。

方案B:使用GenericContainer手动配置

如果OpenSearchContainer无法适配动态镜像,可直接用GenericContainer,利用官方镜像默认凭据配置:

class TestConfiguration : ApplicationContextInitializer<ConfigurableApplicationContext> {
    val container = GenericContainer(
        ImageFromDockerfile()
            .withDockerfileContent("""
                FROM opensearchproject/opensearch:2.11.1
                RUN bin/opensearch-plugin install analysis-phonetic
            """.trimIndent())
    )
        .withExposedPorts(9200)
        .withEnv("discovery.type", "single-node")
        .withEnv("plugins.security.disabled", "false")

    // 官方镜像默认用户名密码固定为admin/admin
    private val defaultUsername = "admin"
    private val defaultPassword = "admin"

    override fun initialize(applicationContext: ConfigurableApplicationContext) {
        container.start()

        TestPropertySourceUtils.addInlinedPropertiesToEnvironment(
            applicationContext,
            "opensearch.username=$defaultUsername",
            "opensearch.password=$defaultPassword",
            "opensearch.host=${container.host}",
            "opensearch.scheme=http",
            "opensearch.port=${container.getMappedPort(9200)}",
        )
    }
}

若需自定义密码,可添加环境变量withEnv("OPENSEARCH_INITIAL_ADMIN_PASSWORD", "your-custom-password")。

方法三:修复DockerComposeContainer配置问题

若之前使用DockerComposeContainer失败,检查路径与配置:

  1. 编写docker-compose.yml(放在src/test/resources目录下)
version: '3.8'
services:
  opensearch:
    build: . # 指向Dockerfile所在目录
    ports:
      - "9200:9200"
    environment:
      - discovery.type=single-node
      - plugins.security.disabled=false
  1. 测试配置代码
class TestConfiguration : ApplicationContextInitializer<ConfigurableApplicationContext> {
    val composeContainer = DockerComposeContainer(File("src/test/resources/docker-compose.yml"))
        .withExposedService("opensearch", 9200)

    override fun initialize(applicationContext: ConfigurableApplicationContext) {
        composeContainer.start()

        val opensearchService = composeContainer.getService("opensearch")
        TestPropertySourceUtils.addInlinedPropertiesToEnvironment(
            applicationContext,
            "opensearch.username=admin",
            "opensearch.password=admin",
            "opensearch.host=${opensearchService.host}",
            "opensearch.scheme=http",
            "opensearch.port=${opensearchService.getMappedPort(9200)}",
        )
    }
}

多模块项目需调整docker-compose.yml的文件路径,确保Testcontainers能正确加载。

内容的提问来源于stack exchange,提问作者Crell

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 03:52:42