SpringBoot 도커 이미지 만들기 최적화

dragonappear·2022년 7월 13일
0

DevOps

목록 보기
1/1

출처

제목: "Spring boot docker image만들기 최적화 방법 (+ 새로운 gradle task)"
작성자: github.io(baeji77)
작성자 수정일: 2020.10.11
링크: https://baeji77.github.io/spring/dev/Spring-boot-gradle-build/
작성일: 2022년7월13일

Spring Dockerized

기본방식

FROM openjdk:8-jdk-alpine
ARG JAR_FILE=build/libs/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
  • 현재 위에 있는 Dockerfile은 인터넷이나 기본적으로 많이들 볼 수 있는 형식이다.
  • 이것을 통해서 간단하게 스프링 도커 이미지를 만들 수 있다.

하지만 여기서 JAR 파일이 무거워 지는 경우 위 방식으로 도커 이미지를 만드는 것은 비효율적이다.
도커는 레이어마다 캐쉬를 활용할 수 있고 그것을 통해서 빠른 도커 이미지를 만들 수 있는 장점이 있다.
이런 구조에서는 자바의 모든 구조가 jar 파일 하나로 퉁치기 때문에 캐쉬를 적용하기가 어렵다.


효율적인 방식

스프링을 이용해서 Jar 파일을 만들때 4개의 영역으로 구분되어지도록 만들 수 있다.

아래와 같이 그래들 빌드 설정을 해준다.

gradle.build

bootJar {
    layered()
}

gradle.build에 위 코드를 추가하고 ./gradlew bootJar를 통해서 Jar 파일을 만들게 되는 경우 4가지 폴더로 나눠져서 JAR가 구성되어지는 것을 볼 수 있다.

그리고 아래 커맨드를 통해 jar 파일을 풀게 되면 4가지 폴더(layer)가 만들어진다.
command

java -Djarmode=layertools -jar JAR_FILE_NAME.jar extract 

레이어별 설명

정확하게 이렇게 4가지로 나눠지는 이유는 적혀있지 않았지만 어플리케이션 레이어부터 밑으로 자주 바뀌지 않는 순서가 존재한다는 것이다.(application이 제일 자주 바뀌고, dependencides가 제일 바뀌지 않는다)

그래서 실제로 도커 이미지를 만들어 가는 과정에서 이 순서에 역순으로 작성을 해주어야 한다.(자주 바뀌지 않기 때문에 캐시가 깨질 가능성이 적어진다.)

FROM openjdk:8-jdk-alpine as builder
WORKDIR application
ARG JAR_FILE=build/libs/*.jar
COPY ${JAR_FILE} application.jar
RUN java -Djarmode=layertools -jar application.jar extract 

FROM openjdk:8-jdk-alpine
WORKDIR application
ENV port 8080
ENV spring.profiles.active local
COPY --from=builder application/dependencies/ ./
COPY --from=builder application/spring-boot-loader/ ./
COPY --from=builder application/snapshot-dependencies/ ./
COPY --from=builder application/application/ ./

ENTRYPOINT ["java", "org.springframework.boot.loader.JarLauncher"]

이 방법으로 생긴 4개의 폴더에 대해서 모두 COPY 하도록 한다.
이것을 통해서 폴더에 어떤 부분이 수정되더라도 최소한의 범위에 대해서 캐시가 깨지기 때문에 전보다는 효율적으로 도커 이미지를 만들 수 있다.

$ docker build -t YOUR_PROJECT_TAG DOCKER_FILE_LOCATION
$ docker run -e spring.profiles.active=local -p 8080:8080 YOUR_DOCKER_IMAGE

SpringBoot 2.3

  • SpringBoot 2.3에서 gradle bootBuildImage 라는 task가 생겼다.

  • 도커 이미지를 만들어주는데 Dockerfile 없이 만드는 것이 가능하다.

  • docker host 정보도 셋어 가능하고, 빌드 관련해서 builder를 바꾼다던지 image 일므을 바꾸는 옵션이 가능하다.

gradle task 실행과 함께 도커 이미지를 만들게 된다.

제일 마지막 줄에 있는 spring-boot-dockerized 이름을 가진 image가 만들어진것을 확인할 수 있다.(gcr.io,paketobuilderpacks 은 Buildpacks를 위해서 필요하다)

Buildpacks
실제 bootBuildImage task는 buildpack 이라는 기술을 활용해서 구현했다. OCI 이미지와 최신 컨테이너 표준을 사용하며 어플리케이션을 컨테이너 이미지로 만드는데 잘 활용될 수 있는 기술이다

  • Java Buildpack memory configuration: buildpack 으로 이미지를 만드는 경우에 있어서 기본적으로 자동으로 jvm 세팅을 해준다.

Default

$ docker run -e spring.profiles.active=local -p 8080:8080 spring-boot-dockerized:0.0.1-SNAPSHOP

Setting Active Processor Count to 6
WARNING: Container memory limit unset. Configuring JVM for 1G container.
Calculated JVM Memory Configuration: -XX:MaxDirectMemorySize=10M -Xmx400163K -XX:MaxMetaspaceSize=136412K -XX:ReservedCodeCacheSize=240M -Xss1M (Total Memory: 1G, Thread Count: 250, Loaded Class Count: 21670, Headroom: 0%)
Adding 127 container CA certificates to JVM truststore
Spring Cloud Bindings Enabled
Picked up JAVA_TOOL_OPTIONS: -Djava.security.properties=/layers/paketo-buildpacks_bellsoft-liberica/java-security-properties/java-security.properties -agentpath:/layers/paketo-buildpacks_bellsoft-liberica/jvmkill/jvmkill-1.16.0-RELEASE.so=printHeapHistogram=1 -XX:ActiveProcessorCount=6 -XX:MaxDirectMemorySize=10M -Xmx400163K -XX:MaxMetaspaceSize=136412K -XX:ReservedCodeCacheSize=240M -Xss1M -Dorg.springframework.cloud.bindings.boot.enable=true

기본적으로 어떤 옵션을 주지 않은 상태에서 실행을 했을 경우 Container size 1G라고 설정하고 나머지 jvm 옵션 + buildpack에서 만든 휴리스틱으로 알아서 셋업해준다.

Container memory set-up

$ docker run -e spring.profiles.active=local -p 8080:8080 -m=2G  spring-boot-dockerized:0.0.1-SNAPSHOP

Setting Active Processor Count to 6
Calculated JVM Memory Configuration: -XX:MaxDirectMemorySize=10M -Xmx1448739K -XX:MaxMetaspaceSize=136412K -XX:ReservedCodeCacheSize=240M -Xss1M (Total Memory: 2G, Thread Count: 250, Loaded Class Count: 21670, Headroom: 0%)
Adding 127 container CA certificates to JVM truststore
Spring Cloud Bindings Enabled
Picked up JAVA_TOOL_OPTIONS: -Djava.security.properties=/layers/paketo-buildpacks_bellsoft-liberica/java-security-properties/java-security.properties -agentpath:/layers/paketo-buildpacks_bellsoft-liberica/jvmkill/jvmkill-1.16.0-RELEASE.so=printHeapHistogram=1 -XX:ActiveProcessorCount=6 -XX:MaxDirectMemorySize=10M -Xmx1448739K -XX:MaxMetaspaceSize=136412K -XX:ReservedCodeCacheSize=240M -Xss1M -Dorg.springframework.cloud.bindings.boot.enable=true
  • 기본으로 셋업되어 있는 1G가 아닌 container의 메모리를 늘리게되면 그것만큼 알아서 나머지 jvm 셋팅을 해준다.
  • 자동으로 셋업되는 것이 아닌 자기가 직접 jvm 셋업을 하고 싶은 경우 docker run을 하면서 JAVA_OPTS으로 셋업할 수 있다.

0개의 댓글