기존 프로젝트에서 작성했던 Dockerfile을 통해 이미지를 빌드하면 속도 저하 및 많은 용량에 대한 문제가 있어, 그에 대한 해결을 공유하고자 합니다.
프로젝트에 대한 구성은 아래의 글에서 확인할 수 있습니다.
아래는 기존의 Dockerfile 입니다. 루트 컨텍스트에서 Dockerfile 의 빌드가 실행되게 하여, 각 서비스 모듈이 의존하는 다른 모듈들을 참조하기 위해 모든 파일을 복사하여 빌드를 수행합니다.
# Stage 1: Build the application
FROM gradle:8.10.1-jdk17 AS build
WORKDIR /app
# ARG로 전달된 파일 디렉터리 설정
ARG FILE_DIRECTORY
# 파일 복사
COPY $FILE_DIRECTORY /app
# Reservation 모듈만 빌드
RUN ./gradlew :reservation:clean :reservation:build -x test --no-daemon
FROM openjdk:17-jdk-slim
COPY --from=build /app/reservation/build/libs/*SNAPSHOT.jar /app.jar
# JAR 파일 실행
CMD ["java", "-jar", "/app.jar"]
현재 Dockerfile 의 문제점은 아래와 같습니다.
1. 모든 파일을 복사
FILE_DIRECTORY
는 루트 컨텍스트의 docker-compose.yml 에서 넘겨준 인자로, 루트 위치를 넘겨줍니다.COPY $FILE_DIRECTORY /app
를 통해 루트 내의 하위 파일들을 모두 복사하므로 매우 비효율적입니다.2. JDK 베이스 이미지 사용
아래는 reservation
모듈의 Dockerfile 예시입니다.
# Stage 1: Build the application
FROM gradle:8.10.1-jdk17 AS build
WORKDIR /app
# ARG로 전달된 파일 디렉터리 설정
ARG FILE_DIRECTORY
# 필요한 모듈만 복사
COPY $FILE_DIRECTORY/settings.gradle /app/settings.gradle
COPY $FILE_DIRECTORY/gradle /app/gradle
COPY $FILE_DIRECTORY/gradlew /app/gradlew
COPY $FILE_DIRECTORY/reservation /app/reservation
COPY $FILE_DIRECTORY/build.gradle /app/build.gradle
COPY $FILE_DIRECTORY/GlowGrow-common/build.gradle /app/GlowGrow-common/build.gradle
COPY $FILE_DIRECTORY/GlowGrow-common/src /app/GlowGrow-common/src
COPY $FILE_DIRECTORY/GlowGrow-security/build.gradle /app/GlowGrow-security/build.gradle
COPY $FILE_DIRECTORY/GlowGrow-security/src /app/GlowGrow-security/src
COPY $FILE_DIRECTORY/GlowGrow-kafka/build.gradle /app/GlowGrow-kafka/build.gradle
COPY $FILE_DIRECTORY/GlowGrow-kafka/src /app/GlowGrow-kafka/src
# Gradle 빌드 캐시 사용을 위한 외부 의존성 다운로드
RUN ./gradlew :reservation:dependencies --no-daemon
# Reservation 모듈만 빌드
RUN ./gradlew :reservation:clean :reservation:build -x test --no-daemon
# Stage 2: Run the application
FROM eclipse-temurin:17-jre-alpine
# 빌드된 JAR 파일 복사
COPY --from=build /app/reservation/build/libs/*SNAPSHOT.jar /app.jar
# JAR 파일 실행
CMD ["java", "-jar", "/app.jar"]
1. 필요한 모듈만 복사하기
2. JDK 대신 JRE 사용
3. 멀티스테이지 빌드 최적화
개선 전 크기
개선 후 크기
개선 전과 후가 거의 1.7 배의 차이를 보이므로 유의미한 수정이라고 할 수 있겠습니다.
사실 속도에 있어서는, 기존 빌드 속도가 느린 편은 아니며 현재 GithubActions 를 통해 Docker 빌드 스테이징을 수행하므로, 로컬 캐싱을 사용할 수 없고, GithubActions에서 캐싱을 진행해야 합니다. 이를 위해 Docker에서 제공하는 플러그인을 사용할 수 있습니다. 아래의 글을 참고하여 각자 구현해 보면 좋을 것 같습니다.