이번 포스팅은 컨테이너 환경에서 AWS RDS를 사용하던 데이터베이스를 비용 이슈 때문에 로컬 데이터베이스로 전환하는 과정에서 마주친 이슈와 해결 방법을 공유하고자 합니다.
기존 설정에서는 AWS RDS 외부 관리형 데이터베이스 서비스 사용해서 Docker 컨테이너 내부 또는 외부에서 액세스할 수 있고 인프라 관리가 필요 없기 때문에 데이터베이스에 대한 Docker Container를 docker-compose.yml 파일에 추가할 필요가 없었습니다.
반면 로컬 데이터베이스를 사용하고 이를 Docker 컨테이너로 실행 하고자 할 때는 MariaDB 데이터베이스 서버를 별도의 컨테이너로 구성하고 관리하기 위해 docker-compose.yml 파일에 데이터베이스 서버를 실행하는 서비스를 추가해야합니다.
version: '3.8'
services:
app:
build:
context: .
dockerfile: Dockerfile
ports:
- "8080:8080"
environment:
- SPRING_DATASOURCE_URL=jdbc:mariadb://spring-container.rds.(rds 주소)amazonaws.com:3306/container
- SPRING_DATASOURCE_USERNAME=username
- SPRING_DATASOURCE_PASSWORD=password
nginx:
image: nginx:latest
ports:
- "80:80"
volumes:
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf
depends_on:
- app
version: '3.8'
services:
app:
build: .
ports:
- "8080:8080"
environment:
SPRING_DATASOURCE_URL: jdbc:mariadb://db:3306/container
SPRING_DATASOURCE_USERNAME: root
SPRING_DATASOURCE_PASSWORD: password
depends_on:
- db
nginx:
image: nginx:latest
ports:
- "80:80"
volumes:
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf
depends_on:
- app
db:
image: mariadb:latest
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: container
volumes:
- db-data:/var/lib/mysql
volumes:
db-data:
기존과 동일하게 로컬 환경에서 Docker 컨테이너를 빌드하고 실행하기 위한 명령어인 docker-compose up --build 터미널에 작성하면
오류없이 잘 작동이 됩니다. (사실 여기까지는 문제가 없는 듯 해서 굉장히 흡족했습니다.)
로그인이 되지 않아 의심스러운 마음으로 회원가입을 진행했습니다.
하지만 다음과 같은 오류가 발생했습니다.
app-1 | 2024-02-28T18:54:11.948+09:00 WARN 1 --- [nio-8080-exec-3] o.m.jdbc.message.server.ErrorPacket : Error: 1146-42S02: Table 'container.user' doesn't exist
app-1 | 2024-02-28T18:54:11.949+09:00 ERROR 1 --- [nio-8080-exec-3] pack.dao.user.UserDAO : 유저 회원 가입 에러
app-1 |
app-1 | org.springframework.jdbc.BadSqlGrammarException:
app-1 | ### Error updating database. Cause: java.sql.SQLSyntaxErrorException: (conn=13) Table 'container.user' doesn't exist
app-1 | ### The error may exist in pack/mapper/user/UserMapper.java (best guess)
app-1 | ### The error may involve pack.mapper.user.UserMapper.userInsertData-Inline
app-1 | ### The error occurred while setting parameters
app-1 | ### SQL: INSERT INTO user (user_id, user_pwd, user_name, user_tel, user_email, user_addr, user_jumin) VALUES (?, ?, ?, ?, ?, ?, ?)
데이터베이스와 상호작용하는 DAO 에 log에서 유저 회원 가입 에러가 찍혔고 SQLSyntaxErrorException 가 발생했습니다.
기본적으로 Docker 컨테이너 내에서 MariaDB를 실행할 때, 해당 컨테이너는 별도의 격리된 환경에서 동작합니다.
즉, 컨테이너가 호스트 시스템의 나머지 부분과
분리되어 있음을 의미하며, 따라서 호스트 시스템에 설치된 MariaDB 인스턴스와는 다른,독립된데이터베이스 인스턴스를 제공합니다.
AWS RDS와 같은 관리형 데이터베이스 서비스를 사용할 때는 데이터베이스가 클라우드에 호스팅되어 있으며, 애플리케이션에서 이를 직접 연결하여 사용했습니다. 이 경우 데이터베이스는 지속적으로 운영되며, 데이터는 RDS 인스턴스 내에 지속적으로 저장됩니다.
하지만 일정 시간을 사용한 후에는 비용이 발생하니 과금이 되지 않게 꾸준하게 모니터링 해주세요!
반면, 로컬 환경에서 Docker 컨테이너로 MariaDB를 실행하는 경우, 컨테이너를 재시작하거나 삭제할 때 기본적으로 컨테이너 내의 모든 데이터가 손실됩니다. 이유는 Docker 컨테이너가 상태를 유지하지 않는(stateless) 특성 때문입니다.
따라서 기존에 로컬 또는 다른 환경에서 사용하던 MariaDB 데이터베이스의 데이터를 Docker 컨테이너 내의 MariaDB로 이전하기 위해산 데이터 덤프(dump) 및 복원(restore) 작업이 필요합니다.
이 과정을 통해 기존 데이터베이스의 데이터를 추출하여 파일로 저장(dump)한 후, 이 파일을 사용해 Docker 컨테이너 내의 MariaDB 데이터베이스에 해당 데이터를 복원(restore)할 수 있습니다.
데이터베이스를 덤프하고 복원하는 명령문을 작성해봅시다.
저는 Window 운영체제와 DB는 MariaDB 그리고 IntelliJ IDEA 터미널 창에서 작성했다는 점 참고해주세요!
mysqldump -u [username] -p[password] --result-file=database_dump.sql container
하지만 명령어가 인식되지 않는 오류 발생🤦♂️
mysqldump : 'mysqldump' 용어가 cmdlet, 함수, 스크립트 파일 또는 실행할 수 있는 프로그램 이름으로 인식되지 않습니다.
이름이 정확한지 확인하고 경로가 포함된 경우 경로가 올바른지 검증한 다음 다시 시도하십시오.
mysqldump 명령어가 인식되지 않는 오류가 발생한 것은 MySQL 또는 MariaDB의 클라이언트 시스템의 PATH 환경 변수에 포함되지 않았기 때문입니다.
즉, windows 운영체제를 사용하시는 분들은 환경 PATH 잡아주셔야 합니다.
MariaDB의 설치 경로를 확인합니다. (일반적으로 bin 폴더 안에 mysqldump 실행 파일이 있다.)
시스템의 PATH 환경 변수에 MySQL 또는 MariaDB의 bin 디렉토리 경로를 추가합니다.
검색창에 "환경 변수 편집"을 입력하고 고급에서 "환경 변수"을 클릭합니다.
시스템 변수" 섹션에서 "Path" 변수를 찾아 "편집"을 클릭합니다.
새로 만들기"를 클릭하고 MariaDB의 bin 디렉토리 경로를 추가 후 저장합니다.
PATH 환경 변수를 수정한 후에는 명령 프롬프트, 터미널 창을 닫고 다시 실행시켜야 합니다!
명령문이 성공적으로 실행이 되었으면 사진과 같이 dump 파일이 생겨야 합니다.
생성된 덤프 파일을 Docker 컨테이너로 복사하는 과정이 필요합니다!
docker cp database_dump.sql [MariaDB_컨테이너_ID_또는_이름]:/path/to/database_dump.sql
[MariaDB컨테이너 ID 또는 이름]은 MariaDB 컨테이너의 ID나 이름으로 대체하고, /path/to/는 파일을 복사할 컨테이너 내의 경로입니다.
저는 컨테이너의 루트 디렉토리에 복사하려고 /를 사용했습니다.
docker cp database_dump.sql acornproject-db-1:/
MariaDB컨테이너 ID 또는 이름은 docker ps 명령어도 확인 가능합니다.
컨테이너의 쉘에 접속하는 명령어를 작성합니다.
docker exec -it [컨테이너 ID 또는 이름] bash
복사한 SQL 파일을 MariaDB 데이터베이스에 적용합니다.
mariadb -u root -p[password] [컨테이너 ID 또는 이름] < /database_dump.sql
지금까지 오류없이 잘 따라왔다면 컨테이너 내부에 들어가서 테이블을 확인
mariadb -u root -p
이 명령어를 실행한 후, 비밀번호 입력 프롬프트가 나타나면 자신이 설정한 DB 비밀번호을 입력합니다
이렇게 하면 MariaDB 커맨드라인 인터페이스에 접속할 수 있으며, 여기에서 데이터베이스를 직접 조작할 수 있는 SQL 명령어들을 실행할 수 있습니다.
이런 화면이 나오면 성공입니다. 짝짝짝~!
로그인이 되지 않았던 이슈도 해결되서 로그인이 성공한 후 마이페이지로 이동
이번 프로젝트를 진행하며, 컨테이너 기술과 MariaDB를 사용하여 로컬 데이터베이스를 Docker 컨테이너로 복원하는 과정에서 많은 것을 배웠습니다.
처음에는 환경 변수 설정과 Docker 명령어 사용에 어려움을 겪었지만, 문제를 하나씩 해결해가며 Docker와 MariaDB에 대한 이해도가 어느 정도 생긴거 같아 뿌듯합니다.
하지만 windows 운영체제에서의 Docker 작업은 매우 까다롭고 힘든거 같습니다.
추후 비슷한 오류를 겪는 분들께 도움이 됬으면 좋겠습니다. 감사합니다.