LC_COLLATE를 ko_KR로 설정할 수 있는 postgresql 도커이미지 만들기

Created
May 21, 2021
Created by
Tags
Docker
Postgresql
Property
 
postgresql 도커이미지를 가지고 LC_COLLATE가 한국어(ko_KR)로 설정된 DB를 만들려고 한다. 아래와 같이 도커헙(dockerhub)에 있는 mdillon/postgis 이미지 위에 DB를 만드는 Dockerfile을 작성했다.
FROM mdillon/postgis RUN su postgres -c "createdb -U postgres ko-db --encoding='utf-8' --lc-collate=ko_KR.UTF-8 --template=template0" EXPOSE 5555 ENTRYPOINT ["psql", "-U", "postgres"]
 
Dockerfile을 작성하고 빌드한 뒤 컨테이너를 생성하려고 하니 아래와 같은 에러가 발생했다.
createdb: database creation failed: ERROR: invalid locale name: "ko_KR.UTF-8
 
mdillon/postgis 이미지에서 사용하는 alpine 운영체제의 로케일(locale) 리스트에 ko_KR이 설정되지 않은 게 원인이었다. (Unix 운영체제가 가지고 있는 로케일들을 보려면 $ locale -a 명령어를 사용한다.)
root@7875ffd0ce24:/# locale -a C C.UTF-8 en_US.utf8 POSIX
 
따라서 mdillon/postgis 이미지를 사용하는 대신에 debian 운영체제에 한국어 로케일을 설정하고 postgresql, postgis를 설치한 뒤 pg_ctl 명령어로 postgresql 서버를 구동하는 Dockerfile을 작성하려고 한다.
 
💡
로케일을 등록한 뒤에는 postgersql 서버를 재시작해야 등록한 로케일로 데이터베이스를 만들 수 있다. 하지만 mdillon/postgis 이미지에는 postgresql 서버를 시작하는 레이어가 이미 들어가있다. postgresql 서버를 재시작하는 레이어를 추가하려면 이전 레이어에서 무엇을 어떻게 하는지를 (postgresql 관련 configuration을) 찾아내고 사용했던 쉘 스크립트를 컨테이너에서 뒤져야 하는데.. 그것보다는 debian 이미지 위에서 한국어 로케일을 등록하고 postgresql, postgis를 설치하는 게 덜 힘들고 깔끔해보였다.
 
 

1. debian 운영체제에 한국어(ko_KR) 로케일 설정하는 레이어 추가하기

 
debian 운영체제에 한국어 로케일을 설정해보자. (기본 이미지는 debian:buster-slim 를 사용한다. buster 외에 strech, jessie 등 여러 버전이 있는데 버전의 차이는 여기서 확인 할 수 있다.)
 
먼저 locales 라는 패키지를 설치한다.
$ apt-get update && apt-get -y install locales
 
/etc/locale.gen 파일 내용을 보면 아래와 같이 되어 있다.
root@bbe859701ab6:/# cat /etc/locale.gen # This file lists locales that you wish to have built. You can find a list # of valid supported locales at /usr/share/i18n/SUPPORTED, and you can add # user defined locales to /usr/local/share/i18n/SUPPORTED. If you change # this file, you need to rerun locale-gen. # aa_DJ ISO-8859-1 # aa_DJ.UTF-8 UTF-8 # aa_ER UTF-8 # aa_ER@saaho UTF-8 ... # ko_KR.EUC-KR EUC-KR # ko_KR.UTF-8 UTF-8 ...
 
sed 명령어로 /etc/locale.gen 파일에 주석 처리된 한국어를 수정해준다.
💡
$ sed -i "s/<A>/<B>/" <file>file에 있는 AB로 바꾸겠다.
$ sed -i 's/# ko_KR.UTF-8 UTF-8/ko_KR.UTF-8 UTF-8/' /etc/locale.gen
 
dpkg-reconfigure 를 사용하여 설치된 locales 패키지를 재설정한다. 위에서 ko_KR.UTF-8주석을 풀었기 때문에 한국어를 로케일로 설정할 수 있다.
$ dpkg-reconfigure --frontend=noninteractive locales
--frontend=noninteractive 옵션을 사용하지 않으면 아래와 같이 프롬프트에서 입력을 받아 설정한다.
notion image
 
위 과정을 하나의 레이어로 작성하면 아래와 같다.
FROM debian:buster-slim RUN apt-get update && \ apt-get -y install locales && \ sed -i 's/# ko_KR.UTF-8 UTF-8/ko_KR.UTF-8 UTF-8/' /etc/locale.gen && \ dpkg-reconfigure --frontend=noninteractive locales
 
 

2. postgresql, postgis 셋업하는 레이어 추가하기

 
postgresql, postgis 를 셋업하려면 아래 단계들을 거쳐야 한다.
 
  1. postgresql, postgis 설치
  1. 환경변수 정의
  1. postgres 유저에게 권한 데이터 디렉토리 및 로그파일에 접근할 수 있는 권한 부여
  1. initdb 명령어로 postgres 클러스터 만들기
 
위 네가지를 수행하는 레이어는 아래와 같다.
쉘에서 psql 명령어를 사용할 수 있도록 PATH 환경변수에 바이너리 파일 경로를 추가하고 PGDATA 환경변수에 데이터가 저장될 디렉토리 위치를 정의했다.
# 1. postgresql, postgis 설치 RUN apt-get update && \ apt-get -y install gnupg lsb-release wget && \ sed -i 's/# ko_KR.UTF-8 UTF-8/ko_KR.UTF-8 UTF-8/' /etc/locale.gen && \ dpkg-reconfigure --frontend=noninteractive locales && \ sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list' && \ wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - && \ apt-get -y install postgresql-11 postgis # 2. 환경변수 정의 ENV PATH=/usr/lib/postgresql/11/bin:$PATH \ PGDATA=/pgdata # 3. postgres 유저에게 데이터 디렉토리 및 로그파일에 접근할 수 있는 권한 부여 RUN mkdir $PGDATA && \ chown postgres /pgdata && \ touch /pglog && \ chown postgres /pglog # 4. initdb 명령어로 클러스터 만들기 RUN su postgres -c "initdb -D /pgdata"
 
도커 이미지를 빌드할 때는 root 유저에 로그인해서 각 명령어를 실행하는데, postgresql 관련 프로세스를 생성하려면 권한이 제한된 유저에 로그인해야 한다. (그래서 $ su postgres -c 와 같이 postgres 유저에 로그인해서 명령어를 실행하도록 했다.) 그렇지 않으면 빌드 과정에서 에러가 발생한다.
initdb: cannot be run as root Please log in (using, e.g., "su") as the (unprivileged) user that will own the server process.
 

3. postgresql 서버 구동하고 한국어 기준으로 정렬하는 DB 만들기

 
이미지를 컨테이너로 만드는 과정은 아주 간략히 말하자면 아래와 같다.
 
  • 이미지를 빌드한다.
  • 빌드한 이미지로 컨테이너를 생성한다. (상태는 created 이며 접속은 못하는 상태)
  • 생성한 컨테이너를 구동시킨다. (상태는 running이며 접속할 수 있는 상태)
 
ENTRYPOINT에는 생성된 컨테이너를 구동시킬 때 실행 할 프로세스(명령어)를 정의하는데, entrypoint.sh 라는 쉘 스크립트를 실행하도록 할 것이다. 쉘 스크립트는 호스트에서 복사한다.
#!/bin/bash # postgresql 서버 시작 su postgres -c "pg_ctl start -l /pglog -D /pgdata" # 한국어를 기준으로 정렬하는 korean-db 생성 su postgres -c "createdb -U postgres korean-db --encoding='utf-8' --lc-collate=ko_KR.UTF-8 --template=template0" # postgresql 접속 psql -U postgres
 
포트번호 5555로 컨테이너에 접속하도록 하는 것 까지 작성하면 아래와 같은 레이어들이 Dockerfile에 추가된다.
COPY ./entrypoint.sh /entrypoint.sh RUN chmod +x /entrypoint.sh EXPOSE 5555 ENTRYPOINT ["./entrypoint.sh"]
 
이제 ko-postgres 라는 이름으로 이미지를 만들고 컨테이너를 구동시켜보자. (Dockerfile을 작성하면서 이미 여러번 빌드를 했었기 때문에 캐시된 레이어들이 있다.)
$ docker build -t ko-postgres . Sending build context to Docker daemon 197.6kB Step 1/9 : FROM debian:buster-slim ---> 80b9e7aadac5 Step 2/9 : RUN apt-get update && apt-get -y install locales gnupg lsb-release wget && sed -i 's/# ko_KR.UTF-8 UTF-8/ko_KR.UTF-8 UTF-8/' /etc/locale.gen && dpkg-reconfigure --frontend=noninteractive locales && sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list' && wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - && apt-get -y install postgresql-11 postgis ---> Using cache ---> 8523944f5a8a Step 3/9 : ENV PATH=/usr/lib/postgresql/11/bin:$PATH PGDATA=/pgdata ---> Using cache ---> 5ccf9f6a5726 Step 4/9 : RUN mkdir $PGDATA && chown postgres /pgdata && touch /pglog && chown postgres /pglog ---> Using cache ---> 02d1e2537f03 Step 5/9 : RUN su postgres -c "initdb -D /pgdata" ---> Using cache ---> 702ef945624c Step 6/9 : COPY ./entrypoint.sh /entrypoint.sh ---> 3c16370df9a8 Step 7/9 : RUN chmod +x /entrypoint.sh ---> Running in 2f7a168885b5 Removing intermediate container 2f7a168885b5 ---> 7ae74e37169c Step 8/9 : EXPOSE 5555 ---> Running in bd0fb89e671d Removing intermediate container bd0fb89e671d ---> 4b2b73937ab4 Step 9/9 : ENTRYPOINT ["./entrypoint.sh"] ---> Running in 468eaf1a0c20 Removing intermediate container 468eaf1a0c20 ---> 6aa090bb3892 Successfully built 6aa090bb3892 Successfully tagged ko-postgres:latest
 
entrypoint.sh에 postgresql 서버에 접속하는 명령어가 있기 때문에 곧바로 접속이 되고 정렬기준이 ko_KR.UTF-8 으로 설정된 것을 확인할 수 있다.
$ docker run -it ko-postgres waiting for server to start.... done server started psql (11.12 (Debian 11.12-0+deb10u1)) Type "help" for help. postgres=# \c korean-db You are now connected to database "korean-db" as user "postgres". korean-db=# show LC_COLLATE; lc_collate ------------- ko_KR.UTF-8 (1 row)
 
Dockerfile 최종 완성본과 쉘 스크립트는 여기서 확인할 수 있다.
 
 
 
참고 및 출처