1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

PostgreSQLのオフィシャルDockerイメージをSSL化したい

Last updated at Posted at 2023-04-15

What's?

DockerHubにあるPostgreSQLのオフィシャルのDockerイメージですが、こちらはSSLが有効になっていません。

DockerHub / postgres

これをなんとかしたいな、ということで。

環境

今回の環境は、こちら。

$ docker version
Client: Docker Engine - Community
 Version:           23.0.3
 API version:       1.42
 Go version:        go1.19.7
 Git commit:        3e7cbfd
 Built:             Tue Apr  4 22:05:48 2023
 OS/Arch:           linux/amd64
 Context:           default

Server: Docker Engine - Community
 Engine:
  Version:          23.0.3
  API version:      1.42 (minimum version 1.12)
  Go version:       go1.19.7
  Git commit:       59118bf
  Built:            Tue Apr  4 22:05:48 2023
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.6.20
  GitCommit:        2806fc1057397dbaeefbea0e4e17bddfbd388f38
 runc:
  Version:          1.1.5
  GitCommit:        v1.1.5-0-gf19387a
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0

Docker Composeも。

$ docker compose version
Docker Compose version v2.17.2

PostgreSQLのイメージは、15.2のものを使うことにします。

SSL証明書を作成する

SSL接続に関するPostgreSQLのドキュメントはこちら。

PostgreSQLのイメージをSSL化するにあたり、SSL証明書を作成することになるわけですが、コマンドは先に載せておきましょう。

$ openssl req -new -x509 -days 365 -nodes -text -out /path/to/server.crt -keyout /path/to/server.key -subj '/CN=example.com'

/path/toの部分は、利用する箇所に応じて変更して使うことにします。

SubjectはCommmon Nameだけ指定することにしました。

Dockerfileを書く

身も蓋もないですが、この方法が1番まとまりがいい気がします…。

Dockerfile
FROM postgres:15.2-bullseye

RUN openssl req -new -x509 -days 365 -nodes -text -out /etc/postgresql/server.crt -keyout /etc/postgresql/server.key -subj '/CN=example.com' \
    && chown postgres:postgres /etc/postgresql/server.key \
    && chmod 600 /etc/postgresql/server.key

RUN chown postgres:postgres /etc/postgresql/server.key \
    && chmod 600 /etc/postgresql/server.key

CMD ["-c", "ssl=on", "-c", "ssl_cert_file=/etc/postgresql/server.crt", "-c", "ssl_key_file=/etc/postgresql/server.key"]

ビルド。

$ docker image build -t charon/postgres:15.2-bullseye .

確認。

$ docker container run -it --rm --name postgres \
   -e POSTGRES_PASSWORD=password \
   -e POSTGRES_USER=myuser \
   -e POSTGRES_DB=example \
   charon/postgres:15.2-bullseye
$ docker container exec -it postgres psql -U myuser -h localhost example
psql (15.2 (Debian 15.2-1.pgdg110+1))
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off)
Type "help" for help.

example=#

OKですね。

あらかじめSSL証明書を作成しておいて

$ openssl req -new -x509 -days 365 -nodes -text -out server.crt -keyout server.key -subj '/CN=example.com'

コンテナに取り込むという方法でもいいと思います。

Dockerfile
FROM postgres:15.2-bullseye

COPY server.key /etc/postgresql/server.key
COPY server.crt /etc/postgresql/server.crt

RUN chown postgres:postgres /etc/postgresql/server.key \
    && chmod 600 /etc/postgresql/server.key

CMD ["-c", "ssl=on", "-c", "ssl_cert_file=/etc/postgresql/server.crt", "-c", "ssl_key_file=/etc/postgresql/server.key"]

オフィシャルイメージのままでなんとかしたい

とはいえ、オフィシャルイメージのままでもなんとかしたいという話はあると思うので…。

SSL証明書の所有者を変更する

こんな感じで、SSL証明書を作成してuidを999にします。

$ openssl req -new -x509 -days 365 -nodes -text -out server.crt -keyout server.key -subj '/CN=example.com'
$ chmod 600 server.key
$ sudo chown 999 server.key

999は、オフィシャルイメージ内でのpostgresユーザーのuidですね。

前は70だったようなので、あまりこの方法は取りたくないものですが…。

確認。

$ docker container run -it --rm --name postgres \
   -e POSTGRES_PASSWORD=password \
   -e POSTGRES_USER=myuser \
   -e POSTGRES_DB=example \
   -v $(pwd)/server.crt:/etc/postgresql/server.crt \
   -v $(pwd)/server.key:/etc/postgresql/server.key \
   postgres:15.2-bullseye \
   -c ssl=on \
   -c ssl_cert_file=/etc/postgresql/server.crt \
   -c ssl_key_file=/etc/postgresql/server.key

OKですね。

$ docker container exec -it postgres psql -U myuser -h localhost example
psql (15.2 (Debian 15.2-1.pgdg110+1))
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off)
Type "help" for help.

example=#

当然ながら、uidが決め打ちになるのが難点です。

ENTRYPOINTを調整する

あまりやりたくないですが、ENTRYPOINTを調整する方法もあるでしょう。

$ docker container run -it --rm --name postgres \
   -e POSTGRES_PASSWORD=password \
   -e POSTGRES_USER=myuser \
   -e POSTGRES_DB=example \
   --entrypoint bash \
   postgres:15.2-bullseye \
   -c 'openssl req -new -x509 -days 365 -nodes -text -out /etc/postgresql/server.crt -keyout /etc/postgresql/server.key -subj "/CN=example.com" && chown postgres:postgres /etc/postgresql/server.{crt,key} && chmod 600 /etc/postgresql/server.key && docker-entrypoint.sh postgres -c ssl=on -c ssl_cert_file=/etc/postgresql/server.crt -c ssl_key_file=/etc/postgresql/server.key'

これでできなくもないですが、ここまでするならもうDockerfileを書いた方がいい気がしますね…。

Docker Composeで定義すると、多少は見やすくなるかもしれません。

compose.yaml
services:
  postgres:
    image: postgres:15.2-bullseye
    environment:
      POSTGRES_PASSWORD: password
      POSTGRES_USER: myuser
      POSTGRES_DB: example
    entrypoint: >-
      bash -c '
        openssl req -new -x509 -days 365 -nodes -text -out /etc/postgresql/server.crt -keyout /etc/postgresql/server.key -subj '/CN=example.com' \
        && chown postgres:postgres /etc/postgresql/server.{crt,key} \
        && chmod 600 /etc/postgresql/server.key \
        && docker-entrypoint.sh postgres \
        -c ssl=on -c ssl_cert_file=/etc/postgresql/server.crt -c ssl_key_file=/etc/postgresql/server.key
        '
1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?