custom JRE를 이용한 Java 컨테이너 경량화
목차
자바 애플리케이션은 종종 큰 컨테이너 이미지로 패키징됩니다. 특히 클라우드 환경에서 자원 활용을 효율적으로 하기 위해 그 크기를 줄이는 최적화 기술에서 큰 이점을 얻을 수 있습니다. 이 글에서는 Amazon Corretto의 OpenJDK에 포함된 도구인 jdeps
와 jlink
를 사용하여 의존성을 분석하고 도커 이미지의 크기를 크게 줄일 수 있는 최소한의 사용자 정의 자바 런타임 환경(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 활용 #
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를 사용한 컨테이너 | 비율 | |
---|---|---|---|
크기 | 563MB | 225MB | 60.06% 감소 |
문제 해결 #
다음은 위 단계를 진행하는 동안 발생한 일부 문제들입니다.
문제 1: 알파인 이미지에서 “*/jre/bin/java no such file or directory”
- 알파인 이미지는 glibc 대신 musl libc를 사용합니다. glibc를 기대하는 바이너리와 문제가 발생할 수 있습니다. 디비안 기반 이미지로 전환하거나 알파인에 glibc를 설치하면 이러한 문제를 해결할 수 있습니다.
문제 2: 도커 이미지 크기 불일치
- Docker Hub와 같은 레지스트리에서 도커 이미지는 레이어가 압축되어 더 작게 보일 수 있습니다. 실제 크기는 로컬로 가져올 때 다를 수 있습니다.
결론 #
jdeps
와 jlink
를 사용하여 자바 컨테이너 이미지를 최적화하는 것은 크기를 줄이고 배포 효율을 개선하는 효과적인 방법입니다. 이 접근 방식은 리소스 제약이 큰 환경, 예를 들어 여러 마이크로서비스를 실행하는 쿠버네티스 클러스터에서 특히 유익합니다.
참조 #
- https://aws.amazon.com/ko/blogs/tech/amazon-corretto-base-container-diet
- https://stackoverflow.com/questions/66963068/docker-alpine-executable-binary-not-found-even-if-in-path