docker

docker로 postgres 구축하기 w. official image

aeongsseu 2024. 3. 14. 17:47

FROM postgres:16
LABEL authors="humanlearning"

ENV POSTGRES_PASSWORD="1234" \ # 필수 환경변수라 run할때마다 붙혀주기 귀찮아 Dockerfile에 일단 포함시켜놓았다
    POSTGRES_USER="postgres" \
    POSTGRES_DB="postgres"

WORKDIR /usr/src/app

#COPY create_dw_table.sql create_dw_table.sql

RUN apt-get update -y && \
    apt-get install vim sudo procps -y

USER postgres

RUN pg_createcluster 16 main &&\
    /etc/init.d/postgresql start &&\
    psql -U postgres -d postgres -f create_dw_table.sql &&\
    sed -i 's|local   all             all                                     peer|local\tall\t\tall\t\t\t\t\ttrust|' /etc/postgresql/16/main/pg_hba.conf &&\
    echo 'host\tall\t\tall\t\t0.0.0.0/0\t\ttrust' >> /etc/postgresql/16/main/pg_hba.conf

USER root

EXPOSE 5432

프로젝트 중에 DW 구축하는 것을 자동화하기 위해 dockerfile을 어떻게 작성했는지
또 그 과정에서 발생한 문제들을 트러블슈팅한 경험에 대해 이야기합니다.

 

데이터 파이프라인을 구축하는 프로젝트를 하던 중에 

미래에 면접관이 해당 프로젝트를 테스트해볼 것을 고려해 DW를 띄우는 것을 자동화하기로 했다.

DW를 bigquery나 redshift를 쓰면 다르겠지만 필자의 경우 postgresql을 사용했기에 dockerfile을 통해 DW구축을 자동화하기로 했다.

 

먼저 구글링 하던 중에 dockerfile만으로 postgresql세팅까지 다 자동화할 수 있다는 걸 확인하고 작업에 본격적으로 들어갔다.

근데 해당 글에서는 ubuntu를 base image로 사용해 그 위에 postgresql을 설치하는 것부터 시작했다.

postgresql official image가 있는 것을 알고 있는 필자는 의아해하고 필자는 그냥 official image를 사용해야겠다 생각했다.

(이 부분은 후에 트러블슈팅 이야기에서 회자됩니다.)

 

먼저 당연히 from을 통해 postgres 이미지를 가져왔다.

FROM postgres:16

그리고 이미지가 어떻게 구성돼 있고 어떻게 세팅해나가야 할지 알아보기 위해 아래 명령어를 치고 접속했다.

docker run -it postgres dwtest /bin/bash

그리고 psql을 통해 postgres에 접속하려 하니 서버가 꺼져있다고 에러메세지가 출력이 된다.

이에 아래 명령어를 통해 서버를 켜보려 하니 postgresql cluster조차 생성돼있지 않다고 뜬다!

service postgresql start

 

뭔 놈의 공식이미지가 본인들 서비스 서버에 클러스터마저 생성이 안 돼있냐 싶었지만 일단 클러스터 생성부터 해나가자고 생각했다.

뭐 물론 그리 어렵진 않고 간단히 아래 명령어를 통해 클러스터부터 생성했다.

pg_createcluster 16 main

 

이에 중간과정 dockerfile은 아래와 같았다.

FROM postgres:16
LABEL authors="humanlearning"

RUN apt-get update -y && \
    apt-get install vim sudo procps -y # 필수는 아니지만 접속해서 테스트할때 다시 깔기 귀찮아서

USER postgres

RUN pg_createcluster 16 main &&\
    /etc/init.d/postgresql start

USER root

EXPOSE 5432

 

여기에 이제 필요한 세팅들을 하기 위해 sql파일을 추가하고 conf파일을 조금 손봤다.

WORKDIR /usr/src/app
...
COPY create_dw_table.sql create_dw_table.sql
...
RUN psql -U postgres -d postgres -f create_dw_table.sql &&\
    sed -i 's|local   all             all                                     peer|local\tall\t\tall\t\t\t\t\ttrust|' /etc/postgresql/16/main/pg_hba.conf &&\
    echo 'host\tall\t\tall\t\t0.0.0.0/0\t\ttrust' >> /etc/postgresql/16/main/pg_hba.conf

hba부분은 보면 모든 ipv4에 대해 전부 trust 즉, 허용하기에 실제 운영에선 절대 저러면 안 되지만 일단 내 로컬에서만 돌릴 것으로 생각하고 작업했기에 저렇게 작성했다.(tmi로 hba은 host based authentication의 약어라 한다)

 

이에 다시 중간 dockerfile을 확인하면

FROM postgres:16
LABEL authors="humanlearning"

ENV POSTGRES_PASSWORD="1234" \ # 필수 환경변수라 run할때마다 붙혀주기 귀찮아 일단 dockerfile에 포함시켜놓았다
    POSTGRES_USER="postgres" \
    POSTGRES_DB="postgres"

WORKDIR /usr/src/app

COPY create_dw_table.sql create_dw_table.sql

RUN apt-get update -y && \
    apt-get install vim sudo procps -y

USER postgres

RUN pg_createcluster 16 main &&\
    /etc/init.d/postgresql start &&\
    psql -U postgres -d postgres -f create_dw_table.sql &&\
    sed -i 's|local   all             all                                     peer|local\tall\t\tall\t\t\t\t\ttrust|' /etc/postgresql/16/main/pg_hba.conf &&\
    echo 'host\tall\t\tall\t\t0.0.0.0/0\t\ttrust' >> /etc/postgresql/16/main/pg_hba.conf

USER root

EXPOSE 5432

 

이에 빌드 후 같은 명령어로 run과 동시에 접속해 보니 클러스터는 생성돼 있는데 서버가 꺼져있었다.

하지만 수동으로 서버를 켜보면 실행시킨 query(create_dw_table.sql)은 정상적으로 적용이 돼 있었다.

 

일단 서버가 꺼지는 문제를 해결하기 위해 /var/log에 있는 postgres서버 로그를 확인해 봤다

root@9381cc7f1add:/usr/src/app# cat /var/log/postgresql/postgresql-14-main.log
2024-03-12 07:45:54.333 UTC [56] LOG: starting PostgreSQL 14.1 (Debian 14.1-1.pgdg110+1) on aarch64-unknown-linux-gnu, compiled by gcc (Debian 10.2.1-6) 10.2.1 20210110, 64-bit
2024-03-12 07:45:54.333 UTC [56] LOG: listening on IPv4 address "0.0.0.0", port 5432
2024-03-12 07:45:54.333 UTC [56] LOG: listening on IPv6 address "::", port 5432
2024-03-12 07:45:54.335 UTC [56] LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
2024-03-12 07:45:54.338 UTC [57] LOG: database system was shut down at 2024-03-12 07:45:53 UTC 2024-03-12 07:45:54.343 UTC [56] LOG: database system is ready to accept connections

별 도움은 되지 않는다.

 

이에 대체 뭐가 문제일까 생각하며 단순히 공식이미지에서 제공하는 튜토리얼을 봐보기로 했다.

아래가 공식이미지 사이트에서 사용한 명령어

docker run --name some-postgres -e POSTGRES_PASSWORD=mysecretpassword -d postgres

귀찮게 detach모드로 사용하네 다시 exec로 접속해야 하게..라고 생각하며 명령어를 실행시켰다.

그리고 exec로 접속해 보니 서버가 처음부터 켜져 있는 것이다.

그리고 그 아래 설명을 봐보니

 

The default postgres user and database are created in the entrypoint with initdb.

 

설마 entrypoint인가?.......!

근데 당시엔 image는 기존이미지에 위에 추가적으로 쌓이는 방식이니까 base image의 entrypoint가 수정된 이미지에 영향을 줄 수 없을 거라 생각했다.

 

base image의 entrypoint는 위에 추가적으로 레이어가 쌓이면 RUN처럼 취급될 거라 생각한 것이다.

근데 그래도 테스트는 해봐야 하니 작성한 dockerfile에 마지막에 단순히 아래 구문을 추가하고 detach모드로 실행하고 exec로 접속해 봤다.

ENTRYPOINT ["echo", "설마"]

 

 

여느 때처럼 서버가 꺼져있었다.

그리고 ENTRYPOINT 없이 detach모드로 실행 후 접속해 보니..

서버가 켜져 있었다.

또한 공식 문서를 더 읽어보니 다음과 같은 말이 있었다.

If you would like to do additional initialization in an image derived from this one, add one or more *.sql*.sql.gz, or *.sh scripts under /docker-entrypoint-initdb.d

 

서버 세팅에 필요한 sql파일을 담을 수 있는 폴더가 애초에 따로 지정돼 있었다.

Entrypoint를 사용하지 않아도 되게끔(물론 난 psql -f를 통해 실행했지만)

 

아무래도 base image에 entrypoint가 있으면 후의 수정된 이미지에서 entrypoint를 추가하면 묻히나 보다.

이제야 위에서 처음 본 글이 생각났다.

해당 글의 필자가 실제로 겪어서 그랬는지는 모르겠지만 비슷한 이유로 우분투를 base image로 사용해 postgres를 까는 것부터 시작한 거 같다.

앞으로는 base image를 사용할 때 어떠한 제약사항들이 있는지 확인하고 작업해야겠다..

최종적인 dockerfile은 아래와 같다.

FROM postgres:16
LABEL authors="humanlearning"

ENV POSTGRES_PASSWORD="1234" \
    POSTGRES_USER="postgres" \
    POSTGRES_DB="postgres"


WORKDIR /usr/src/app

COPY create_dw_table.sql /docker-entrypoint-initdb.d

RUN apt-get update -y && \
    apt-get install vim sudo procps -y

USER postgres

RUN pg_createcluster 16 main &&\
    sed -i 's|local   all             all                                     peer|local\tall\t\tall\t\t\t\t\ttrust|' /etc/postgresql/16/main/pg_hba.conf &&\
    echo 'host\tall\t\tall\t\t0.0.0.0/0\t\ttrust' >> /etc/postgresql/16/main/pg_hba.conf

USER root

EXPOSE 5432

또한 추가적으로 환경변수에서 POSTGRES_USER와 POSTGRES_DB를 다른 값으로 바꾸면 어떤 이유에선지 모르겠지만
USER의 경우 root, postgres, 환경변수로 지정한 이름 전부 즉, 아무 유저가 생성돼있지 않아 서버에 접속할 수 없고
DB의 경우 폴더 안에 있는 sql파일이 정상적으로 작동하지 않는다.