Docker 컨테이너에 Postgres 데이터베이스 구축 with SSL

Published Nov 27, 2024 | Updated Nov 29, 2024 | 0 comments

개요

Postgres 데이터베이스를 Docker 컨테이너로 구축하는 과정을 기록합니다.
SSL 적용 과정의 오류에 대한 해결 과정도 포함하고 있습니다.

컨테이너 폴더 및 인증서 생성

인증서 폴더(ca) 와 데이터 폴더(pgdata) 를 생성한 다음 인증서를 생성합니다.
폴더 구조는 다음과 같습니다.

폴더를 생성하는 스크립트 입니다.

kkomzi@KKOMZI_HPN54L:/volume1/docker$ mkdir postgres
kkomzi@KKOMZI_HPN54L:/volume1/docker$ cd postgres/
kkomzi@KKOMZI_HPN54L:/volume1/docker/postgres$ mkdir ca
kkomzi@KKOMZI_HPN54L:/volume1/docker/postgres$ mkdir pgdata

인증서를 생성하는 스크립트 입니다.

kkomzi@KKOMZI_HPN54L:/volume1/docker/postgres$ openssl req -new -text -passout pass:abcd -subj /CN=localhost -out ./ca/server.req -keyout ./ca/privkey.pem
Generating a RSA private key
........+++++
.....................+++++
writing new private key to './ca/privkey.pem'
-----
kkomzi@KKOMZI_HPN54L:/volume1/docker/postgres$ openssl rsa -in ./ca/privkey.pem -passin pass:abcd -out ./ca/server.key
writing RSA key
kkomzi@KKOMZI_HPN54L:/volume1/docker/postgres$ openssl req -x509 -in ./ca/server.req -text -key ./ca/server.key -out ./ca/server.crt

docker-compose.yaml 파일 작성

PGDATA 환경 변수에 데이터 폴더의 경로를 지정하고 호스트 폴더와 마운트 시켜 줍니다.
인증서 경로와 인증서를 적용하기 위한 command 도 포함되어 있습니다.

services:
  postgres:
    image: postgres:latest
    container_name: postgres
    restart: always
    command: -c ssl=on -c ssl_cert_file=/var/lib/postgresql/server.crt -c ssl_key_file=/var/lib/postgresql/server.key
    environment:
      PGDATA: /var/lib/postgresql/data/pgdata
      POSTGRES_DB: kkomzi
      POSTGRES_PASSWORD: {{비밀번호}}
      POSTGRES_USER: kkomzi
    volumes:
      - ./ca/server.crt:/var/lib/postgresql/server.crt
      - ./ca/server.key:/var/lib/postgresql/server.key
      - ./pgdata:/var/lib/postgresql/data/pgdata
    ports:
      - 5432:5432

컨테이너 실행

컨테이너를 실행합니다.

kkomzi@KKOMZI_HPN54L:/volume1/docker/postgres$ docker-compose up -d
Creating network "postgres_default" with the default driver
Pulling postgres (postgres:latest)...
latest: Pulling from library/postgres
2d429b9e73a6: Already exists
3234e936b543: Pull complete
b5b68d2b7dfa: Pull complete
2bc4b686b410: Pull complete
0e741c16b01d: Pull complete
febd2e801cbc: Pull complete
abad6e2f102b: Pull complete
fc0ed0630c16: Pull complete
15ea73ccc174: Pull complete
bc241f8dfdda: Pull complete
e6b9724cd240: Pull complete
87f78d636266: Pull complete
4bd7a2dad750: Pull complete
4c07baf06858: Pull complete
Digest: sha256:994cc3113ce004ae73df11f0dbc5088cbe6bb0da1691dd7e6f55474202a4f211
Status: Downloaded newer image for postgres:latest

오류 해결 과정

컨테이너 생성 후 데이터베이스에 연결해서 테스트 하려고 했더니 접속이 되지 않아 컨테이너 로그를 확인해 봅니다.

오류 – 소유자

로그를 확인해 보면 server.key 파일 관련해서 오류가 발생한 것을 확인할 수 있습니다.

kkomzi@KKOMZI_HPN54L:/volume1/docker/postgres$ docker logs postgres -f
The files belonging to this database system will be owned by user "postgres".
This user must also own the server process.

The database cluster will be initialized with locale "en_US.utf8".
The default database encoding has accordingly been set to "UTF8".
The default text search configuration will be set to "english".

Data page checksums are disabled.

fixing permissions on existing directory /var/lib/postgresql/data/pgdata ... ok
creating subdirectories ... ok
selecting dynamic shared memory implementation ... posix
selecting default "max_connections" ... 100
selecting default "shared_buffers" ... 128MB
selecting default time zone ... Etc/UTC
creating configuration files ... ok
running bootstrap script ... ok
performing post-bootstrap initialization ... ok
syncing data to disk ... ok


Success. You can now start the database server using:
initdb: warning: enabling "trust" authentication for local connections
initdb: hint: You can change this by editing pg_hba.conf or using the option -A, or --auth-local and --auth-host, the next time you run initdb.

    pg_ctl -D /var/lib/postgresql/data/pgdata -l logfile start

waiting for server to start....2024-11-27 09:39:59.800 UTC [47] FATAL:  private key file "/var/lib/postgresql/server.key" must be owned by the database user or root
2024-11-27 09:39:59.800 UTC [47] LOG:  database system is shut down
 stopped waiting
pg_ctl: could not start server
Examine the log output.

PostgreSQL Database directory appears to contain a database; Skipping initialization

2024-11-27 09:40:03.275 UTC [1] FATAL:  private key file "/var/lib/postgresql/server.key" must be owned by the database user or root
2024-11-27 09:40:03.275 UTC [1] LOG:  database system is shut down

PostgreSQL Database directory appears to contain a database; Skipping initialization

2024-11-27 09:40:06.567 UTC [1] FATAL:  private key file "/var/lib/postgresql/server.key" must be owned by the database user or root
2024-11-27 09:40:06.568 UTC [1] LOG:  database system is shut down

PostgreSQL Database directory appears to contain a database; Skipping initialization

소유자 id 확인

위 스크립트의 11 번째 줄을 보면 pgdata 폴더의 퍼미션을 수정하는 로그를 확인할 수 있습니다.
컨테이너가 생성되는 과정에서 데이터 폴더의 소유자가
컨테이너의 postgres 계정의 id 인 999 로 수정되어 있습니다.

kkomzi@KKOMZI_HPN54L:/volume1/docker/postgres$ ls -al
total 4
drwxrwxrwx+ 1 kkomzi users  54 Nov 27 14:35 .
drwxrwxrwx+ 1 root   root  564 Nov 27 13:19 ..
drwxrwxrwx+ 1 kkomzi users  82 Nov 27 13:37 ca
-rwxrwxrwx+ 1 kkomzi users 892 Nov 27 17:48 docker-compose.yaml
drwx------  1    999 users 454 Nov 27 18:46 pgdata
kkomzi@KKOMZI_HPN54L:/volume1/docker/postgres$

소유자 변경

sudo 로 전환해서 파일 소유자를 다음과 같이 999 로 수정합니다.

kkomzi@KKOMZI_HPN54L:/volume1/docker/postgres$ sudo -i
root@KKOMZI_HPN54L:~# chown 999 /volume1/docker/postgres/ca/server.key
root@KKOMZI_HPN54L:~# exit
logout
kkomzi@KKOMZI_HPN54L:/volume1/docker/postgres$

오류 – 퍼미션

다시 로그를 확인해 보면 퍼미션도 수정하라고 합니다.

kkomzi@KKOMZI_HPN54L:/volume1/docker/postgres$ docker logs postgres -f
The files belonging to this database system will be owned by user "postgres".
This user must also own the server process.

The database cluster will be initialized with locale "en_US.utf8".
The default database encoding has accordingly been set to "UTF8".
The default text search configuration will be set to "english".

~~~~~~ 생략

2024-11-27 09:50:28.729 UTC [1] FATAL:  private key file "/var/lib/postgresql/server.key" has group or world access
2024-11-27 09:50:28.729 UTC [1] DETAIL:  File must have permissions u=rw (0600) or less if owned by the database user, or permissions u=rw,g=r (0640) or less if owned by root.
2024-11-27 09:50:28.729 UTC [1] LOG:  database system is shut down
kkomzi@KKOMZI_HPN54L:/volume1/docker/postgres$

퍼미션 수정

sudo 로 전환해서 파일 퍼미션를 다음과 같이 600 으로 수정합니다.

kkomzi@KKOMZI_HPN54L:/volume1/docker/postgres$ sudo -i
root@KKOMZI_HPN54L:~# chmod 600 /volume1/docker/postgres/ca/server.key
root@KKOMZI_HPN54L:~# exit
logout
kkomzi@KKOMZI_HPN54L:/volume1/docker/postgres$

다시 로그를 확인해 보면 에러 없이 정상적으로 실행이 된 것을 확인할 수 있습니다.

kkomzi@KKOMZI_HPN54L:/volume1/docker/postgres$ docker logs postgres -f

~~~생략

2024-11-27 09:54:39.042 UTC [1] LOG:  starting PostgreSQL 17.2 (Debian 17.2-1.pgdg120+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 12.2.0-14) 12.2.0, 64-bit
2024-11-27 09:54:39.058 UTC [1] LOG:  listening on IPv4 address "0.0.0.0", port 5432
2024-11-27 09:54:39.058 UTC [1] LOG:  listening on IPv6 address "::", port 5432
2024-11-27 09:54:39.115 UTC [1] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
2024-11-27 09:54:39.167 UTC [30] LOG:  database system was shut down at 2024-11-27 09:39:58 UTC
2024-11-27 09:54:39.219 UTC [1] LOG:  database system is ready to accept connections

오류 – 데이터베이스가 존재하지 않습니다.

하지만 직접 접속해 보면 다음과 같이 데이터베이스가 생성되지 않았다고 합니다.

kkomzi@KKOMZI_HPN54L:/volume1/docker/postgres$ docker exec -it postgres /bin/bash
root@37119dca925d:/# psql -U kkomzi
psql: error: connection to server on socket "/var/run/postgresql/.s.PGSQL.5432" failed: FATAL:  database "kkomzi" does not exist

데이터 폴더 하위 다시 생성

아직 어떤 이유로 발생하는 문제인지는 모르겠지만 일단 다음과 같은 방법으로 해결하였습니다.
컨테이너를 삭제한 다음 pgdata 폴더 하위의 모든 파일을 삭제하고 다시 컨테이너를 실행하면 제대로 동작하는 것을 확인할 수 있었습니다.
하위 폴더 및 파일 삭제는 WinSCP 로 접속된 상황이라 UI 에서 삭제하였습니다.

kkomzi@KKOMZI_HPN54L:/volume1/docker/postgres$ docker-compose down
Stopping postgres ... done
Removing postgres ... done
Removing network postgres_default
kkomzi@KKOMZI_HPN54L:/volume1/docker/postgres$ docker-compose up -d
Creating network "postgres_default" with the default driver
Creating postgres ... done

접속 테스트

직접 접속해서 로그인 한 다음 테스트 합니다.

kkomzi@KKOMZI_HPN54L:/volume1/docker/postgres$ docker exec -it postgres /bin/bash
root@37e12de71f0f:/# psql -U kkomzi
psql (17.2 (Debian 17.2-1.pgdg120+1))
Type "help" for help.

kkomzi-# \du
                             List of roles
 Role name |                         Attributes
-----------+------------------------------------------------------------
 kkomzi    | Superuser, Create role, Create DB, Replication, Bypass RLS

kkomzi-# \l
                                                 List of databases
   Name    | Owner  | Encoding | Locale Provider |  Collate   |   Ctype    | Locale | ICU Rules | Access privileges
-----------+--------+----------+-----------------+------------+------------+--------+-----------+-------------------
 kkomzi    | kkomzi | UTF8     | libc            | en_US.utf8 | en_US.utf8 |        |           |
 postgres  | kkomzi | UTF8     | libc            | en_US.utf8 | en_US.utf8 |        |           |
 template0 | kkomzi | UTF8     | libc            | en_US.utf8 | en_US.utf8 |        |           | =c/kkomzi        +
           |        |          |                 |            |            |        |           | kkomzi=CTc/kkomzi
 template1 | kkomzi | UTF8     | libc            | en_US.utf8 | en_US.utf8 |        |           | =c/kkomzi        +
           |        |          |                 |            |            |        |           | kkomzi=CTc/kkomzi
(4 rows)

kkomzi-#

TAG INFORMATION

Learn more on this topic

Related Blog Posts

Join in the conversation

Leave a Comment

0 Comments

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

무료 온라인 전광판

전광판

텍스트를 입력하고 텍스트 효과 및 배경효과 를 변경해서 전체화면으로 표시할 수 있는 전광판 용도로 사용하실 수 있습니다. 각종 스포츠 및 공연 관람시 응원 용도로 사용이 가능합니다.

Carousel

여러개의 슬라이드를 추가하여 프레젠테이션 및 이미지 슬라이드 용도로 사용하실 수 있습니다. 브라우저가 포함된 IT 기기로 큰 모니터에 연결하여 매장 내 공지사항 및 메뉴소개를 이미지로 표시할 수 있습니다.

Pin It on Pinterest

Shares
Share This

Share This

Share this post with your friends!

Shares