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

配置Minio Testcontainers修改默认端口解决集群端口冲突

解决方案:修改Minio Testcontainer端口避免冲突

方案1:保持Minio内部端口不变,修改Testcontainer端口映射(推荐)

Minio容器默认内部监听9000端口,无需修改这个核心配置,只需让Testcontainer自动分配或指定未被占用的外部端口,同时确保客户端连接映射后的正确地址即可。

修改你的MinioContainer类:

public class MinioContainer extends GenericContainer<MinioContainer> {

    // Minio容器内部默认端口,保持不变
    private static final int MINIO_INTERNAL_PORT = 9000;
    private static final String DEFAULT_IMAGE = "minio/minio";
    private static final String DEFAULT_TAG = "latest";

    private static final String MINIO_ACCESS_KEY = "MINIO_ACCESS_KEY";
    private static final String MINIO_SECRET_KEY = "MINIO_SECRET_KEY";

    private static final String DEFAULT_STORAGE_DIRECTORY = "/data";
    private static final String HEALTH_ENDPOINT = "/minio/health/ready";

    public MinioContainer() {
        this(DEFAULT_IMAGE + ":" + DEFAULT_TAG);
    }

    public MinioContainer(String image) {
        super(image == null ? DEFAULT_IMAGE + ":" + DEFAULT_TAG : image);
        Network network = Network.newNetwork();
        withNetwork(network);
        withNetworkAliases("minio-" + Base58.randomString(6));
        // 暴露容器内部9000端口,Testcontainer自动映射到宿主机未占用端口
        addExposedPort(MINIO_INTERNAL_PORT);
        withEnv(MINIO_ACCESS_KEY, "access_key");
        withEnv(MINIO_SECRET_KEY, "secret_key");
        withCommand("server", DEFAULT_STORAGE_DIRECTORY);
        setWaitStrategy(new HttpWaitStrategy()
                .forPort(MINIO_INTERNAL_PORT) // 健康检查针对容器内部端口
                .forPath(HEALTH_ENDPOINT)
                .withStartupTimeout(Duration.ofMinutes(1)));
    }

    public String getHostAddress() {
        // 返回宿主机地址+映射后的外部端口
        return getHost() + ":" + getMappedPort(MINIO_INTERNAL_PORT);
    }
}

在Spring Boot测试中动态注入配置,避免硬编码端口:

@SpringBootTest
public class MinioTest {

    @Container
    private static final MinioContainer minioContainer = new MinioContainer();

    @DynamicPropertySource
    static void setProperties(DynamicPropertyRegistry registry) {
        registry.add("spring.minio.url", () -> "http://" + minioContainer.getHostAddress());
        registry.add("spring.minio.access-key", () -> "access_key");
        registry.add("spring.minio.secret-key", () -> "secret_key");
    }

    private final String BUCKET = "bucket";
    
    @Autowired
    private MinioClient minioClient;

    @BeforeEach
    void setup() {
        boolean bucketExists = minioClient.bucketExists(BucketExistsArgs.builder().bucket(BUCKET).build());
        // 后续逻辑...
    }
}

该方案优势:

  • 无需修改Minio核心运行配置,避免额外复杂度
  • 自动规避端口冲突,适配集群环境
  • 健康检查逻辑正确,确保容器正常启动

方案2:修改Minio容器内部监听端口(仅特殊场景使用)

如果必须让Minio容器内部使用非9000端口,需通过启动参数指定端口,并同步调整Testcontainer配置:

public class MinioContainer extends GenericContainer<MinioContainer> {

    // 指定新的内部监听端口
    private static final int MINIO_INTERNAL_PORT = 9001;
    private static final String DEFAULT_IMAGE = "minio/minio";
    private static final String DEFAULT_TAG = "latest";

    private static final String MINIO_ACCESS_KEY = "MINIO_ACCESS_KEY";
    private static final String MINIO_SECRET_KEY = "MINIO_SECRET_KEY";

    private static final String DEFAULT_STORAGE_DIRECTORY = "/data";
    private static final String HEALTH_ENDPOINT = "/minio/health/ready";

    public MinioContainer() {
        this(DEFAULT_IMAGE + ":" + DEFAULT_TAG);
    }

    public MinioContainer(String image) {
        super(image == null ? DEFAULT_IMAGE + ":" + DEFAULT_TAG : image);
        Network network = Network.newNetwork();
        withNetwork(network);
        withNetworkAliases("minio-" + Base58.randomString(6));
        addExposedPort(MINIO_INTERNAL_PORT);
        withEnv(MINIO_ACCESS_KEY, "access_key");
        withEnv(MINIO_SECRET_KEY, "secret_key");
        // 通过--address参数指定Minio监听端口
        withCommand("server", "--address", ":" + MINIO_INTERNAL_PORT, DEFAULT_STORAGE_DIRECTORY);
        setWaitStrategy(new HttpWaitStrategy()
                .forPort(MINIO_INTERNAL_PORT)
                .forPath(HEALTH_ENDPOINT)
                .withStartupTimeout(Duration.ofMinutes(1)));
    }

    public String getHostAddress() {
        return getHost() + ":" + getMappedPort(MINIO_INTERNAL_PORT);
    }
}

同样需要通过@DynamicPropertySource动态注入客户端配置,确保连接地址正确。


你之前修改失败的原因

直接修改DEFAULT_PORT为非9000值,但Minio容器内部仍在默认的9000端口监听,导致:

  1. Testcontainer健康检查访问错误端口,找不到健康端点
  2. Minio客户端连接到集群中已占用9000端口的Minio服务,出现密钥不匹配错误

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 02:31:08