どうも、nippa です。
前回の内容:
docker で postgreSQL の構築を行いましたが、より便利に使うためにホストのストレー ジとコンテナのストレージの共有設定を行いたいと思います。
コンテナの初回起動時に、データベース構築 SQL を読み込み、2 回目以降のコンテナ起 動では、前回データが読み込まれるように設定します。
今回はついでに PostgreSQL 14 がリリースされたので、14 を使ってみたいと思います。
環境
- macOS 10.15
- PostgreSQL 14
ディレクトリ構造
今回は下記のようなディレクトリ構造になります。
. ├── 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 を使うと更に便利になりますので、こちらも紹介したいと思います。
ではでは、また次回。