Невозможно запустить контейнер с помощью testcontainers

#java #docker #junit #junit4 #testcontainers

#java #docker #junit #junit4 #testcontainers

Вопрос:

Я пытаюсь реализовать тест JUnit (v4.13.2) с использованием testcontainers (v1.16.2), чтобы лучше протестировать наши классы DAO / JPA. Я использую официальный образ docker centos / postgresql-96-centos7, и я могу просто запустить его в строке 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 Env:
Клиент / сервер: Docker Engine — Community v20.10.7

Комментарии:

1. Вы пытаетесь использовать пустой конструктор (PostgreSQLContainer()) или DOCKER_IMAGE_NAME, кроме imgName?

2. Оба конструктора PostgreSQLContainer() and PostgreSQLContainer(String imageName) теперь устарели; поэтому я избегал их использования. Пошаговое выполнение кода: кажется, что изображение находится в порядке, но по какой-то причине он, похоже, не считает, что он запускается правильно.

3. Кажется, что изображение centos / postgresql-96-centos7 несовместимо с testcontainers, если вы посмотрите на PostgreSQLContainer.java вы можете найти это PostgreSQLContainer.java устанавливает другие переменные среды (POSTGRES_USER против POSTGRESQL_USER) и ожидает, что сообщения «система базы данных готова к приему подключений» дважды появятся в журналах контейнера.

4. Хороший улов. Я собираюсь углубиться в создание образа и посмотреть, смогу ли я обернуть этот образ и предоставить правильную среду. Хотя я не уверен, как я могу отображать сообщения журнала… РЕДАКТИРОВАТЬ: для меня было бы лучше использовать GenericContainer и создать URL-адрес JDBC… PITA.

Ответ №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();
    }
}
 

Добавлены правильные переменные среды и изменена стратегия ожидания. В качестве примечания: по-видимому, изображение, которое я использую, более нестандартно, чем я предполагал. Официальному контейнеру может не потребоваться изменение стратегии ожидания.