MySQL しか使ったことないアプリケーション開発者が PostgreSQL の Docker 環境を立てるまで
最近仕事で PostgreSQL を使うことになったので、忘備録としてDocker で環境構築して一通り触ったメモを、主に MySQL との差分に注目しながら書きます。
PostgreSQL の Docker image
PostgreSQL は公式の docker image が公開されています
基本的に ${Postgresのバージョン}-${baseのLinux OS}
の名前で 11.14-apline
とか 12.9-bullseye
とかのタグがつけられています。
数字のみのタグは -bullseye
と同内容(Debian 11 ベース)のようです。
基本的には好みのバージョンの -alpine
を使い、何か困ったら -bullseye
に変える感じにすればいいと思います。
以下のような docker-compose.yaml
を準備しておきます。
version: '3.7' services: db: image: postgres:13.4-alpine ports: - 5432:5432 # postgres はデフォルトで 5432 を使う environment: - POSTGRES_HOST=localhost - POSTGRES_PASSWORD=password # スーパーユーザーのパスワード - POSTGRES_USER=admin # スーパーユーザーの名前。デフォルトは `postgres` - POSTGRES_DB=test_db # この環境変数で指定した名前のデータベースを自動で作ってくれる # パスワード無しでのログインを可能にする。MySQL における `MYSQL_ALLOW_EMPTY_PASSWORD=yes` とほぼ同じ # - POSTGRES_HOST_AUTH_METHOD=trust volumes: - postgres-tmp:/var/lib/postgresql/data volumes: postgres-tmp:
POSTGRES_PASSWORD
に何かしらの値を入れるあるいは POSTGRES_HOST_AUTH_METHOD=trust
を付けるのどちらかを行わないと、起動時にエラーを吐きます。
対話型クライアント psql
PostgreSQL は psql
という対話型 のクライアントが用意されています。MySQL における mysql
コマンドとだいたい同じです。
先述の docker-compose.yaml で image を立ち上げている場合、 docker compose exec db psql -U admin -W test_db
で立ち上げられます。
docker compose exec db psql -U admin -W test_db Password: password psql (13.4) Type "help" for help. test_db=#
ここに出てきたオプションの説明です。
-U
(または--username
): ユーザー名-W
: パスワード要求プロンプトを表示させるtest_db
: 使用するデータベース名*1
MySQL との違いはユーザー名のあたりぐらいでしょうか(MySQL では -u
または --user
)
私の環境ではなぜか POSTGRES_HOST_AUTH_METHOD=trust
を指定しなくてもパスワード入力を省略してログインできたり、パスワードプロンプトに間違った文字列を入力してもログインできたりする現象が発生しました(ローカル環境で動作確認をする分には問題ないのでとりあえずそのままで)。
psql を起動できたのでとりあえず色々触ってみましょう。psql にはメタコマンドと呼ばれるものが用意されており、以下のようなものがあります。
メタコマンド | 説明 | MySQLで似たような挙動をするやつ |
---|---|---|
\? (またはhelp ) |
ヘルプを表示 | ? help |
\l |
データベース一覧を表示 | show databases |
\du |
ユーザー一覧を表示 | select * from mysql.user; など |
\dn |
スキーマ一覧を表示 | スキーマは MySQL には存在しない |
\dt |
テーブル一覧を表示 | show tables |
\d {テーブル名} |
指定したテーブルの概要を表示 | show columns from {テーブル名} |
\c {データベース名} |
指定したデータベースに接続する | use {データベース名} |
\q |
psql を終了((PostgrSQL 11 以降は exit も可)) |
q quit exit |
とりえあず、適当にテーブルを作って、適当にデータを追加して、適当に取得してみます。
データベース一覧を見る
test_db=# \l List of databases Name | Owner | Encoding | Collate | Ctype | Access privileges -----------+-------+----------+------------+------------+------------------- postgres | admin | UTF8 | en_US.utf8 | en_US.utf8 | template0 | admin | UTF8 | en_US.utf8 | en_US.utf8 | =c/admin + | | | | | admin=CTc/admin template1 | admin | UTF8 | en_US.utf8 | en_US.utf8 | =c/admin + | | | | | admin=CTc/admin test_db | admin | UTF8 | en_US.utf8 | en_US.utf8 |
POSTGRES_DB
で指定した test_db
というデータベースが作成されています。
テーブル作成
適当に CREATE TABLE
します。
test_db=# CREATE TABLE "test_table" ( "id" VARCHAR(32) NOT NULL, "name" VARCHAR(255) NOT NULL, "tags" VARCHAR(255)[] NOT NULL, "created_at" TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY ("id") ); CREATE TABLE
\dt
でテーブル一覧を表示すると、作成した test_table
が確認できます。
test_db=# \dt List of relations Schema | Name | Type | Owner --------+------------+-------+------- public | test_table | table | admin
\d test_table
で test_table
の中身を見ます。
test_db=# \d test_table; Table "public.test_table" Column | Type | Collation | Nullable | Default ------------+--------------------------------+-----------+----------+------------------- id | character varying(32) | | not null | name | character varying(255) | | not null | tags | character varying(255)[] | | not null | created_at | timestamp(6) without time zone | | not null | CURRENT_TIMESTAMP Indexes: "test_table_pkey" PRIMARY KEY, btree (id)
PRIMARY KEY の指定方法が MySQL とちょっと違いますね。あと、 PostgreSQL は配列型を使えるようで便利そうですね。*2
データを保存・取得
test_table
にデータを適当に insert してみます。
test_db=# INSERT INTO test_table ("id", "name", "tags") VALUES ( 'id1234', 'MyName', Array['tag1','tag2']); INSERT 0 1
配列は Array[]
で囲むか {}
で囲むかすると表現できるようです。あとは連結演算子 ||
があって Array[1,2] || 3
とか書くと Array[1,2,3]
になったりとか便利そうな機能が用意されています。
データ取得も普通に SELECT 文を書くだけです。
test_db=# SELECT * FROM "test_table" WHERE "id"='id1234'; id | name | tags | created_at --------+--------+-------------+---------------------------- id1234 | MyName | {tag1,tag2} | 2022-02-03 09:55:55.306328
アプリケーション開発の場面では、実際のデータベースへのアクセスはほとんどの場合ライブラリ任せで生のクエリを書くことはあまりないので(特に書き込み系)動作確認はこれぐらいで。
スキーマ
PostgreSQL にはデータベースとテーブルの間にスキーマという層が存在し、三層構造になっています。MySQL にはスキーマが存在せず二層であり、このあたりが両者の大きな相違点なのかなと思います。
デフォルトでは public
という名前のスキーマが用意されており、クエリが省略されているときは自動で補完されます。
public スキーマのみを使用すれば MySQL とだいたい同じ使用感になると思われますが、 MySQL では test_db.test_table
と書けたところが PostgreSQL では test_db.public.table
になる点は注意したいですね。
おわりに(日記)
本稿では、 PostgreSQL の Docker image を構築し、一通り触ってみました。
余談ですが、ポスグレを使うことになった経緯について少し書きます。
そこそこ大きな Node.js 製アプリケーションの一部をマイクロサービス化しつつちょっと新機能を追加する試みを進めており、その一環で私は現在 TypeScript で小さめのアプリケーションを作っています。 既存アプリケーションからのデータの移行等はなく、データベースは新規に作ったものを使うことになりました。 ある程度プロトタイプの開発を進めて方向性が決まった段階で、データベースの選定について SRE に相談したところ、 PostgreSQL を使うことになりました。 弊社ではこれまで RDB は MySQL を使っていましたが、 PostgreSQL の知見を貯める意味で試験的にやってみよう❗という感じです。
当初は前例に習って MySQL を使うつもりで進めていましたが途中で postgreSQL に切り替えるという状況になったのですが、データベースの操作は ORM ライブラリの Prisma*3 を使用しており、設定ファイルをちょっと書き換えるだけで、アプリケーションの実装はほぼそのままで移行が住みました。
以上、 ORM って便利ですねという日記でした。
この記事は業務時間中に書きました。 仕事の一貫なので弊社の宣伝を
↓弊社開発チームメンバーのブログ記事集です↓
↓我々と一緒に働きたい人を募集中です↓
参考資料