⏩ [ko] Accelerate Java Deployment: Easy Containerization with Google Jib, No Dockerfile work
Google Jib 를 활용하여, 쉽고 빠르게 java image 를 만들어봅시다.
Google Jib simplifies containerization of Java applications without any Dockerfile. It builds images efficiently and quickly, reducing the complexity and time associated with traditional Docker builds.
Container
" Write Once, run anywhere. "
컨테이너는 어느 환경에서든 일관된 동작을 보장하며,
애플리케이션의 빠른 배포와 확장을 가능하게 하므로
개발 생산성을 크게 높일 수 있습니다.
이를 위해서는 Dockerfile
을 작성하고,
지속적으로 관리해야하는 어려움이 있죠.
또한 서비스가 커짐에 따라,
이미지를 빌드하는 데에 걸리는 소요 시간은 점점 늘어납니다.
이로부터 CI/CD 시간이 길어지므로,
개발 생산성은 점차 떨어지게 되겠죠.
이를 해결하려면,
DockerFile 스크립트를 조정하여
이미지를 빌드하는 과정을 최적화해야 합니다.
아래와 같이 잘 정리된 아티클을 참고할 수 있습니다.
하지만 Devops 가 아닌 애플리케이션 개발자에게는,
DockerFile 에 대한 러닝 커브가 존재합니다.
이러한 문제점을 Google Jib 를 통해서 효과적으로 해결할 수 있습니다.
Jib 를 사용하면 DockerFile 을 작성하지 않고도,
빠르고 효율적으로 이미지를 빌드할 수 있습니다.
Jib 에 대해서 더 알아보기 전에,
전통적인 Docker Build 방식부터 먼저 살펴봅시다.
Docker Build
일반적으로는 Docker Build 방식을 사용하여 컨테이너화를 수행합니다.
dockerFile 을 통해 image 를 만들고 Dokcer registry 에 만들어진 image 를 push 한 뒤,
배포 서버에서 run 하면 컨테이너가 생성됩니다.
조금 더 디테일하게 들어가볼까요?
자바 애플리케이션을 빌드하여 JAR 파일을 생성하고,
DockerFile 에서 base image, layer, command 등을 설정한 뒤에,
DockerFile 과 JAR 파일을 Docker Daemon 에 전달하여, image 를 build 합니다.
그리고 AWS ECR, Docker Hub 와 같은 Docker registry 에 image 를 push 합니다.
배포 서버에서 Docker registry 에 push 된 image 를 pull 하여 애플리케이션을 실행합니다.
Optimize Docker image
위에서 언급한 바와 같이,
프로젝트가 점점 커지면 image build 시간도 같이 길어집니다.
이는 개발 생산성을 크게 떨어뜨리는 요인이 되죠.
해결하기 위해서는,
DockerFile 을 최적화해야합니다.
FROM openjdk:8
COPY target/springdemo-*.jar /app.jar
ENTRYPOINT java -jar /app.jar
가장 먼저 시도할 수 있는 것은,
경량화 된 base image 를 사용하는 것 입니다.
openjdk:8 image 는 284 MB 이므로,
alpine 버전의 base image 로 대체하면 200 MB 를 절약할 수 있습니다.
FROM openjdk:8-jre-alpine
COPY target/springdemo-*.jar /app.jar
ENTRYPOINT java -jar /app.jar
하지만 이미 프로젝트가 커져있다면,
base image 를 아무리 경량화 된 버전을 사용한다고 해도
image build time 은 여전히 느리죠.
.dockerignore
에서 target/springdemo-*.jar
를 ignore 하도록 설정하면 해결할 수 있을까요?
image build time 은 꽤 빨라지겠지만,
소스 코드의 변경이 발생하면,
어차피 target/springdemo-*.jar
를 포함하여 image 를 build 해야 하므로
적절한 해결책은 아닌 것 같습니다.
다시 dockerfile 파일을 봅시다.
FROM openjdk:8-jre-alpine
COPY target/springdemo-*.jar /app.jar
ENTRYPOINT java -jar /app.jar
아래와 같이 layer 가 구성될 것입니다.
+---------+---------+
| layer2: | app.jar |
| layer1: |openjdk:8|
+---------+---------+
docker build 를 최초 수행하면, 해당 layer 가 생성되고 캐싱됩니다.
한번 더 docker build 를 수행하면
변경점이 없는 layer 는, 캐싱된 layer 를 사용하여 image 를 build 합니다.
JAR 파일은 프로젝트가 커짐에 따라,
size 가 매우 늘어나게 될 텐데요.
JAR 파일 전체가 하나의 layer 를 이루게 된다면 비효율적이지 않을까요?
문제 상황을 다시 정리해봅시다.
- 소스 코드나 dependency 를 일부만 수정해도 JAR Layer 를 새로 생성하기 때문에 image build time 이 매우 느려짐에 따라 개발 생산성 저하가 우려된다.
Spring boot 2.3 version 부터,
효과적으로 layering 할 수 있는 기능을 제공하고 있습니다.
이를 통해, JAR 파일을 네 개의 레이어로 분리할 수 있습니다.
- dependecies
- spring-boot-loader
- snapshot-dependencies
- application
아무래도 변경점이 가장 많이 발생하는 layer 는 application 이겠죠.
java -Djarmode=layertools -jar springdemo.jar extract
--
- layer1. application
- layer2. dependencies
- layer3. snapshot-dependencies
- layer4. spring-boot-loader
소스 코드를 변경하여도,
application layer 만 재생성하고
다른 layer 는 캐싱된 layer 를 사용하게 될 것이므로
docker image build time 이 효과적으로 개선됩니다.
- 최초 build time 은 아무래도 거의 동일하겠죠?
이 방법 외에도 추가적으로 알려진 dockerFile best practice
를 적용하여,
조금 더 최적화 할 수도 있겠죠.
위 과정을 java 애플리케이션 개발자가 수행하게 된다면,
dockerFile 과 컨테이너에 대한 러닝 커브가 발생할 것이고
비지니스 로직에 집중할 리소스가 줄어들게 될 것입니다.
dockerFile 을 최적화하려는 과정에서 실수가 발생할 여지도 굉장히 많죠.
이 문제들은 Google Jib 를 사용하여 효과적으로 해결할 수 있습니다.
Google Jib
DockerFile 을 작성하지 않고, maven 이나 gradle 과 같은 build system 에서
java application image 를 효과적으로 build 할 수 있습니다.
일반적인 Docker build 파이프라인을 다시 한번 살펴본 뒤에,
Jib 를 활용한 파이프라인과 비교해봅시다.
굉장히 간단하죠.
아래와 같이 gradle 설정을 해준 뒤,
plugins {
...
ip 'com.google.cloud.tools.jib' version '3.1.4'
...
}
...
jib {
from {
image = 'your-base-image'
}
to {
image = 'remote-docker-registry/your-application-image'
auth {
username =
password =
}
}
// you can add additional options like jvm flags, program arguments, etc...
}
./gradlew jibDockerBuild
위 명령어 만으로 docker image build 를 효과적으로 수행할 수 있습니다.
DockerFile 을 알지 못하더라도,
Jib 를 사용하면
최적화 된 dockerFile 을 사용하여 image build 를 하는 것과 같은 효과를 누릴 수 있습니다.
프로젝트가 커질수록, Jib 의 성능은 더욱 명확하게 체감할 수 있습니다.
사내 서비스의 평균 배포 시간이 기존 15분 이상에서,
Jib 도입 후 1~3분으로 대폭 줄었습니다.
컨테이너 기반의 자바 프로젝트를 구성할 때,
DockerFile 을 작성하지 않고도 효과적으로 컨테이너화가 가능한
Jib 의 도입을 고려하는 것도 좋을 것 같습니다.
Leave a comment