[Spring boot] 애플리케이션을 Docker 이미지로 만들기 Old & New

Spring boot로 개발한 서버를 운영하기 위해서는 인스턴스에 서버 애플리케이션을 배포해야 합니다. 애플리케이션을 배포하는 방법에는 WAS로 배포하는 방법도 있지만 Docker 컨테이너 이미지를 만들어서 Docker 이미지로 배포하는 방법도 존재합니다.

이번 포스트에서는 Spring boot에서 개발한 애플리케이션을 Docker로 만드는 방법에 대해 이야기 해보도록 하겠습니다.

 

Install Docker

먼저 Docker 이미지를 만들기 위해서 내 컴퓨터에 Docker가 설치되어 있어야 합니다. 아래의 포스트를 참고하여 Docker를 설치해주세요.

2016/07/06 - [Infrastructure/Docker] - Docker, 그것은 무엇이고, 설치는 어떻게할까?

 

Docker, 그것은 무엇이고, 설치는 어떻게할까?

요즘 Docker 라고 하는 것이 굉장히 인기입니다. Docker 컨테이너는 알기 시작한건 저도 작년 10월부터였는데, 저도 꽤 많이 사용하고 있습니다. What is Docker? Docker를 검색하시는 분들은 아마 한 번��

blog.neonkid.xyz

 

 

Create Dockerfile

Docker 설치가 끝났다면, 이제 내가 만든 애플리케이션이 들어 있는 Docker Image를 만들어야 합니다. Docker Image를 만들기 위해서 우리는 두 가지 작업을 진행해야 합니다.

  • gradlew 명령어 등을 이용하여 jar 파일로 빌드
  • Dockerfile 생성

Jar 파일은 Docker 이미지에서 내가 만든 애플리케이션을 실행하기 위해 사용됩니다. 그리고 Dockerfile에서 컨테이너 환경을 구성하게 됨으로써 내 애플리케이션이 별도의 환경 설정을 수동으로 진행할 필요없이 자동으로 이미지가 생성되는 방식입니다.

FROM    openjdk:8-jdk-alpine
RUN     addgroup -S neonkid && adduser -S neonkid -G neonkid
USER    neonkid:neonkid
ARG     JAR_FILE=build/libs/*.jar
COPY    ${JAR_FILE} app.jar
ENTRYPOINT  ["java", "-jar", "/app.jar"]

서비스할 애플리케이션에 기반이 될 이미지를 FROM 옆에 적으시면 되는데, 만약 수동으로 Java 설정을 진행하고자 한다면, ubuntu, centos 등의 미니멀 운영체제의 이미지를 사용하셔야 하지만, 여기서는 기본 설정 값으로 진행하여 만들어진 openjdk8 버전의 이미지를 사용하도록 하겠습니다.

기본적으로 Docker는 root 계정에서 실행이됩니다. 다른 사용자를 이용하여 애플리케이션을 실행하고자 원하는 경우, adduser 명령어 등을 이용하여 사용자를 생성하고, USER를 이용해 원하는 사용자 이름을 입력하면 해당 사용자 이름으로 애플리케이션이 실행됩니다.

위 방법은 Docker 이미지 내에서 단일 애플리케이션을 돌릴 때 사용하지 않고, 두 개 이상의 미들웨어 등을 동시에 운영할 때 실행 영역 공간을 나누기 위해서 보통 나누는 편이지만, Docker 이미지에서는 거의 사용하지 않습니다. 그렇지만 우리는 연습을 위해 진행하는 것이므로 이런 것도 있다. 라는 생각으로 진행하시면 좋을 것 같네요.

마지막으로 프로젝트에서 jar 파일의 경로를 ARG에 넣고, Docker 이미지에 복사할 이름을 정해준 다음 ENTRYPOINT에 java 명령어를 이용해 실행 명령어를 입력하면 Docker 이미지가 생성되었을 때 자동으로 서버가 실행됩니다.

 

 

Build Application

IDEA를 이용하여 Spring boot 애플리케이션을 만들 때는 Run 기능을 이용해서 Embedded Tomcat을 이용해 개발 서버로 테스트 정도만 사용할 수 있었습니다. 그런데, IDEA가 아닌 일반 Gradle 환경을 수동으로 만들고 했다면 어떻게 애플리케이션을 빌드 할 수 있을까요?

만약, Spring Initializr를 이용하여 프로젝트를 초기화 했다면, gradlew 명령어나 mvnw 명령어를 이용하여 애플리케이션을 빌드할 수 있습니다. 여기서는 gradlew를 이용하여 애플리케이션을 빌드해보록 하겠습니다.

$ ./gradlew build

위 명령어를 이용하여 빌드 작업을 진행하게 되면 ${PROJECT_NAME}/build/libs/*.jar 형태로 애플리케이션이 빌드됩니다. 우리는 이를 이용해서 Docker 이미지를 만들 수 있습니다.

 

 

Build Docker Image

이제 두 가지 작업을 모두 끝마쳤으니, 본격적으로 Docker 이미지를 만들어보도록 하겠습니다. 우리는 Spring boot 프로젝트 루트에 Dockerfile을 만들었고, 여기에서 작업을 진행하면 됩니다.

# docker build -t neonkid/dockerexample .

로컬에 이미지를 빌드할 때는 root 권한을 이용해야 합니다. 처음 빌드한다면, 시간이 조금 오래 걸릴 수도 있습니다.

모든 작업이 끝났다면 위와 같이 neonkid/dockerexample 이미지가 생성된 것을 알 수 있습니다.

 

 

Run Server

이제 그럼 서버를 실행해볼까요? 만들어진 Docker 이미지를 실행하기 위해서는 아래의 명령어를 이용하면 됩니다.

# docker run -d -p 1412:1412 --name dockerexample neonkid/dockerexample:latest

여기서 주의할 점은 -p 인자 다음에 나오는 포트 번호입니다. 여기서 포트 번호는 컨테이너에서 실행되는 포트 번호와 현재 운영체제의 포트 번호를 연결시켜주는 링킹 작업입니다. 따라서 Spring boot에서 내가 설정한 포트 주소가 뒤에 나와야 하며, 현재 인스턴스에 링킹하고자 하는 포트 주소를 입력해줘야 합니다. 

예를 들면 아래와 같습니다.

  • Spring boot에서 8080으로 설정한 서비스를 80 포트에 서비스하고자 한다면, => -p 80:1412
  • nginx 웹 서버에 올라간 서비스를 다른 서비스 포트로 서비스하고자 한다면, => -p 1412:80

 

 

Spring Boot 2.3 버전에서 Docker 이미지를 만드는 방법

최근 출시된 Spring boot 2.3 버전에서는 위 방법보다 더 쉬운 방법으로 Docker 이미지를 만들어 볼 수 있습니다. 간단한 명령어 한 줄 만으로도 Docker 이미지를 만들어 보도록 하죠.

# ./gradlew bootBuildImage

로컬 환경에 이미지를 만드는 작업이므로 반드시 root 권한을 이용하여 진행하도록 합시다.

처음 이미지 빌드 작업은 수동으로 만드는 것에 비해 엄청 오래 걸린다는 단점이 있지만, Docker를 배울 시간이 모자라다거나 러닝 커브가 좀 낮은 레벨의 작업을 원하신다면, 음 이 방법도 나쁘진 않아 보이네요..

작업이 끝나면 위와 같이 빌드된 Docker 이미지의 이름이 나오게 됩니다. dockerexample:0.0.1-SNAPSHOT이군요.

# docker run --tty -p 1412:1412 dockerexample:0.0.1-SNAPSHOT

이번엔 데몬 모드가 아닌 tty 모드로 실행해보도록 하겠습니다. 두 차이가 무슨 차이냐구요? 데몬 모드는 백그라운드에서 실행하는 것과 동일하게 서비스 모드로 동작하여 터미널이나 쉘에서 빠져나가도 동작하지만 tty 모드는 현재 내가 실행되고 있는 터미널 혹은 쉘에서 동작하기 때문에 터미널이나 쉘을 종료하면 컨테이너도 같이 종료되는 방식입니다.

 

 

 

마치며...

서버 애플리케이션을 배포할 때 WAS로 빌드하고, Tomcat에 올리는 경우가 대부분이었습니다. 그러나 Spring boot가 등장하면서 Jar 파일의 빌드가 가능해졌고, 그럼에 따라 일반 Java 명령어를 이용해서도 배포할 수가 있다는 것은 큰 메리트입니다.

이러한 방식으로 Docker 이미지를 쉽게 만들어서 개발하였을 때 테스트를 용이하게 한다는 것은 매우 큰 장점입니다. 물론 지금은 Docker 하나만을 가지고, 애플리케이션 이미지 하나 정도를 만드는 것에 그쳤지만 Docker Compose, Docker Swarm을 이용하면 내가 만든 서버에서 사용하는 미들웨어(DB, MQ) 등도 종합적으로 테스트 환경을 만들 수 있다는 장점도 있습니다. 이 부분에 대한 포스트는 다음에 다뤄볼 예정입니다.

comments powered by Disqus

Tistory Comments 0