본문 바로가기
JAVA

Spring boot 프로젝트 도커 이미징

by 직장인B 2022. 9. 2.

 스프링 부트 프로젝트를 도커 이미지로 구성하는 실습 과정을 포스팅한다. 조그만 back-end 서버를 경량의 이미지로 구성해서 배포해보는 걸 목표로 한다. 과정은 다음과 같다. 

 

  1. Spring boot 프로젝트 생성
  2. Dockerflie 작성
  3. Build 및 배포

1 . Spring boot 프로젝트 생성

 작고 귀여운 스프링 부트 토이 프로젝트를 생성한다. dependency는 spring web만으로 충분하다. 생성한 프로젝트에 두 가지 작업을 더한다. 

 첫째는 생존 체크용 api 작성이다.

 

@SpringBootApplication
@RestController
public class ProtoApplication {

	@GetMapping("/healtz")
	public String healtz(){
		return "Hello, I'm healtz";
	}
	
	public static void main(String[] args) {
		SpringApplication.run(ProtoApplication.class, args);
	}

}

 

 둘째는 렌더링 자원 저장이다. Resources -> static 폴더에 렌더링 테스트용 html / js 파일을 넣어둔다. 

 

* resource/static/index.html

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Proto</title>
</head>
<body style="width: 100vw; height: 100vh; display: flex; justify-content: center; align-items: center;">
    <div id="proto"></div>
    <script src="./app.js"></script>
</body>
</html>
* resources/static/app.js

const proto = document.getElementById("proto");
proto.innerText = "I has healtz body!";

 

 이렇게 해서 어플리케이션을 구동시키면 화면/api 호출이 정상적으로 작동해야 한다. 

 도커 파일 작성 전에 수동으로 패키징을 해주어야 한다. 패키징은 프로젝트 내에 설치되어 있는 maven 툴을 사용하면 된다. 아래는 패키지 명령어다. 프로젝트의 루트에서 명령하면 된다.

 

./mvnw package

 

2 . Dockerfile 작성

 

 도커라이징 작업의 꽃은 바로 Dockerfile 작성이다. 기본적으로는 앱의 구동 환경/작동 방식에 맞추어 도커 파일이 작성되어야 한다. 하지만 그것으로 끝내는 건 죄악이다. 운영 편의성을 위한 적당한 커스터마이징과 최적화가 필요하다. 

 작성된 도커 파일은 아래와 같다. adoptopenjdk 이미지와 openj9 태그를 사용했다. adoptopenjdk는 나름의 가장 범용적인 openjdk이기때문에 선택했고, openj9는 살펴보니 다른 선택지인 hotspot 보다 성능이 좋은 JVM이라고 해서 선택했다. 

 아래의 빌드 과정은 다소 독특하다. 자바 파일을 컴파일해서 jar를 만드는 과정이 아니다. 도리어 압축된 jar 파일을 분해하는 작업이다. 따지자면 여기서의 build는 어플리케이션 build 가 아니라 도커 이미지 layer build이다. 도커 이미지는 여러 개의 layer를 쌓아서 만들 수 있다. 아래는 이 성질을 응용하여 하나의 jar 파일을 여러 개의 layer로 쪼개는 작업인 것이다. ( 참조 : https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.container-images.layering )

 

FROM adoptopenjdk:11-jre-openj9 as builder

WORKDIR app
ARG JAR_FILE=target/*jar
COPY ${JAR_FILE} app.jar
RUN java -Djarmode=layertools -jar app.jar extract

FROM adoptopenjdk:11-jre-openj9
WORKDIR app
COPY --from=builder app/dependencies/ ./
COPY --from=builder app/spring-boot-loader/ ./
COPY --from=builder app/snapshot-dependencies/ ./
COPY --from=builder app/application/ ./

EXPOSE 8080

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

 

*** 사실 직접 도커 파일을 작성하지 않고 이미지를 만들 수 있는 방법이 있다. 프로젝트의 maven 툴에 이미지를 만드는 옵션이 있다. 아래처럼 명령어를 치면된다. 간편한 방법이다! 하지만 말했듯이 도커라이징의 핵심은 여러 방식의 커스터마이징에 있다. 그렇기에 그닥 매력적으로 보이지는 않는 기능이다. ( 암튼 참조 : https://spring.io/guides/gs/spring-boot-docker/ )

 

  ./mvnw spring-boot:build-image -Dspring-boot.build-image.imageName=spring-boot-toy:0

 

3 . Build 및 배포

 

 빌드 명령어는 다음과 같다. 

 

docker build --build-arg JAR_FILE=./target/docker-1.jar -t spring-boot-toy:0 .

 

 배포 명령어는 다음과 같다. 

 

docker run -p 8080:8080 -d --name spring-boot-toy spring-boot-toy:0

 

 


 

 실습은 이것으로 끝이다!