Docker で PostgreSQL を使いたい


- 概要
    - PostgreSQL のコンテナを作成し psql でログインする手順です
    - `data/` ディレクトリにデータを保存して永続化します
- 補足
    - 環境は Ubuntu, bash です
    - コピペで動作します
- 使用する Docker Image
    - [postgres - Official Image | Docker Hub](https://hub.docker.com/_/postgres)

## Step 1. bash

コンテナを立ち上げ psql でローカルからコンテナの PostgreSQL サーバにログインします。

```bash:bash
# PostgreSQL のデータを保存するディレクトリを作成する。
mkdir data/

# Docker
docker container run \
  --interactive \
  --tty \
  --rm \
  --user $(id -u):$(id -g) \
  --volume ${PWD}/data:/var/lib/postgresql/data \
  --publish 5432:5432 \
  --name my-postgres \
  --env POSTGRES_DB=my-postgres \
  --env POSTGRES_USER=my-postgres \
  --env POSTGRES_PASSWORD=my-postgres \
  postgres:16


# PostgreSQL
PGPASSWORD="my-postgres" psql \
  --host "localhost" \
  --username "my-postgres" \
  --dbname "my-postgres"
```



<details><summary>補足</summary>


これが無いと `data/` ディレクトリ配下のファイルの所有者が root で作成されてしまい設定ファイルをいじるとき面倒になります。

```
  --user $(id -u):$(id -g) \
```

<br />

データを永続化させる方法もいろいろ種類があるそうです。リンク先を参照してください。

```
  --volume ${PWD}/data:/var/lib/postgresql/data \
```
* [Docker、ボリューム(Volume)について真面目に調べた - Qiita](https://qiita.com/gounx2/items/23b0dc8b8b95cc629f32)


<br />

指定されたデータベースやユーザが存在しなかった場合は作成するみたいな動作をしていると思われます。`initdb` コマンドを実行してくれているのだと思います。

```
  --env POSTGRES_DB=my-postgres \
  --env POSTGRES_USER=my-postgres \
  --env POSTGRES_PASSWORD=my-postgres \
```

* [OSS-DB Silver 学習メモその2【initdbについて】 - Qiita](https://qiita.com/takada-syunya/items/98eb24ff76e99e1c54a9)


</details>



## Step 2. psql

テーブルを作成する。

```:psql
\d

CREATE TABLE Person (
    name VARCHAR(100),
    age INT
);

\d
\q
```



## Step 3. bash

コンテナを再起動し psql でコンテナの PostgreSQL サーバにログインする。

```bash:bash
docker container stop my-postgres

docker container run \
  --interactive \
  --tty \
  --rm \
  --user $(id -u):$(id -g) \
  --volume ${PWD}/data:/var/lib/postgresql/data \
  --publish 5432:5432 \
  --name my-postgres \
  postgres:16

PGPASSWORD="my-postgres" psql \
  --host "localhost" \
  --username "my-postgres" \
  --dbname "my-postgres"
```

<details><summary>補足</summary>


データベースとユーザは作成されているので以下のオプションは不要になります。

```
  --env POSTGRES_DB=my-postgres \
  --env POSTGRES_USER=my-postgres \
  --env POSTGRES_PASSWORD=my-postgres \
```

</details>



## Step 4. psql

`Person` テーブルが残っているのが確認できるはず...
プロジェクトルートの `data/` ディレクトリ配下でデータを保存して永続化しています。

```:psql
\d
```

## そのほか

### ◯ コマンド

```
# 1. コンテナにログイン
docker exec -it my-postgres bash

# 2. コンテナから psql で PostgreSQL サーバにログイン
docker exec -it my-postgres psql my-postgres my-postgres
```

2 番目のコマンドでパスワードがなくても PostgreSQL にログインできるのは data/pg_hba.conf でローカルからの接続は trust になっているからです。セキュリティにはご注意ください。

* [Docker が俺の Postgres を勝手に全世界に公開しやがって色々怒られた話 - Qiita](https://qiita.com/isso_719/items/c22e617986c821b2f624)

### ◯ はまりどころ

psql でログインするときはローカルホストであっても `-h` を省略せず `-h localhost` を指定してください。省略すると以下のようにハマります。

- [Docker, PostgreSQL - "/var/run/postgresql/.s.PGSQL.5432" failed: No such file or directory](https://qiita.com/domodomodomo/items/99ce7ca0dcff41e3d838)

### ◯ まとめ

- PosqgreSQL のデータは `/var/lib/postgresql/data` に保存されます
- `/var/lib/postgresql/data` をローカルのディレクトリにマウントすればデータを永続化できます
- `docker container run ... postgres:16` は `/var/lib/postgresql/data` が空っぽの場合、自動で初期化してくれます。`Ubuntu` のイメージから PostgreSQL をインストールした場合はこの作業を Dockerfile に書かないといけません