메인 콘텐츠로 이동하기
  1. Posts/

custom JRE를 이용한 Java 컨테이너 경량화

·462 자

자바 애플리케이션은 종종 큰 컨테이너 이미지로 패키징됩니다. 특히 클라우드 환경에서 자원 활용을 효율적으로 하기 위해 그 크기를 줄이는 최적화 기술에서 큰 이점을 얻을 수 있습니다. 이 글에서는 Amazon Corretto의 OpenJDK에 포함된 도구인 jdepsjlink를 사용하여 의존성을 분석하고 도커 이미지의 크기를 크게 줄일 수 있는 최소한의 사용자 정의 자바 런타임 환경(JRE)을 생성하는 방법을 탐구하고자 합니다.

초기 도커 설정 #

스프링 부트 애플리케이션을 위한 전형적인 도커 설정은 다음과 같은 기본 도커 파일로 시작할 수 있습니다:

FROM amazoncorretto:11.0.20-alpine

COPY ./sample-app.jar /app/sample-app.jar
WORKDIR /app

EXPOSE 8000
ENTRYPOINT ["/jre/bin/java", "-jar", "/app/app.jar"]

이 도커 파일은 Amazon Corretto의 알파인 기반 이미지를 사용하여 자바 환경을 설정합니다. 애플리케이션 JAR를 이미지에 복사하고 작업 디렉토리를 설정합니다. 애플리케이션은 8000 포트에 노출됩니다.

jdeps는 자바 의존성 분석 도구로, 자바 애플리케이션에 필요한 특정 모듈을 결정하는 데 도움을 줍니다. jlink는 필요한 모듈을 기반으로 사용자 정의 JRE를 생성할 수 있는 자바 링커입니다. 이 도구들을 결합 사용하면 자바 런타임의 크기를 상당히 줄일 수 있습니다.

다음은 jdeps 사용의 기본 예시입니다:

jdeps --ignore-missing-deps --print-module-deps -q --recursive --multi-release 17 --class-path="./*" --module-path="./*" ./sample-app.jar

출력은 다음과 같을 수 있습니다:

java.base,java.management

이 모듈들이 확인되면, jlink는 축소된 버전의 JRE를 생성할 수 있습니다:

jlink \
    --verbose \
    --add-modules java.base,java.management \
    --strip-debug \
    --no-man-pages \
    --no-header-files \
    --compress=2 \
    --output customjre

최적화된 도커 이미지 빌드 #

위의 통찰을 사용하여, 최소한의 사용자 정의 JRE를 빌드한 후 애플리케이션을 위한 경량 컨테이너를 만드는 다단계 도커 파일을 구성할 수 있습니다:

# STAGE 1: 의존성 분석
FROM amazoncorretto:17.0.2 AS deps
WORKDIR /root
COPY ./sample-app.jar /root/sample-app.jar
RUN

 $JAVA_HOME/bin/jdeps \
    --ignore-missing-deps \
    --print-module-deps \
    -q --recursive \
    --multi-release 17 \
    /root/sample-app.jar > /deps.info

# STAGE 2: JRE 생성
FROM amazoncorretto:17.0.2 AS corretto-jdk
RUN yum install -y binutils # jlink에 필요
COPY --from=deps /deps.info /deps.info
RUN $JAVA_HOME/bin/jlink \
    --verbose \
    --add-modules $(cat /deps.info) \
    --strip-debug \
    --no-man-pages --no-header-files \
    --compress=2 \
    --output /root/customjre

# STAGE 3: 최종 이미지
FROM debian:bookworm-slim
ENV JAVA_HOME=/jre
ENV PATH="${JAVA_HOME}/bin:${PATH}"
COPY --from=corretto-jdk /root/customjre/ /jre/
COPY ./sample-app.jar /app/
WORKDIR /app
EXPOSE 8000
CMD ["java", "-jar", "sample-app.jar"]

결과 및 이점 #

사용자 정의 JRE를 사용함으로써 컨테이너 크기를 현저하게 줄일 수 있습니다. 우리의 테스트 중 하나에서는 이미지 크기가 563MB에서 225MB로 60% 이상 감소했습니다.

corretto:17.0.2를 사용한 컨테이너사용자 정의 JRE를 사용한 컨테이너비율
크기563MB225MB60.06% 감소

문제 해결 #

다음은 위 단계를 진행하는 동안 발생한 일부 문제들입니다.

문제 1: 알파인 이미지에서 “*/jre/bin/java no such file or directory”

  • 알파인 이미지는 glibc 대신 musl libc를 사용합니다. glibc를 기대하는 바이너리와 문제가 발생할 수 있습니다. 디비안 기반 이미지로 전환하거나 알파인에 glibc를 설치하면 이러한 문제를 해결할 수 있습니다.

문제 2: 도커 이미지 크기 불일치

  • Docker Hub와 같은 레지스트리에서 도커 이미지는 레이어가 압축되어 더 작게 보일 수 있습니다. 실제 크기는 로컬로 가져올 때 다를 수 있습니다.

결론 #

jdepsjlink를 사용하여 자바 컨테이너 이미지를 최적화하는 것은 크기를 줄이고 배포 효율을 개선하는 효과적인 방법입니다. 이 접근 방식은 리소스 제약이 큰 환경, 예를 들어 여러 마이크로서비스를 실행하는 쿠버네티스 클러스터에서 특히 유익합니다.

참조 #

  1. https://aws.amazon.com/ko/blogs/tech/amazon-corretto-base-container-diet
  2. https://stackoverflow.com/questions/66963068/docker-alpine-executable-binary-not-found-even-if-in-path