spring boot 도커환경 auto reload 세팅

uchan·2023년 11월 21일
0

배경

spring boot 를 시작하면서 한가지 불편함을 겪었다. 바로 컴파일 언어와 인터프리터 언어 간 차이 때문에 발생하는 이슈였다. python 의 경우 컴파일을 거치지 않고 실행되는 반면, java 의 경우 컴파일을 한 후 jar 파일을 만들어 실행한다. 이 때문에 도커 개발환경에서 django 의 경우 내 디렉토리를 마운팅해주면 코드를 수정할 때마다 서버가 재시작되어 바로 반영 가능하다. 그러나 java 의 경우 내가 코드를 수정하고 컴파일하여 새로운 jar 파일을 토대로 서버를 재시작해야되기 때문에 쉽지 않다. 이와 관련하여 어떻게 해결해야할 지 구글링 및 스프링 문서를 뒤져봤고 해결한 방법을 정리하고자 한다.

spring boot devtools

spring Boot Application을 개발하고 디버깅을 하는데 도움이 되는 도구 모음을 의미한다. 개발 단계에서 자동으로 다시 로드되는 기능을 제공하여 개발자가 변경 사항을 신속하게 확인할 수 있도록 도움을 준다. 또한 라이브 리로딩, 프로퍼티 변경 감지 및 자동 재시작과 같은 기능도 제공한다.

docker container 에서..

intellij IDE 에서 spring boot devtools 관련하여 설정 및 관리가 가능하다. 그러나 나는 직접 devtools 를 관리하여 docker container 단에서 설정하기를 원했고, 이와 관련된 레퍼런스를 조사하여 다음과 같이 코드를 추가해주었다.

code

entrypoint.sh

#!/bin/bash

# Dockerfile 에서 ENTRYPOINT ["./entrypoint.sh"] 로 실행된다

start_server() {
  (sleep 30; ./gradlew buildAndReload --continuous -PskipDownload=true -x Test) &
  ./gradlew bootRun -PskipDownload=true
}

start_server

직접 정의한 buildAndReload task 를 백그라운드로 돌려주고 빌드 시 패키지 다운로드와 테스트를 스킵하도록 처리해준다.

application.properties

# devtools
spring.devtools.restart.enabled = true  # restart 활성화
spring.devtools.restart.additional-paths = .
spring.devtools.livereload.enabled = true  # livereload 활성화
spring.devtools.restart.trigger-file = .restart  # 트리거 파일로서 해당 파일이 수정되면 서버가 재시작된다

docker-compose

version: '3.9'
services:
  db:
    container_name: postgresql
    image: postgres:15-alpine
    ...
  backend:
    build:
      context: ./backend
      dockerfile: Dockerfile
      target: development  # not production
    container_name: backend
    environment:
      - ...
    depends_on:
      db:
        condition: service_healthy
    ports:
      - 8080:8080
    restart: always
    volumes:
      - ./backend:/home/deploy/app/backend

volume 설정에 ./backend:/home/deploy/app/backend 와 같이 넣어줌으로써 내 코드를 마운트해주었다. 이로서 내가 코드 수정하면 컨테이너 내 코드도 같이 수정되도록 한다.

build.gradle

...

dependencies {
	...
	developmentOnly "org.springframework.boot:spring-boot-devtools"
}

...

task getDeps(type: Copy) {
	duplicatesStrategy = DuplicatesStrategy.EXCLUDE
	from configurations.compileClasspath into "libs/"
	from configurations.runtimeClasspath into "libs/"
}

task buildAndReload {
	dependsOn build
	mustRunAfter build    // buildAndReload must run after the source files are built into class files using build task
	doLast {
		new File(".", ".restart").text = "${System.currentTimeMillis()}" // update trigger file in root folder for hot reload
	}
}

getDeps task 의 경우 변경된 파일을 반영한다. 그리고 buildAndReload task 를 통해 빌드하면 .restart 파일도 수정하도록 한다.

auto reload 순서 정리

  1. 이미지 빌드하여 컨테이너를 띄운다
  2. 코드를 수정한다
  3. 코드가 변경됨을 감지하고 재빌드한다
  4. 빌드가 끝나면 .restart 를 수정한다
  5. devtools 에서 .restart 수정됨을 감지하고 spring 서버를 재시작한다.

references

0개의 댓글