환경: Spring Boot 2.7, Java 11, Gradle
FROM openjdk:17-ea-11-jdk-slim as build
WORKDIR /workspace/app
COPY gradle gradle
COPY build.gradle settings.gradle gradlew ./
COPY src src
RUN ./gradlew build -x test
RUN mkdir -p build/libs/dependency && (cd build/libs/dependency; jar -xf ../*.jar)
FROM openjdk:11-jre-slim-buster
VOLUME /tmp
ARG DEPENDENCY=/workspace/app/build/libs/dependency
COPY --from=build ${DEPENDENCY}/BOOT-INF/lib /app/lib
COPY --from=build ${DEPENDENCY}/BOOT-INF/classes /app
COPY --from=build ${DEPENDENCY}/META-INF /app/META-INF
ENTRYPOINT ["java", "-cp","app:app/lib/*", "com.example.UserManageServiceApplication"]
해당 파일이 존재하지 않는다는 에러였으며 로컬에서 ./gradlew build -x test
명령어부터 시작하여 분석해보았다.
뒤에 plain이 붙은 jar 파일이 생성된다. 압축을 풀어 디렉토리를 살펴보았다.
plain jar에는 META-INF, com, static, teplates, application.yml의 파일 중 스테이지2에 copy될 BOOT-INF이 존재하지 않아 발생한 에러였다.
plain jar 파일은 어플리케이션 실행에 필요한 모든 의존성이 포함되지 않고 class 파일과 리소스 파일만 포함된다. 따라서
java -jar
명령어로 실행할 때 오류가 발생한다!
./gradlew bootJar
로 생성된 jar 파일도 압축을 해제해 살펴보았다. BOOT-INF, META-INF, org 파일이 있다.
bootJar로 생성된 jar 파일은 실행가능한 jar 파일이다. 즉, 애플리케이션 실행을 위한 모든 의존성이 포함되어 있으며
java -jar
로 실행가능하다.
FROM openjdk:17-ea-11-jdk-slim as build
WORKDIR /workspace/app
COPY gradle gradle
COPY build.gradle settings.gradle gradlew ./
COPY src src
RUN ./gradlew bootJar
RUN mkdir -p build/libs/dependency && (cd build/libs/dependency; jar -xf ../*.jar)
FROM openjdk:11-jre-slim-buster
VOLUME /tmp
ARG DEPENDENCY=/workspace/app/build/libs/dependency
COPY --from=build ${DEPENDENCY}/BOOT-INF/lib /app/lib
COPY --from=build ${DEPENDENCY}/BOOT-INF/classes /app
COPY --from=build ${DEPENDENCY}/META-INF /app/META-INF
ENTRYPOINT ["java", "-cp","app:app/lib/*", "com.example.UserManageServiceApplication"]