동아리 개발환경 구축 (spring boot, mysql 도커로 배포하기)
개요
개발 동아리에서 개발부장으로 스터디를 관리하게 되었다. 혼자 공부하는 것과 동아리에서 활동하는 것의 가장 큰 차이점은 협업이라고 생각했다. 그래서 프론트엔드와 백엔드의 협업 방법을 생각을 해봤다.
1. 클라우드 서버에 배포 후 백엔드 API이용
2. 프론트엔드 로컬 PC에 백엔드 서버 배포 후 API이용
1번은 돈이 든다는 문제점과 여러 가지 프로젝트진행 시 동아리 원들이 팀을 나눠 스터디를 동시에 진행하게 된다면 한 개의 EC2에 모든 프로젝트를 배포하게 된다면 포트 설정을 따로 해주어야 한다는 번거로움이 있어 2번을 선택하게 되었다.
2번을 선택한 후 프론트엔드 측에서 데이터베이스를 설치하고, 자바를 설치하고 spring boot 서버를 띄우는 것은 불필요한 작업이라고 생각이 되어 도커 컨테이너를 이용해서 명령어 하나만으로 백엔드 API를 이용할 수 있는 방법을 생각했다.
도커로 서버 올리기
생각한 방법이 도커를 이용해서 mysql 컨테이너와 spring boot 서버 컨테이너를 배포한 후 두 컨테이너를 연결하여 프론트 측에서 백엔드 API를 이용하는 방법이다.
mysql 컨테이너와 spring boot 서버 컨테이너를 연결하기 위해 같은 network로 설정해 주어야 했다. 또 docker-compose를 이용해 프론트엔드 개발자 분들이 docker compose up 명령만을 통해 쉽게 서버를 구축했으면 좋겠다고 생각했다.
문제1
프론트엔드 개발자 분들이 docker compose up 명령만을 통해서 쉽게 구축할 수 있게 하고 싶었지만 mysql 컨테이너에 spring boot에서 사용하는 데이터베이스를 생성해 주지 않아 에러가 발생했다. 즉 프론트엔드 개발자분들이 mysql에 접속하여 사용할 데이터베이스를 생성해 주어야 한다는 것이다.
해결
위 문제 과정도 생략하고 싶었다. 명령어 하나만으로 모든 과정을 해결하고 싶었다.
그러기 위해 데이터베이스를 도커 이미지 생성할 때 자동생성하기 위해 컨테이너 내부의 docker-entrypoint-initdb.d에 sql 스크립트 파일을 저장해야 한다.
컨테이너가 실행될 때 docker-entrypoint-initdb.d에 있는 sql 스크립트가 자동 반영된다.
그러기 위해 init 폴더 안에 init.sql을 생성해 두고 docker-compose파일에 볼륨을 사용하여 마운트 시켜준다.
volumes:
- "./init/:/docker-entrypoint-initdb.d/"
결국 폴더의 구조는 아래 사진과 같다
문제2
위 과정을 수행 후 docker compose up 명령을 통해 컨테이너를 실행했을 때 spring boot에 데이터베이스가 연결이 안 되는 오류가 발생했다. 혹시 데이터베이스가 생성이 안 된 건 아닐까 mysql 컨테이너에 접속해서 확인해 본 결과 데이터베이스는 생성이 잘 되어있었다. 문제를 찾아본 결과 mysql 컨테이너가 생성되고 데이터베이스를 생성하기 전에 spring boot 컨테이너가 먼저 실행되어서 연결이 안 된 문제이다.
해결
위 문제를 해결하기 위해 spring boot 컨테이너를 일정 시간이 지난 후 실행시키는 것으로 해결하기 위해 아래 command를 사용해서 20초 후 실행되도록 설정했다.
command: sh -c "
/bin/sleep 20 &&
java -jar /app.jar"
과정
스프링의 datasource 부분에 127.0.0.1 대신 my-db라는 컨테이너 이름으로 연결해 준다.
datasource:
url: jdbc:mysql://my-db:3306/dbtest
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: 1234
docker-compose.yaml 파일이다.
version: '3.9'
services:
my-db:
image: mysql:latest
container_name: my-db
ports:
- "3307:3306"
restart: always
environment:
MYSQL_ROOT_PASSWORD: 1234
networks:
- testnetwork
volumes:
- "./init/:/docker-entrypoint-initdb.d/"
spring:
depends_on:
- my-db
build: .
image: mission-backend:latest
container_name: spring
ports:
- "8080:8080"
networks:
- testnetwork
command: sh -c "
/bin/sleep 20 &&
java -jar /app.jar"
networks:
testnetwork: {}
후기
이러한 과정을 통해 프론트엔드 측에서 터미널에서 docker compose up 명령만을 통해 백엔드 API를 이용할 수 있게 되어 개발환경 구축시간을 줄이면서 협업을 할 수 있게 되었다.