postgresql를 docker로 올릴 때, 데이터베이스들을 초기화 할 수 있습니다. 이 방법을 알아보겠습니다.

 


 그 전에 volumes에 대해 간단히 알아봅시다. 먼저, 폴더 구조는 아래와 같습니다.

 

 docker-compose.yml 파일이 있고, ddl 폴더 밑에 schema.sql이 있습니다. 이제 밑에 있는 compose 파일을 보겠습니다.

 

 

 11 ~ 15번째 줄이 중요합니다. 11 ~ 13번째 줄부터 해석해 봅시다. 문서를 보면 12 ~ 13번째 줄은 VOLUME:CONTAINER_PATH임을 알 수 있어요. CONTAINER_PATH는 VOLUME이 마운트 되는 경로를 의미합니다. 실제로 처음 postgres가 초기화 되고 볼륨이 만들어 질 때 초기화 되게 하기 위해 13번째 줄을 넣었는데요. /docker-entrypoint-initdb.d 디렉토리가 중요합니다. 왜 이렇게 했는지는, 밑에 후술하겠습니다.

 

 14 ~ 15번째 줄은 pgdata 라는 volume을 없다면 생성합니다. 이것을 12번째 줄에서 쓰고 있어요.

 

 ddl 디렉토리 밑에 있는 schema.sql입니다. volumes이 빈 상태에서 초기화 할 때, 실행할 sql 문들이 있는데요. schema.sql은 그 중 하나입니다. user와 book, borrow 테이블을 만듭니다. docker compose up -d 명령을 수행해 보겠습니다.

 

 

  그러면, volumes에 pg_docker_pgdata가 생성되었음을 볼 수 있어요.

 

 

 이 드라이브에 있는 내용들을 보면, pg_hba.conf, pg_ident.conf가 있음을 볼 수 있어요. 이들은 /var/lib/postgresql/data 폴더 밑에 있는 파일들입니다. 이 상황을 정리해 보겠습니다.

 

 장치 pg_docker_pgdata가 컨테이너 내부의 /var/lib/postgresql/data에 연결된다. 뭔가 어려워 보이는데요. 윈도우에서 e:에 들어가면, usb에 있는 파일에 접근할 수 있다고 합시다. 이건 조금 익숙하실 거에요. 마찬가지로 생각해 봅시다. 우리에게 익숙한 e: 대신에 /var/lib/postgresql/data에 들어가면, pgdata에 있는 파일들에 접근할 수 있다고 생각하면 편하겠습니다.

 


 이제 13번째 줄을 보겠습니다. ./ddl:/docker-entrypoint-initdb.d 가 무엇을 의미할까요? 똑같습니다. 컨테이너 내부에 있는 경로가 있을 거에요. /docker-entrypoint-initdb.d에 들어가면, ./ddl에 접근할 수 있다. 그런데, 여기서 ./ddl은 무엇인가요?

 

 

 schema.sql만 있어요. 정말 /docker-entrypoint-initdb.d 디렉토리 안에 들어가면 해당 파일을 볼 수 있을까요?

 

 볼 수 있어요. 만약에 schema2.sql을 추가하면 어떻게 될까요?

 

 컨테이너 안에서 touch schema2.sql을 입력해 보겠습니다.

 

 

 그러면 제 작업 디렉토리의 ddl 폴더 안에 schema2.sql이 추가됩니다. 왜? 컨테이너와 연결된 장치였기 때문입니다. 그러면 왜 제 host에 있는 작업 디렉토리 밑에 있는 ddl 폴더를 volume으로 삼아서 /docker-entrypoint-initdb.d와 연결시켰을까요? 이 폴더 밑에 있는 sql, sh 파일들을 초기화 될 때 실행하기 때문입니다. postgresql docker 공식 문서의 Initialization scripts에 언급된 부분을 보면 알 수 있습니다.

 

 

 컨테이너 안에 들어가서, postgres에 접속해 보겠습니다.

 

 테스트를 해 보면, sql문 안에 있는 테이블 생성문들이 잘 작동했음을 볼 수 있습니다.

 


 이제 조심해야 할 점을 알아봅시다. schema.sql에 token 테이블을 추가하는 명령어를 추가한 다음에 다시 compose up 명령어를 입력해 보겠습니다.

 

 그러면, 아래와 같은 로그를 볼 수 있습니다. skipping initialization. 왜 그럴까요? 비어 있는 data 디렉토리로 컨테이너를 시작할 때에만 초기화가 되기 때문입니다. 이미 테이블이 생성된 상황에서는 데이터 디렉터리가 비어있지 않았습니다. 따라서, 초기화가 실행되지 않았습니다.

 

 

 당연하게도, 초기화가 되지 않아 token 테이블이 없을 테니, token을 조회하려고 하면 오류가 떨어집니다.