DamienKarrus’s blog

プログラミングとクライミングの足跡

PostgreSQLのコンテナを作る Docker実践-1 

DBのコンテナを作ってみる。 PostgreSQLの14.xで作成することにする。カレントディレクトリを mpses とする。 Dockerfileはpostgresフォルダを作りその中に入れる

mpses/postgres/

Dockerfileを作る

FROM postgres:14-alpine
ENV LANG ja_JP.utf8

debian版とalpine版があるが、alpineのほうががサイズが小さい
次に docker-compose.yaml で起動時の初期設定を書く。Dockerfile 内で docker run しないのは、起動時の設定を覚えるのが大変だから。 docker-compose.yaml にその設定を書いてしまえばよい。

version: '3'
services:
  db:
    build: ./postgres
    ports:
      - 5432:5432
    environment:
      POSTGRES_USER: admin
      POSTGRES_PASSWORD: admin

dbという名称は任意に付けたもの。ユーザ名を指定しないとデフォルトのpostgresになる。
コンテナを起動する

$ docker-compose up -d ←デタッチモード

面倒なパラメータはdocker-composeに入っているので何も指定しなくてよい。起動されているか確認してみる。

$ docker container exec -it mpses_postgres_1 /bin/bash
bash-5.1# psql -U admin
psql (14.2)
Type "help" for help.

admin=# select version();
                                                   version
--------------------------------------------------------------------------------------------------------------
 PostgreSQL 14.2 on x86_64-pc-linux-musl, compiled by gcc (Alpine 10.3.1_git20211027) 10.3.1 20211027, 64-bit
(1 row)

admin=# \q
bash-5.1# exit
$ docker-compose down

version14.2が稼働していることが確認できた。
次はコンテナ起動時にDBにデータを入れてみる。なお、adminというユーザを登録した場合はadminというデータベースも作られているので、データベースをcreateする必要はない。
postgres の docker image は、docker-entrypoint-initdb.d 内に.sh を置いておくと起動時にその内容を実行してくれる。 postgresフォルダ内に docker-entrypoint-initdb.d フォルダを作り、以下のinit.shファイルを置いてみる。
init.sh

set -e
psql -U admin admin <<EOF
CREATE TABLE m_user(
id TEXT PRIMARY KEY,
name TEXT,
password TEXT
);
EOF

docker-composeファイルに、volume設定を定義してこのファイルを参照させる。

version: '3'
services:
  db:
    build: ./postgres
    ports:
      - 5432:5432
    environment:
      POSTGRES_USER: admin
      POSTGRES_PASSWORD: admin
    volumes:
      - ./postgres/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d

コンテナを立ち上げて、DBを確認してみる。

$ docker-compose up -d
$ docker container exec -it mpses_postgres_1 /bin/bash
bash-5.1# psql -U admin
psql (14.2)
Type "help" for help.

admin=# \d
        List of relations
 Schema |  Name  | Type  | Owner
--------+--------+-------+-------
 public | m_user | table | admin
(1 row)

admin=# \d m_user
              Table "public.m_user"
  Column  | Type | Collation | Nullable | Default
----------+------+-----------+----------+---------
 id       | text |           | not null |
 name     | text |           |          |
 password | text |           |          |
Indexes:
    "m_user_pkey" PRIMARY KEY, btree (id)

admin=#

指定した通りに生成できているようだ。 ここで一旦コンテナを削除する。

$ docker-compose down

次に、既存のDBをリストアしてみる。
バックアップファイルを docker-entrypoint-initdb.d フォルダに data.out というファイル名で用意する。init.shは不要なので削除しておく。
また、データを永続的に保存するため、ホスト側のディレクトリをマウントしたい。ところが、ホスト側(Windows)をマウントしても、書き込み権限エラーやSYNCエラーが多発する。おそらくLinuxが仮想ファイルシステムWindows上で動かしているとおもわれるがこれが良くないみたいだ。そこでdockerでvolumeを作り、それを利用することにする。

$ docker volume create mps-db-data

docker-compose.yamlは以下の通り

version: '3'
services:
    db:
        build: ./postgres
            ports:
                - 5432:5432
            environment:
                POSTGRES_USER: admin
                POSTGRES_PASSWORD: admin
            volumes:
                - mps-db-data:/var/lib/postgresql
                - ./postgres/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d
volumes:
  mps-db-data:
    external:true

コンテナに入り、バックアップデータをリストアする。

$ docker-compose up -d
$ docker-compose exec db bash
# cd /docker-entrypoint-initdb.d
# psql -U admin < data.out
...(snip)...
# psql -U admin
admin=# \d
テーブルやレコードの存在することを確認する
admin=# \q
# exit

これでデータベースの内容はvolume内に保存されたはずである。確認のため、コンテナを削除してから再構築し、データが保存されていることを確認してみる。

$ docker-compose down
$ docker container ls ←消えている
$ docker network ls ←消えている
$ docker volume ls ←volumeは残っている
DRIVER    VOLUME NAME
local     mps-db-data
$ docker-compose up -d
$ docker-compose exec db bash
# psql -U admin
admin=# \d
テーブルやレコードの存在することを確認する
admin=# \q
# exit
$ docker-compose down

DBデータの永続化ができた。くれぐれもdocker volume prune で消しませんように......

次の記事 damienkarrus.hatenablog.com