[docker] spring boot 도커 환경에 빌드 배포하기

앞서 카카오톡 메신저봇 챗봇 서버를 돌리기 위해  윈도우11에 docker desktop 환경을 구축했었습니다.

 

 

[docker] docker desktop 설치, 챗봇 서버 이미지 배포 테스트

윈도우에 WSL2 docker 설치 후 테스트 서버로 시운전까지 마쳐주고 설치해준 도커 서버는 삭제를 해주었습니다. 좀 더 편리한 환경을 위해 Docker Desktop을 설치해서 운용해보기로 합니다. 먼저 Docker D

quantrader.tistory.com

 

 

 

 

이제 추가적으로 모든 개발 환경을 docker 에 올리기로 합니다. 단일 tomcat 을 띄워서 구동하는 방식보다 여러모로 장점이 있는 듯 합니다. 아직은 더 경험해보아야 하는 부분이지만 일단 한번 시작한 스터디는 끝을 봐야 할듯 합니다. 

 

spring boot 배포에 이어 프로메테우스와 그라파나를 이용해 spring boot 서버를 모니터링하는 환경을 구축하고자 합니다. 스터디와 함께 머리속에 각인 시키기 위해 이 과정을 포스팅 하려 합니다. 

 

Spring Boot 프로젝트 생성

 

intelliJ를 통해 스프링 부트 프로젝트를 생성해줍니다.

JAVA 에 Gradle-Groovy 를 선택해줍니다. 코틀린에 익숙하시다면 코틀린을, 본인이 익숙한 환경으로 생성해서 진행해주시면 됩니다. 

SDK 는 Amazon Corretto 버전을 사용했으며 java 버전은 17을 선택했고 패키징은 Jar를 선택해줍니다.

 

추가적으로 롬복을 선택해주었는데 Getter, Setter 를 간편히 해준다는데 일단은 그렇게 알고만 넘어갑니다.

 

 

 

프로젝트가 생성되었습니다.

 

생성된 DemoApplication 소스코드는 아래와 같습니다.

@SpringBootApplication 어노테이션을 통해 스프링부트의 설정 자동화, Spring Bean 설정까지 모두 자동화 되도록 되어 있습니다. 스프링 부트의 장점이죠. 추가적인 복잡한 설정은 어딘가에 또 정의를 해야 하겠지만 차근차근 알아가보도록 합니다.

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
public class Demo3Application {

    public static void main(String[] args) {
        SpringApplication.run(Demo3Application.class, args);
    }

}

 

 

 

스프링 부트 서버 실행 

 

정상적으로 생성되었고 실행이 되는지 확인하기 위해 서버를 실행해봅니다.

우측 Gradle 탭을 통해 Tasks->bootJar 항목을 더블클릭 해줍니다.

빌드 과정이 진행되며 스냅샷 jar 파일이 build/libs 폴더에 생성이 됩니다.

우측 마우스 클릭으로 나타나는 컨텍스트 메뉴를 통해 Run 실행해서 서버를 띄워 봅니다.

 

 

run 명령어를 통해 서버를 구동시켜 보니 실행과 함께 종료되는 문제가 있습니다.

 

spring-boot-starter 는 라이브러리 간의 의존성 관리 및 버전 충돌에 대한 이슈를 해결하고 검증되어 사전에 미리 정의해서 제공하는 라이브러리입니다만 웹 컨테이너와 관련한 라이브러리가 빠져 있습니다.
웹서버를 띄워야 하므로 spring-boot-starter-web 라이브러리로 교체해주어야 합니다.

 

변경된 dependencies 내용은 다음과 같습니다.

 

프로메테우스와 그라파나를 이용해 모니터링 시스템을 구축할 예정이어서 액츄에이터와 프로메테우스 라이브러리도 디펜던시에 넣어줍니다. 

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    compileOnly 'org.projectlombok:lombok'
    annotationProcessor 'org.projectlombok:lombok'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    
    implementation 'org.springframework.boot:spring-boot-starter-actuator'
    implementation 'io.micrometer:micrometer-registry-prometheus'
}

 

 

이제 정상적으로 서버가 실행이 되는 것을 확인하실 수 있으며 8080포트로 접속해보면 Whitelabel Error Page 가 뜨긴하지만 서버가 동작하는 것을 확인하실 수 있습니다. 아직 외부에 노출된 endpoint 가 없는 관계로 이제부터 이 작업을 해주겠습니다.

 

서버포트와 외부로 노출될 액츄에이터 endpoint 정의를 위해 application.xml 파일을 수정해줍니다.

application.properties 파일을 application.yml로 변경해주고 계층적 환경 변수로 설정해봅니다.

 

액츄에이터에서 노출할 endpoint를 prometheus 로 설정하고, 서버 포트는 9201로 설정했습니다. 기본이 8080인데 제 임의로 변경했습니다.

management:
  endpoints:
    web:
      exposure:
        include: prometheus
server:
  port : 9201

 

 

rest api 정의

 

RestAPI 서버로 활용할 수 있게 api 를 간단히 정의해보도록 하겠습니다.

 

restcontroller 패키지를 만들고 HelloRestController.java 파일을 생성해 api를 작성해줍니다.

url root '/' endpoint 접근 시 Server Started!! 를 출력하고 hello endpoint 접근 시 Hello, World 를 출력하는 rest api를 작성해줍니다. 

@RestController 어노테이션 호출을 통해 메서드마다 @ResponseBody 를 붙일 필요 없도록 자동화 시켜줍니다.

@GetMapping  의 경우 Get 방식의 @RequestMapping 을 선언해주고 endpoing url을 넣어주게 됩니다.

이제 api call 에 따른 response 로 String 타입을 넘겨주게 되므로 TEXT 나 json 데이타를 정의해서 내려줄 수 있는 기본 골격이 만들어졌습니다. 

package com.example.demo.restcontroller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Date;

@RestController
public class HelloRestController {
    @GetMapping("/")
    public String init(){
        return "Server Started!!";
    }

    @GetMapping("/hello")
    public String hello(){
        return "Hello, World";
    }
}

 

localhost 서버에 접근해보니 정상적으로 api 호출에 따른 결과 텍스트를 보여주고 있습니다.

http://localhost:9201/actuator/prometheus 접근을 통해 프로메테우스에 내려줄 메트릭 정보에도 접근이 가능한 것을 확인 할 수 있습니다.

 

 

 

docker 이미지 생성

 

이제 gradle Tasks 에서 bootJar 더블클릭을 통해 새로운 jar 파일을 만들어 줍니다. 이 파일을 docker 로 올리고 tar 파일로 저장해서 운영서버에 올리는 작업까지 해보겠습니다.

 

 

jar 파일이 생성된 build/libs 폴더에 Dockerfile 을 작성해줍니다.

 

openjdk 18 버전과 jar 파일을 app.jar 파일로 변환, 9201 포트를 EXPOSE 해주는 내용으로 작성했습니다.

FROM openjdk:18
ARG JAR_FILE=*.jar
COPY ${JAR_FILE} app.jar
EXPOSE 9201
ENTRYPOINT ["java","-jar","app.jar"]

 

해당 폴더 경로의 터미널을 열어 docker build 명령어로 도커에 이미지를 올려줍니다.

docker build -t springbootdemo ./

 

빌드 과정을 거쳐 정상적으로 docker desktop 에 이미지가 만들어졌습니다. 

name:tag = springbootdemo:latest 

 

생성된 이미지를 springbootdemo.tar 파일로 저장하여 운영서버로 복사한 뒤 다시 load 하는 과정을 거칩니다.

 

#springbootdemo.tar로 이미지 저장
docker save -o d:\springbootdemo.tar springbootdemo:latest

#springbootdemo 이미지 로드
docker load -i .\springbootdemo.tar

 

 

로드된 이미지는 docker desktop 이미지 탭에서 확인이 가능합니다. 이제 docker run 명령어를 통해 컨테이너로 서버를 띄워줍니다.

데몬으로 실행되며 9201 포트 맵핑 시켜서 진행했습니다.

docker run -d -p 9201:9201 springbootdemo

 

운영서버 docker desktop에서 정상적으로 서버가 실행되는 것을 확인까지 했습니다.

 

 

 

마무리

 

여기까지 docker 에서 spring boot 서버를 띄우는 과정을 진행해보았습니다. 

다음 과정은 프로메테우스와 그라파나를 이용해 스프링 부트 모니터링 구축과정을 진행해보겠습니다.

 

운영서버 배포 작업은 파일 복사 방식으로 진행중인데 현재 Jenkins 환경하에 소스관리가 되고 있지만 docker에 배포 자동화는 구성되어 있지 않았고, git 을 이용한 ci/cd 구축 이후에 자동화할 예정이어서 현재는 이렇게 불편한 과정을 거칩니다.

하면 할수록 할게 정말 많은데 그만큼 얻는것도 많은듯 합니다.

 

 

https://quantrader.tistory.com/154

 

[docker] docker desktop 설치, 챗봇 서버 이미지 배포 테스트

윈도우에 WSL2 docker 설치 후 테스트 서버로 시운전까지 마쳐주고 설치해준 도커 서버는 삭제를 해주었습니다. 좀 더 편리한 환경을 위해 Docker Desktop을 설치해서 운용해보기로 합니다. 먼저 Docker D

quantrader.tistory.com