【问题标题】:Unable to Run Container Using testcontainers无法使用 testcontainers 运行容器
【发布时间】:2022-01-08 05:33:35
【问题描述】:

我正在尝试使用testcontainers (v1.16.2) 实现 JUnit (v4.13.2) 测试,以更好地测试我们的 DAO/JPA 类。我正在使用 centos/postgresql-96-centos7 官方 docker 映像,我可以在 cmd 行上运行它,使用:docker run -d --name postgres -e POSTGRESQL_USER=user -e POSTGRESQL_PASSWORD=pass -e POSTGRES_DATABASE=db -p 5432:5432 centos/postgresql-96-centos7。我在运行单元测试之前删除了容器,以避免在我的 docker 环境中出现任何冲突。但是,当我运行测试时,我始终收到以下错误:

java.lang.ExceptionInInitializerError
Caused by: org.testcontainers.containers.ContainerLaunchException: Container startup failed
Caused by: org.rnorth.ducttape.RetryCountExceededException: Retry limit hit with exception
Caused by: org.testcontainers.containers.ContainerLaunchException: Could not create/start container
Caused by: java.lang.IllegalStateException: Container exited with code 2

我尝试将超时值增加到 5 分钟并简化为 JUnit4 测试模式(以避免运行混合测试环境),但无济于事。我只包含抽象类的代码,因为它在调用POSTGRESQL_CONTAINER.start() 之前抛出异常。

public abstract class AbstractRdbmsTest {
    private static final String DOCKER_IMAGE_NAME = "centos/postgresql-96-centos7";
    private static final String POSTGRESQL_USER = "user";
    private static final String POSTGRESQL_PASSWORD = "pass";
    private static final String POSTGRESQL_DATABASE = "db";

    protected static final PostgreSQLContainer POSTGRESQL_CONTAINER;

    static {
        DockerImageName imgName = DockerImageName.parse(DOCKER_IMAGE_NAME).asCompatibleSubstituteFor("postgres");

        POSTGRESQL_CONTAINER = (PostgreSQLContainer) new PostgreSQLContainer(imgName)
                .withDatabaseName(POSTGRESQL_DATABASE)
                .withUsername(POSTGRESQL_USER)
                .withPassword(POSTGRESQL_PASSWORD)
                .withExposedPorts(PostgreSQLContainer.POSTGRESQL_PORT);

        POSTGRESQL_CONTAINER.start();
    }
}

编辑:本地 Docker 环境: 客户端/服务器:Docker 引擎 - Community v20.10.7

【问题讨论】:

  • 你尝试使用空构造函数(PostgreSQLContainer())还是 DOCKER_IMAGE_NAME 除了 imgName?
  • PostgreSQLContainer()PostgreSQLContainer(String imageName) 构造函数现在都已弃用;所以我避免使用它们。单步执行代码:它似乎可以很好地找到图像,但无论出于何种原因,它似乎都认为它没有正确启动。
  • 好像centos/postgresql-96-centos7镜像不兼容testcontainers,如果你看一下PostgreSQLContainer.java你会发现PostgreSQLContainer.java设置了另一个环境变量(POSTGRES_USER vs POSTGRESQL_USER)并期望“数据库系统已准备好接受连接”消息在容器日志中出现两次。
  • 好收获。我将进一步深入研究创建图像,看看我是否可以包装这个图像并提供正确的环境。虽然,我不确定如何回显 LOG 消息... 编辑:使用 GenericContainer 并构造 JDBC URL 对我来说可能是最好的... PITA。

标签: java docker junit junit4 testcontainers


【解决方案1】:

如上所述,似乎已经解决了以下问题:

public abstract class AbstractRdbmsTest {
    private static final String DOCKER_IMAGE_NAME = "centos/postgresql-96-centos7";
    private static final String POSTGRESQL_USER = "user";
    private static final String POSTGRESQL_PASSWORD = "pass";
    private static final String POSTGRESQL_DATABASE = "db";

    protected static final PostgreSQLContainer CONTAINER;

    static {
        DockerImageName imgName = DockerImageName.parse(DOCKER_IMAGE_NAME).asCompatibleSubstituteFor("postgres");

        CONTAINER = (PostgreSQLContainer) new PostgreSQLContainer(imgName)
                .withDatabaseName(POSTGRESQL_DATABASE)
                .withUsername(POSTGRESQL_USER)
                .withPassword(POSTGRESQL_PASSWORD)
                .withEnv("POSTGRESQL_DATABASE", POSTGRESQL_DATABASE)
                .withEnv("POSTGRESQL_USER", POSTGRESQL_USER)
                .withEnv("POSTGRESQL_PASSWORD", POSTGRESQL_PASSWORD)
                .withExposedPorts(PostgreSQLContainer.POSTGRESQL_PORT);

        CONTAINER.setWaitStrategy(Wait.defaultWaitStrategy()
                .withStartupTimeout(Duration.of(60, SECONDS)));

        CONTAINER.start();
    }
}

添加了正确的环境变量并更改了等待策略。注意:显然,我使用的图像比我意识到的更不标准。官方容器可能不需要更改等待策略。

【讨论】:

    猜你喜欢
    • 2020-08-14
    • 2022-12-29
    • 2019-01-17
    • 2021-09-07
    • 2020-04-22
    • 1970-01-01
    • 2021-12-21
    • 2019-11-01
    • 2018-03-15
    相关资源
    最近更新 更多