Docker compose로 Spring Boot 올리기
Docker안녕하세요 Lovefield 입니다.
요즘 서버 인프라를 구성하고 있습니다. 인프라는 다양한 방식으로 구성할 수 있지만, 그 중에서 컨테이너 기반인 Docker를 도입하고 있습니다. 이번에는 Docker에 Spring Boot를 올리는 방법에 대해 이야기해볼까 합니다. 마침 Devellany님께서 만들어놓은 spring-boot-sample이 있어서 이를 바탕으로 같이 살펴보도록 하죠!
우선 작업 디렉토리 구조입니다.
- app
- db
- data
docker-compose.yml
저는 docker-compose
를 활용합니다. Docker가 컨테이너 자체를 다루는 친구라면 docker-compose
는 여러 컨테이너를 하나로 관리해주는 아이랍니다. 그래서 컨테이너를 세부적으로 나누어 사용할 계획이기에 이를 사용하고 있습니다. docker-compose
와 디렉토리 구조를 맞추기 위해 컨테이너 당 하나의 디렉토리를 할당해서 사용합니다.
docker-compose 란?
Docker에서 사용하는 컨테이너 공간을 한 곳에서 관리하기 위한 도구입니다. yml
파일로 작성하며, docker-compose
명령어를 활용하여 여러 개의 컨테이너를 한 번에 관리할 수 있습니다.
docker-compose.yml
파일을 작성해 볼까요? docker-compose
는 1버전 부터 3버전까지 있습니다. 최신 소프트웨어를 사용하기 위하여 버전을 3으로 명시해줍시다.
version : “3”
services:
db:
app:
버전 다음에 오는 services
는 실질적인 컨테이너 집합 요소입니다. services
안에 입력하는 값으로 하나의 컨테이너가 만들어져 유기적으로 동작하게 되죠. 이번에 사용할 컨테이너는 "db", "app" 이렇게 두 가지입니다.
MySQL을 설치할 "db"컨테이너를 먼저 작성합니다.
db:
container_name: spring-db
image: mysql
environment:
MYSQL_DATABASE: spring_db
MYSQL_USER: spring
MYSQL_PASSWORD: spring_pw
MYSQL_ROOT_PASSWORD: root_pw
volumes:
- ./db/data:/var/lib/mysql:rw
ports:
- “3306:3306”
restart: always
container_name
: 컨테이너 이름 지정image
: Docker hub에 올라가있는 image 리스트에서 사용할 이미지 명과 태그environment
: 컨테이너 내부에서 사용할 인자volumes
: local 디렉토리와 컨테이너 경로 매칭ports
: 외부에서 접속하는 포트를 Docker 내부 포트와 매칭restart
: 컨테이너 오류와 같이 종료되었을 때 다시 시작할지 여부
각 속성은 위와 같은 역할을 담당합니다. MySQL 이 올라갈 컨테이너이므로 컨테이너 명은 spring-db
로 합시다. Spring Boot에서 DB를 접근하고자 할 때 포트 번호를 포함하여 spring-db:3306
으로 적습니다. docker-compose.yml
로 생성하는 컨테이너는 자동으로 하나의 네트워크 그룹에 포함 됩니다. 컨테이너 이름과 포트 번호를 이용해 서로를 찾아낼 수 있죠.
dockerfile
파일로 이미지를 생성할 수도 있지만, 지금 당장 그정도로 복잡한 이미지 파일이 필요하지 않습니다. Docker hub에 공유되어 있는 이미지를 활용하여 MySQL 컨테이너를 구성할겁니다.
environment
를 통해 간단한 db 정보를 설정합니다.MYSQL_DATABASE
를 통해 데이터베이스명을,MYSQL_USER
를 통해 DB의 유저명을,MYSQL_PASSWORD
를 통해 DB 유저의 패스워드를,MYSQL_ROOT_PASSWORD
를 통해 root의 패스워드를,각각 지정해주면
"db"컨테이너의 MySQL 초기 설정이 완료됩니다.
volumes
에 잡은 경로인 "/var/lib/mysql:rw"는 MySQL의 실제 저장 경로입니다. Docker를 구동을 하게 되면 "db/data"에 파일들이 많이 생성될 텐데요. 이것들이 DB에 접속했을 때 보이는 정보랍니다. 이렇게 만들어진 이유는 컨테이너가 종료 혹은 삭제 되었을 때 내부 데이터가 날아가는걸 방지하기 위함입니다. 로컬에 데이터를 보관하여 다시 컨테이너를 생성할 때도 DB는 그대로 남아있습니다.
다음은 Spring Boot가 실행 될 "app" 컨테이너입니다.
app:
container_name: spring-app
image: openjdk:11-jdk
ports:
- “8082:8082”
volumes:
- ./app:/app
working_dir: /app
command: [“./gradlew”, “bootrun”]
depends_on:
- db
restart: always
"db"컨테이너와 다르게 추가된 명령어가 보이죠? 각각 다음과 같은 기능을 수행합니다.working_dir
: 컨테이너가 실행되고 나서 command명령어가 실행되는 위치command
: Bash나 PowerShell과 같은 커멘드 명령어를 실행depends_on
: 컨테이너 실행 우선순위 지정. 하위로 기입한 컨테이너가 정상적으로 실행 된 후 현재 컨테이너를 실행
컨테이너 이름은 "spring-app"으로 지정합니다. Spring Boot로 사용할 spring-boot-sample
이 Java 11 기반이므로 이미지에 openjdk:11-jdk
를 기입하여 버전을 맞춰줍니다.
Spring Boot는 내부 톰캣을 이용해 8082포트로 지정되어 있습니다. 외부에서 8082포트로 접속하면 Docker 내부 포트로 8082를 바라보도록 매칭해줍시다.
Spring Boot 구성 파일을 저장할 app 디렉토리에 맞춰줍니다. 컨테이너 내부에서 app 디렉토리를 찾을 때 local의 app 디렉토리를 찾아 연결해 줄 것입니다.
working_dir
으로 컨테이너가 기본적으로 command를 실행할 경로를 지정합니다. Spring Boot 소스가 app 안에 있으므로 이곳으로 지정해줍니다.
Spring Boot를 실행하기 위한 명령어인 "./gradlew bootrun"을 입력합니다. docker-composer.yml 양식에 맞도록 [“./gradlew”, “bootrun”]으로 변경했습니다.
depends_on
을 이용해 "db"컨테이너가 구동된 후 "app"컨테이너가 실행되도록 지정합니다. 이렇게하면 MySQL이 먼저 실행된 다음 "app"디렉토리가 실행됩니다.
이제 "app"디렉토리 내에 spring-boot-sample
을 불러와야 합니다.
cd app & git clone https://github.com/devellany/spring-boot-sample.git .
"app" 폴더 내에 Git clone으로 코드를 가져옵니다. 저희는 이미 "app" 디렉토리를 생성하여 작업 디렉토리로 지정해놓았기에 "."옵션을 사용해야 합니다. "app"디렉토리 내에 또 다른 폴더가 생성되는걸 보고싶지 않다면 말이죠.
spring-boot-sample
에서는 기본적으로 설정해야 할 두 가지가 있습니다.
우선 node_modules
를 사용하고 있기에 다음 명령어를 실행해줘야 합니다.
cd src/main/resources & npm install
설치가 완료되면 다음은 application.yml
설정인데요.
해당 샘플에서는 application.yml
을 통해 기본적인 환경설정을 하고 있습니다.
server:
mail:
host: #SMTP_HOST
port: #SMTP_PORT
username: #ID
password: #PASSWORD
properties:
mail:
smtp:
auth: false
timeout: 50000
starttls:
enable: true
app:
host: http://localhost:8082
title: Devellany's sample
version: ver.prototype
help-email: #MAIL_SENDER_ADDRESS
token-available-period: 60
위와 같이 파일을 생성해줍니다.
자 이제 준비는 다 끝났습니다!
docker-compose up -d
위의 명령어를 이용해 `docker-compose`를 실행합시다.그러면 필요한 `image`를 다운로드하고 기재한 명령어대로 컨테이너를 생성해줄거에요.완료 표시가 뜬다면 `http://localhost:8082`에 들어가서 정상적으로 나오는지 확인합시다.완료 표시가 떴다고 해도 Spring Boot가 실행 되기까지 1~2분 정도 더 소요된답니다.
이처럼 구성한 컨테이너를 더이상 사용하지 않는다면
docker-compose down
명령어를 통해 docker-compose.yml
파일에 등록된 컨테이너들이 전부 제거 되고 네트워크 구성도 해제된답니다.
이렇게 Docker를 활용하여 Spring Boot를 올려 보았습니다. 생각보다 어려운 설정이 존재하지 않죠? 이 글을 보고 따라하신다면 쉽고 빠르게 로컬 개발 환경을 구축해볼수 있습니다.
도움이 되었길 빌며 이만 글을 마치겠습니다.