https://www.wanted.co.kr/events/pre_challenge_be_25
원티드에서 진행하는 25차 프리온보딩 챌린지의 주제가 좋아보여 참가하였다. 사전 과제도 주어졌는데, 이를 배포하는 방식이 인상적이라 기록해두고자 한다.
1. docker-compose.yml
우선 해당 프로젝트에서는 데이터베이스를 필요로 한다. 데이터베이스를 어느 환경에서나 동일하게 실행할 수 있는 방법이 컨테이너를 사용하는 것이고 Docker 를 사용해서 처리할 수 있다.
services:
mysql:
image: mysql:8.0.33
ports:
- 13306:3306
volumes:
- ${DB_INIT_FILE}:/docker-entrypoint-initdb.d
command:
- '--character-set-server=utf8mb4'
- '--collation-server=utf8mb4_unicode_ci'
- '--lower_case_table_names=1'
environment:
MYSQL_ROOT_PASSWORD: wanted
MYSQL_DATABASE: wanted_preonboarding
위 파일로 MySQL 8.0 버전의 이미지를 가진 컨테이너가 실행된다. 실행 시 root 비밀번호와 데이터베이스를 초기화해주는 것을 볼 수 있다.
/docker-entrypoint-initdb.d
가 눈에 띈다. 해당 경로는 Docker 이미지에서 초기 데이터베이스를 설정할 때 사용하는 특별한 디렉토리다. 이 디렉토리 내에 위치한 SQL 스크립트는 MySQL 컨테이너가 처음 시작될 때 자동으로 실행된다.
조금만 더 살펴보자면 MySQL 이미지는 docker-entrypoint.sh
라는 기본 스크립트를 가지고 있다.
실제 docker 컨테이너 내부 파일을 보더라도 해당 스크립트가 존재하는 것을 확인할 수 있다.
위 경로를 찾아가 /usr/local/bin/docker-entrypoint.sh
파일을 열어보자
...
# there's no database, so it needs to be initialized
if [ -z "$DATABASE_ALREADY_EXISTS" ]; then
docker_verify_minimum_env
# check dir permissions to reduce likelihood of half-initialized database
ls /docker-entrypoint-initdb.d/ > /dev/null
docker_init_database_dir "$@"
mysql_note "Starting temporary server"
docker_temp_server_start "$@"
mysql_note "Temporary server started."
mysql_socket_fix
docker_setup_db
docker_process_init_files /docker-entrypoint-initdb.d/*
mysql_expire_root_user
mysql_note "Stopping temporary server"
docker_temp_server_stop
mysql_note "Temporary server stopped"
echo
mysql_note "MySQL init process done. Ready for start up."
echo
...
/docker-entrypoint-initdb.d
가 사용되는 부분만 발췌했다.
docker_process_init_files /docker-entrypoint-initdb.d/*
해당 명령어를 통해서 해당 디렉토리 내에 sql 파일들이 모두 실행되며 컨테이너 초기화가 완료되는 것을 볼 수 있다.
결국 다시 돌아오자면 DB_INIT_FILE
이라는 경로의 디렉토리가 컨테이너 안 디렉토리로 마운트 되어 해당 경로의 파일들이 컨테이너 내부로 이동해서 초기화 때 실행되는 것이다. 그렇기에 생성되는 모든 컨테이너들을 동일한 상태로 유지할 수 있다.
2. .env
DB_INIT_FILE
라는 변수는 어떻게 지정할 것인가? 간단한게 .env
파일을 사용하면 된다. 환경 변수를 설정하기 위한 텍스트 파일로 다양한 곳에서 사용되기에 익숙할 수 있다. 상대 경로도 지원하기에 아래와 같이 작성해주면 된다.
환경 변수 파일은 공유하지 않는 편이 좋으므로 따로 작성해줘야한다.
DB_INIT_FILE=./src/main/resources/initdb
3. application.yml
spring:
application:
name: "clone-one-port"
thymeleaf:
cache: false
check-template-location: true
prefix: classpath:/templates/
suffix: .html
---
spring:
config:
activate:
on-profile: dev
datasource:
url: jdbc:mysql://localhost:13306/wanted_preonboarding?serverTimezone=UTC&characterEncoding=UTF-8
username: wanted
password: backend
driver-class-name: com.mysql.cj.jdbc.Driver
# JPA 설정
jpa:
hibernate:
ddl-auto: create-drop # DB 초기화 전략 (none, create, create-drop, update, validate)
properties:
hibernate:
auto_quote_keyword: false
globally_quoted_identifiers: false
format_sql: true # 쿼리 로그 포맷 (정렬)
show_sql: true # 쿼리 로그 출력
흔히 볼 수 있는 application.yml 설정이다. 대부분의 프로젝트에서는 yml 파일 자체를 gitignore 로 설정해 올라가지 않지만 이렇게 미리 작성해놓으면 사용하기 굉장히 편하다. 민감한 정보들은 .env
파일을 통해서 변수화 처리할 수 있다.
여기서 의문인 점은 docker-compose.yml
의 root 비밀번호와 다르게 접근한다는 점이다. 실제 실행했을 때에도 DB 커넥션이 잘 생성되기에 의아했다.
4. initdb/create_schema.sql
CREATE DATABASE IF NOT EXISTS `wanted_preonboarding`;
USE wanted_preonboarding;
CREATE USER IF NOT EXISTS `wanted`@`localhost` IDENTIFIED BY 'backend';
CREATE USER `wanted`@`%` IDENTIFIED BY 'backend';
GRANT all privileges ON `wanted_preonboarding`.* TO `wanted`@`localhost`;
GRANT all privileges ON `wanted_preonboarding`.* TO `wanted`@`%`;
CREATE TABLE `purchase_order`
(
...
sql 스크립트를 보자마자 의문은 해결됐다. 처음 데이터베이스를 초기화할 때 해당 아이디, 비밀번호로 유저를 생성하고 권한까지 부여했다. 이후 테이블을 생성하는 초기화작업을 마쳐준다.
이러한 배포 구성을 통해서 동일한 환경 배포를 보장하는 것이 인상적이라 기록해두고자 한다. 실제로 Mac 노트북과 Window 데스크탑 환경을 동시에 사용 중이기에 이러한 환경 동기화에 불편함을 겪었었다. Docker 를 사용해서 환경을 세팅해볼 생각이 있었는데 좋은 레퍼런스를 찾을 수 있었다. 물론 배포 시 예민한 정보들은 잘 관리해야함에 유의하자.
'Programming > Coding' 카테고리의 다른 글
Clustered Index 를 활용한 Full Table Scan 없는 N 명 추첨 알고리즘 (3) | 2024.11.10 |
---|---|
[WebSocket] STOMP 테스트를 위한 블로그 사이트 (4) | 2024.10.28 |
우아콘 2022 발표 'API Gateway Pattern 에는 API Gateway 가 없다' (4) | 2024.09.08 |
[CI/CD] Github Actions 에서 AWS Credential 을 AccessKey 로?? (0) | 2024.08.23 |
[CI/CD] Docker, Github Action, AWS 를 통한 자동 배포! (4) | 2024.07.03 |