인프라 개선
현재 Spring boot는 도커에서 실행되고 있지 않다. MySQL만 도커로 실행 중이고, Spring boot 서버는 서버 로컬에서 직접 jar 파일로 실행해 둔 상태이다.
배포 서버(오라클 클라우드)가 프리티어 이기 때문에 추후에 클라우드 플랫폼 자체를 변경할 가능성이 있음. 추후에 이식성, 확장성, 일관성 등을 고려하여 서버 클라우드 플랫폼을 다른 곳으로 변경하더라도 쉽게 옮길 수 있도록 도커로 실행하는 것으로 변경하겠다.
📌 MySQL 컨테이너 데이터 보존 필요
현재 도커로 실행중인 MySQL이 볼륨 설정이 되어있지 않다. 이는 컨테이너가 삭제되면 내부에 데이터들이 모두 날아간다는 의미이다. 호스트 서버에 MySQL 데이터가 저장될 수 있도록 마운트 설정을 추가해야 한다.
이미 실행 중인 MySQL 컨테이너에 볼륨 설정을 추가하기 위해서는 컨테이너를 새롭게 run 해야 한다. 따라서, 기존에 사용 중이던 MySQL 컨테이너의 데이터를 호스트 서버에 마운트하여 데이터를 보존할 수 있도록 한다.
1. 현재 실행 중인 MySQL 컨테이너 데이터 디렉토리 확인
"Mounts" 부분에서 데이터 디렉토리가 확인이 가능하다.
docker inspect <컨테이너 이름 또는 ID>
2. 현재 컨테이너 중지 후, 컨테이너 내부 MySQL 데이터를 호스트 서버로 복사
컨테이너 내부에 MySQL 데이터를 호스트 서버(내 ubuntu)로 복사해온다.
# 도커 MySQL 컨테이너 중지
docker stop <컨테이너 이름 또는 ID>
# MySQL 데이터 서버에 복사해옴
docker cp <컨테이너 이름 또는 ID>:/var/lib/mysql /var/lib
3. 복사해 온 MySQL 디렉토리 소유권 설정
# 일회성 컨테이너를 실행하여 mysql 사용자의 ID를 확인. 일반적으로, mysql 사용자의 UID와 GID는 999임
docker run --rm -it mysql:8.0.33 /bin/sh -c 'id mysql'
sudo chown -R 999:999 /var/lib/mysql
4. 복사해온 데이터를 이용하여 새로운 MySQL 컨테이너 실행 (마운트 설정)
백업해 온 데이터를 도커 컨테이너 내부에 마운트 하여 새로운 컨테이너 생성 및 실행한다.
docker run -d --name mysql-container-new \
-p 3306:3306 \
-e MYSQL_ROOT_PASSWORD=<비밀번호> \
-v /var/lib/mysql:/var/lib/mysql \
mysql:8.0.33 \
--character-set-server=utf8mb4 \
--collation-server=utf8mb4_unicode_ci
5. 새로운 MySQL 컨테이너 접속하여 데이터 있는지 확인
docker exec -it mysql-container-new /bin/sh
이렇게 새로운 컨테이너가 실행되고, MySQL의 데이터가 그대로 있다. 이제 호스트 서버에 MySQL 데이터가 영구적으로 저장된다.
📌 Spring boot 도커로 실행하는 것으로 변경 (+MySQL 컨테이너와 연결)
기존 서버에 java를 직접 설치하여 Spring boot를 실행하던 것을 추후 일관성, 이식성을 위해 도커를 이용하여 실행하는 것으로 변경할 것이다. MySQL 컨테이너와의 연결을 위해 도커 네트워크 설정도 추가하도록 한다.
1. Docker network 생성 및 설정
- MySQL 컨테이너와 Spring boot 컨테이너의 통신을 위해 network를 생성하고 설정을 적용한다.
docker network create bitrun
- 실행 중인 MySQL 컨테이너 네트워크 설정 추가하여 재실행
docker run -d --network bitrun --name mysql-db \
-p 3306:3306 \
-e MYSQL_ROOT_PASSWORD=[비밀번호] \
-v /var/lib/mysql:/var/lib/mysql \
mysql:8.0.33 \
--character-set-server=utf8mb4 \
--collation-server=utf8mb4_unicode_ci
2. application.yml 파일 수정
localhost:3306 -> mysql-db(MySQL 컨테이너 이름):3306 으로 변경
spring:
messages:
basename: messages, errors
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://mysql-db:3306/bitrun?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Seoul&characterEncoding=UTF-8
username: root
password: [비밀번호]
.....
3. Spring boot 이미지 빌드를 위한 Dockerfile 작성
프로젝트에 이미지 빌드를 위한 도커파일을 추가하였다. 프로젝트 최상단에 파일 생성.
FROM bellsoft/liberica-openjdk-alpine:17
ARG JAR_FILE=build/libs/*.jar
COPY ${JAR_FILE} app.jar
# 도커 컨테이너를 시작할 때 실행할 명령어
ENTRYPOINT ["java","-jar","/app.jar"]
4. 프로젝트 빌드 (jar 파일 생성)
Docker Hub에 도커 이미지를 업로드하기 위하여 프로젝트를 먼저 빌드하여 jar 파일을 만들도록 한다. 아직 프로젝트에 테스트 코드가 작성되어있지 않아서 테스트 코드 없이 빌드한다.
./gradlew clean build -x test
5. Dockerfile로 이미지 생성
아래 명령어로 도커 이미지를 빌드한다. docker images로 이미지 빌드 확인.
# 도커 이미지 빌드
docker build -t spring-bitrun --platform=linux/x86_64 .
6. Spring boot 이미지 컨테이너 실행
빌드된 이미지를 이용하여 컨테이너를 실행한다. MySQL과 연동을 위해 이전에 생성했던 네트워크 설정을 넣어준다.
docker run -d --name spring-app --network bitrun -p 8080:8080 spring-bitrun
7. 웹애플리케이션 동작 확인
내가 배포한 도메인으로 접속하여 서버가 정상적으로 실행되는지 확인한다.
📌 결과 및 추후 개선점..
결과적으로 변경된 점은 다음과 같다.
- 컨테이너가 삭제되어도 MySQL 데이터가 호스트 서버에 남게 됨
- 도커로 실행하지 않던 Spring boot 애플리케이션 -> 도커로 실행
추후에 개선할 점은 다음과 같다.
- docker compose를 활용하여 MySQL 컨테이너 + Spring boot 컨테이너를 묶어서 한 번에 관리하면 편리하지 않을까.
- 빌드/배포 자동화 적용을 통해 배포 과정에 드는 비용을 줄여보자.
개인 프로젝트 Github
배포 : https://coinrun.kr/
모든 피드백은 환영입니다.