문제를 해결하면서 차근차근 도커 볼륨 설정을 해보자.
docker volume이란?
데이터가 컨테이너 수명 주기 이후에도 지속될 수 있도록 보장해주는 솔루션이다.
컨테이너가 재시작해도 h2 데이터베이스의 데이터가 유지될 수 있도록 컨테이너 내부에서 외부에 존재하는 db 데이터를 참조할 수 있다.
# url: jdbc:h2:mem:mydb # 인메모리
url: jdbc:h2:file:./data/mydb # 파일 기반
현재 h2 db 설정은 인메모리(in-memory)에서 file 기반으로 바꾸어서 데이터가 file에 계속 유지될 수 있도록 해뒀다.
(도커에서 띄워도 데이터가 파일에 계속 기록되도록 하기 위함이다)
문제 상황
설정 파일인 application-local.yml을 로컬 환경과 도커 환경에서 함께 사용하고 있다.
그런데 도커 환경에서는 작업 디렉토리를 /usr/src/app로 따로 설정해두었기 때문에,
로컬환경과 db 데이터가 존재하는 경로가 다르다.
- 로컬 : ./data
- 도커: /usr/src/app/data
Dockerfile
# JDK 17을 기반으로 하는 이미지 사용
FROM openjdk:17-alpine
# 작업 경로 설정
WORKDIR /usr/src/app
ARG JAR_PATH=./build/libs
# 빌드한 파일 옮기기
COPY ${JAR_PATH}/springapp-0.0.1-SNAPSHOT.jar ${JAR_PATH}/springapp-0.0.1-SNAPSHOT.jar
# 실행하기
CMD ["java","-jar","./build/libs/springapp-0.0.1-SNAPSHOT.jar"]
작업 경로를 따로 설정해둔 이유는 도커 이미지에 존재하는 폴더가 덮어씌워지지 않도록 방지하기 위해서이다.
해결 방법
환경 변수를 사용하면 된다.
1. 환경 변수 설정하기 + 도커 볼륨 설정
docker-compose.yml
version: '3.7'
services:
app:
build:
context: .
dockerfile: Dockerfile
environment: # 환경 변수 설정
- SPRING_DATASOURCE_URL=jdbc:h2:file:/usr/src/app/data/mydb;DB_CLOSE_ON_EXIT=FALSE
platform: linux/amd64
ports:
- "8080:8080"
# h2data 볼륨을 컨테이너 내부의 /usr/src/app/data에 매핑
volumes:
- h2data:/usr/src/app/data
# 볼륨 정의 (기본 설정 사용)
volumes:
h2data:
volumes.h2data (맨 마지막 줄)
볼륨을 정의한다.
볼륨이 매번 생성되는 것은 아니고, services에서 볼륨이 참조되면 볼륨이 이미 존재하는지 확인하고 없을 경우에만 기본 설정으로 생성된다. 볼륨 이름인 h2data의 : 뒤에 설정을 추가할 수 있다.
services.app.volumes
h2data라는 볼륨을 컨테이너 내부의 /usr/src/app/data에 매핑한다.
=> 컨테이너의 `/usr/src/app/data`에 기록된 모든 내용이 실제로 `h2data` 볼륨에 저장된다.
✅ 볼륨은 Docker가 관리한다는 것을 기억할 것!
DB_CLOSE_ON_EXIT : 마지막 연결이 닫힐때 데이터베이스가 종료되지 않도록 한다.
즉 애플리케이션이 최종 종료되기 전까지 계속 DB가 연결되어있어 DB Connection이 자주 열고 닫힘에 따른 문제가 발생하지 않도록 한다.
2. 환경 변수 적용하기
application-local.yml
spring:
datasource:
driver-class-name: org.h2.Driver
url: ${SPRING_DATASOURCE_URL:jdbc:h2:file:./data/mydb;DB_CLOSE_ON_EXIT=FALSE}
SPRING_DATASOURCE_URL이라는 환경 변수를 찾고, 없으면 : 뒤에 나와있는 기본값을 사용한다.
결과
로컬로 실행하던 Docker에서 실행하던 별도의 구성 파일 없이 적절하게 H2 데이터베이스가 사용된다.
'문제&해결' 카테고리의 다른 글
도커 컨테이너의 ip 주소는 왜 127.0.0.1(localhost)가 아닐까? (0) | 2024.03.09 |
---|---|
로컬, docker 컨테이너 포트 충돌 : 포트 관리 중요성 (mysql) (0) | 2024.03.09 |
웹소켓 취약점 해결 : 인증 도입 (STOMP, Jwt, Spring Security) (3) | 2024.02.20 |
[스프링 시큐리티] Spring Security의 Filter에서 의존성 전달받기 (빈 주입) (0) | 2024.01.24 |
yml 파일이 깃허브에 올라갔을때 커밋에서 삭제하는 방법 (0) | 2023.09.29 |