본문 바로가기
백엔드/오류

Docker Compose Gradle 시 테스트 fail

by ARlegro 2025. 4. 17.

문제 상황

  • docker-compose를 통해 Spring Boot 애플리케이션과 PostgreSQL을 컨테이너로 구성
  • Dockerfile 내 RUN ./gradlew clean build 구문에서 테스트 실행 중 실패 발생
  • 테스트 클래스는 개별 실행 시 문제 없음
  • 하지만 docker build 단계에서 Hibernate Dialect 관련 예외 발생:
  • AppleApplicationTests > contextLoads() FAILED  
    java.lang.IllegalStateException  
    Caused by: org.springframework.beans.factory.BeanCreationException  
    Caused by: org.hibernate.service.spi.ServiceException  
    Caused by: org.hibernate.HibernateException at DialectFactoryImpl.java:191
    

문제의 dockerfile, compose.yml

FROM amazoncorretto:17

WORKDIR /app

COPY ./ ./

**RUN ./gradlew clean build   <<<<<**

EXPOSE 80

ENV SPRING_PROFILES_ACTIVE=prod
ENV PROJECT_NAME=apple
ENV PROJECT_VERSION=1.2-M8
ENV JVM_OPTS=""

ENTRYPOINT ["sh", "-c", "exec java ${JVM_OPTS} -jar /app/build/libs/${PROJECT_NAME}-${PROJECT_VERSION}.jar"]

services:
  application-server:
    container_name: apple-server
    build: .
    ports:
      - 8081:80

    depends_on:
      postgres-db:
        condition: service_healthy

    env_file:
      - .env

  postgres-db:
    container_name: postgres-db
    image: postgres
    ports:
      - 5432:5432
    environment:
      POSTGRES_USER: ${DB_USERNAME}
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      POSTGRES_DB: ${DB_NAME}

    volumes:
      - ./discodeit-data:/var/lib/postgresql/data
      - ./src/main/resources/schema.sql:/docker-entrypoint-initdb.d/schema.sql

    env_file:
      - .env

    healthcheck:
      test: ["CMD", "pg_isready", "-U", "${DB_USERNAME}"]
      interval: 5s
      retries: 10

원인 분석

생각의 흐름

프로덕션 코드의 빌드는 제대로 되는데 이상하게 테스트 코드 build시 문제가 된다.
그렇다고 테스트 코드들이 실패하는가??? No, 테스트 클래스별 테스트를 실행할 떄는 전혀 문제가 없다.
근데 이상하게 build단계에서만 계속해서 접속을 못하는 문제가 발생
RUN ./gradlew clean build dockerfile에 명시된 이것이 큰 문제이다. 이 부분에서 계속 오류가 나는 상황

분석

✅ 실행 타이밍 생각

RUN ./gradlew clean build

RUN 명령어는 이미지를 빌드할 때 실행되며, 테스트 코드까지 실행된다.
하지만 이 시점에는
1️⃣ DB 컨테이너가 존재하지 않는다.
2️⃣ 환경변수 미적용 : .env파일에 정의된 환경변수가 적용되지 않는다.

  • 테스트 시 DB 연결은 아래와 같이 구성되어 있다.
    • 물론, 명시적으로 실행시 환경변수를 주입할 수 있지만, 실제 배포까지 생각을 했을 때 매번 그렇게 부여하는건 비효율적이어서 안했다.
  • **[yml] yml에는 환경변수로 주입시켰다.** url: jdbc:postgresql://${DB_HOST:localhost}:5432/${DB_NAME:discodeit-test} username: ${DB_USERNAME} password: ${DB_PASSWORD}

<aside> 💡
참고 : 결국 환경변수가 주입되는 것은 docker-compose.yml 에 설정되어있다.

[docker-compose.yml 파일]
services:
  apple-server:
    container_name: apple-server
		...
        condition: service_healthy

    env_file:
      - .env  <<< compose file 에 설정 

</aside>

즉, ./gradlew clean build는 실제 테스트 코드를 실행시키기 때문에, 환경변수 주입이 안된 DB 커넥션 설정은 실패하게 된다.

해결방법

test를 좀 더 늦춰야 한다.

Step 1. 테스트 생략 후 빌드 : -x test

./gradlew clean build -x test
  • -x test 사용 → 테스트를 실행하지 않고 빌드만 진행할 수 있음
  • 이후 docker-compose up으로 실행 시 컨테이너 간 의존성을 활용해 정상 작동 가능
  • 이 방법은 빌드와 테스트를 분리할 때 쓰는 적절한 방법이다.

Step 2. compose파일에서 test 실행

애플리케이션 실행 컨테이너에 테스트 실행 command 등록

결국 지금 겪는 문제는, DB연결이 제대로 되지 않는 상태에서 테스트 코드가 실행됐던 것이다.
그렇기 때문에, DB 컨테이너가 생성되고 애플리케이션 컨테이너가 생성될 때, 테스트 코드를 실행시키도록 하면 된다.

services:
  apple-server:
    container_name: apple-server
    build: .
    ports:
      - 8081:80
    command:
      **- ./gradlew test**  **<<<<<<<<<<<< 테스트 코드는 여기서 실행** 

    depends_on:
      postgres-db:
        condition: service_healthy

    env_file:
      - .env        **<<<<<<<<<<<< 이로 인해 DB에 접속할 환경변수 주입 가능** 

  postgres-db:
    ....
  • docker compose로 DB 컨테이너가 먼저 실행되고, 이후 apple-server에서 테스트가 실행된다.
  • 이 컨테이너에서는 .env의 환경변수가 설정되어 있기에 환경변수 주입 방식으로 설정해놓은 DB연결 YML은 성공할 것이다.

후기

이걸로 7시간은 뻘짓했던 것 같다.
검색을 아무리 해도 잘 안나오기도 했고, build자체가 시간이 너무 오래걸려서 문제였다.
참고로 테스트 컨테이너 의존성을 추가해서 테스트 컨테이너 기반 DB 테스트 환경 구성도 있다고 하는데, 이 방법도 나중에 다뤄보면 좋을 것 같다.