IT技術で仕事を減らしたい!

ITエンジニアのメモ+α

Docker PostgreSQLの環境構築(その2)

どうも、nippa です。

前回の内容:

timesaving.hatenablog.com

docker で postgreSQL の構築を行いましたが、より便利に使うためにホストのストレー ジとコンテナのストレージの共有設定を行いたいと思います。

コンテナの初回起動時に、データベース構築 SQL を読み込み、2 回目以降のコンテナ起 動では、前回データが読み込まれるように設定します。

今回はついでに PostgreSQL 14 がリリースされたので、14 を使ってみたいと思います。

PostgreSQL 14 Released!

環境

ディレクトリ構造

今回は下記のようなディレクトリ構造になります。

.
├── dockerfile
├── data/
└── init/
    └── init.sql

init には初回起動に実行するスクリプトを配置します。

data はコンテナの PostgreSQL データをホストと共有して保存するためのディレクトリ になります。

PostgreSQL イメージのビルド

dockerfile でイメージをpostgres:14-alpineを指定してください。

FROM postgres:14-alpine

# Time Zone
ENV TZ Asia/Tokyo

dockerfile の内容をpostgresqlというイメージ名でビルドします。

docker build -t postgresql .

コンテナの初回起動時の SQL の作成

初回実行時の SQL init/init.sqlは以下のような内容を書き込みます。

/* Variables */
\set user_name [ユーザー]
\set user_password [ユーザーのパスワード]
\set database_name [データベース名]
\set schema_name public
\set table_name users

/** CREATE ROLE **/
CREATE ROLE :user_name WITH LOGIN PASSWORD :'user_password';

/** CREATE DATABASE **/
CREATE DATABASE :database_name OWNER = :user_name TEMPLATE = template0 ENCODING = 'UTF8' LC_COLLATE = 'en_US.utf8' LC_CTYPE = 'en_US.utf8';

/** TIMEZONE Asia/Tokyo **/
ALTER DATABASE :database_name SET timezone to 'Asia/Tokyo';

/** GRANT FOR DATABASE **/
GRANT ALL ON DATABASE :database_name TO :user_name;
ALTER ROLE :user_name SET search_path TO :schema_name;

/** CONNECTION DATABASE **/
\c :database_name

/** CREATE TABLE **/
CREATE TABLE IF NOT EXISTS :schema_name.:table_name (
    id          serial PRIMARY KEY,
    username    VARCHAR ( 50 ) UNIQUE NOT NULL,
    password    VARCHAR ( 50 ) NOT NULL,
    email VARCHAR ( 255 ) UNIQUE NOT NULL,
    created_on TIMESTAMP NOT NULL
);

/** GRANT FOR TABLE **/
GRANT ALL ON :schema_name.:table_name TO :user_name;

今回は簡単な user テーブルを作成しています。

PostgreSQL コンテナの起動

コンテナの起動時にボリュームとポートを指定します。また、postgres ユーザーのパス ワード指定は必須なので指定します。

docker run --name postgres -it -p 5432:5432 -e POSTGRES_PASSWORD=[パスワード] -v $(pwd)/init:/docker-entrypoint-initdb.d -v $(pwd)/data:/var/lib/postgresql/data -d postgresql

起動の確認を行います。

docker ps

CONTAINER ID   IMAGE        COMMAND                  CREATED         STATUS         PORTS                    NAMES
a22e709fd827   postgresql   "docker-entrypoint.s…"   2 minutes ago   Up 2 minutes   0.0.0.0:5432->5432/tcp   postgres

データベースの確認

以下のコマンドでコンテナの PosgreSQL にログインします。

psql -U [ユーザー名] -h localhost -p 5432 -d [データベース名]

# 出力
Password for user [ユーザー名]: <--- パスワードを入力
psql (14.0, server 14.1)
Type "help" for help.

[データベース名]=>

データベースにログインしたら、テーブルの確認を行います。

[データベース名]=>\d

# 出力
             List of relations
 Schema |    Name     |   Type   |  Owner
--------+-------------+----------+----------
 public | user        | table    | postgres
 public | user_id_seq | sequence | postgres
(2 rows)

初回起動時の SQL が読み込まれ、user テーブルと user_id_seq テーブルが作成されて います。今回 admin ユーザーを指定していないので、初回起動時の SQL は posgres ユ ーザーで作成されています。権限の確認をします。

[データベース名]=> \z

# 出力
                                      Access privileges
 Schema |     Name     |   Type   |     Access privileges          | Column privileges | Policies
--------+--------------+----------+--------------------------------+-------------------+----------
 public | users        | table    | postgres=arwdDxt/postgres+     |                   |
        |              |          | [ユーザー名]=arwdDxt/postgres    |                   |
 public | users_id_seq | sequence |                                |                   |
(2 rows)

権限が正しくついています。select 文を実行してみます。

[データベース名]=>  select * from users;
 id | username | password | email | created_on
----+----------+----------+-------+------------
(0 rows)

テーブルが空になっています。ここデータを挿入します。

[データベース名]=> INSERT INTO users (username, password, email, created_on) VALUES ('Yamada Taro', 'yamadatraro', 'yamada-taro@example.com', now());

# 出力
INSERT 0 1

[データベース名]=> select * from users;
 id |  username   |  password   |          email          |         created_on
----+-------------+-------------+-------------------------+----------------------------
  1 | Yamada Taro | yamadatraro | yamada-taro@example.com | 2021-11-13 14:28:24.695819
(1 row)

データ挿入が確認できたので、コンテナを停止・削除を行ったのちに再度起動します。

# コンテナの停止
docker stop postgres

# コンテナの削除
docker rm postgres

# 削除されていることを確認
docker ps

コンテナを再度起動させます。

docker run --name postgres -it -p 5432:5432 -e POSTGRES_PASSWORD=[パスワード] -v $(pwd)/init:/docker-entrypoint-initdb.d -v $(pwd)/data:/var/lib/postgresql/data -d postgresql

データベースにアクセスしてデータが残っているかを確認します。

psql -U [ユーザー名]] -h localhost -d [データベース名]
Password for user [ユーザー名]]:
psql (14.0, server 14.1)
Type "help" for help.

[データベース名]=> select * from users;
 id |  username   |  password   |          email          |         created_on
----+-------------+-------------+-------------------------+----------------------------
  1 | Yamada Taro | yamadatraro | yamada-taro@example.com | 2021-11-20 21:28:24.695819
(1 row)

データが残っていることが確認できました。

感想

今回、docker Postgresql を開発でより使いやすくするために、ホスト側とストレージを 共有して、データ部分を残す方法をご紹介しました。

これで、必要なときに必要なデータベースを切り替えて開発することができるので、非常 に便利です。

docker-compose を使うと更に便利になりますので、こちらも紹介したいと思います。

ではでは、また次回。