目次

DockerでPostgreSQLを実行する:インストール、接続、バックアップ、アップグレード

PostgreSQL 18の重要な変更点:postgres:18 以降、公式イメージのデータディレクトリは /var/lib/postgresql/18/docker に変わりました。Volumeは /var/lib/postgresql にマウントしてください。多くのオンラインチュートリアルに記載されている /var/lib/postgresql/data は17以前のパスです。18で使うと起動に失敗します。以下で実際の動作を確認します。

1行のコマンドで起動する

$ docker run -d --name pg -e POSTGRES_PASSWORD=secret -p 127.0.0.1:5432:5432 -v pgdata:/var/lib/postgresql --restart unless-stopped postgres:18
1b34d05a195f347c86e431441162b760167a5c04016a528e10342d0199be016d

$ docker logs pg 2>&1 | tail -n 3
2026-10-13 00:53:32.071 UTC [1] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
2026-10-13 00:53:32.075 UTC [72] LOG:  database system was shut down at 2026-10-13 00:53:31 UTC
2026-10-13 00:53:32.080 UTC [1] LOG:  database system is ready to accept connections

$ docker exec pg psql -U postgres -c "SHOW data_directory;"
        data_directory
-------------------------------
 /var/lib/postgresql/18/docker
(1 row)
パラメーター説明
POSTGRES_PASSWORDスーパーユーザーのパスワード(必須)
-p 127.0.0.1:5432:5432ローカルマシンからのみ接続可能にします
-v pgdata:/var/lib/postgresqlデータをVolume pgdata に保存します。18ではこのパスをマウントします

SHOW data_directory で、実際のデータディレクトリが /var/lib/postgresql/18/docker であり、マウントした /var/lib/postgresql の下にあることを確認できます。ディレクトリ名にはメジャーバージョン番号が含まれるため、将来アップグレードするときに新旧バージョンのデータを同じVolume内に共存させられます。

その他のよく使う環境変数:

環境変数説明デフォルト値
POSTGRES_USERスーパーユーザー名postgres
POSTGRES_DBデフォルトのデータベースPOSTGRES_USER と同じ
PGDATAデータディレクトリ/var/lib/postgresql/18/docker(18)
TZタイムゾーンUTC

MySQLと同様、これらの変数が有効なのはデータディレクトリが空の場合だけです。あとから POSTGRES_PASSWORD を変更しても既存のパスワードは変わりません。ALTER USER ... PASSWORD '...' を使って変更してください。

実際の動作:18では古いパスへのマウントに失敗する

古いチュートリアルに従い、Volumeを /var/lib/postgresql/data にマウントします:

$ docker run -d --name pgold -e POSTGRES_PASSWORD=secret -v pgold:/var/lib/postgresql/data postgres:18
b480eb9c72b29fa99f1ed8df17972e2bfc2d6da4b86c058a36cf21fd63579bfa

$ docker ps -a --filter name=pgold --format "{{.Status}}"
Exited (1) 5 seconds ago

$ docker logs pgold 2>&1 | head -n 12
Error: in 18+, these Docker images are configured to store database data in a
       format which is compatible with "pg_ctlcluster" (specifically, using
       major-version-specific directory names).  This better reflects how
       PostgreSQL itself works, and how upgrades are to be performed.

       See also https://github.com/docker-library/postgres/pull/1259

       Counter to that, there appears to be PostgreSQL data in:
         /var/lib/postgresql/data (unused mount/volume)

       This is usually the result of upgrading the Docker image without
       upgrading the underlying database using "pg_upgrade" (which requires both

コンテナは数秒で Exited (1) になって終了します。エラーメッセージによると、18ではメジャーバージョンごとのディレクトリを使うように変わり、/var/lib/postgresql/data に「使用されていないマウント」が見つかりました。このチェックは、データが保存されていると思っていても実際にはすべてコンテナ内に書き込まれ、コンテナを削除すると消えてしまう事態を防ぐためのものです。マウント先を /var/lib/postgresql に変更すれば解決します。

Compose で管理する

実際のプロジェクトでは Compose の使用をおすすめします。pg-demo フォルダーを作成します。

pg-demo/
├── compose.yaml
├── .env
└── initdb/
    └── 01-init.sql

.env:

DB_PASSWORD=change-this-password

initdb/01-init.sql(初回の初期化時に実行され、拡張機能、テーブル、サンプルデータを作成します。最後の pg_sleep(8) は、大量のデータのインポートなど時間のかかる初期化を意図的にシミュレートし、ヘルスチェックを確認するためのものです):

CREATE EXTENSION IF NOT EXISTS pg_trgm;

CREATE TABLE products (
  id serial PRIMARY KEY,
  name text NOT NULL,
  price integer NOT NULL
);

INSERT INTO products (name, price) VALUES ('珍珠奶茶', 65), ('鳳梨酥', 45), ('牛肉麵', 180);

-- 時間のかかる初期化をシミュレートします(例:大量のデータのインポート)
SELECT pg_sleep(8);

compose.yaml:

services:
  db:
    image: postgres:18
    environment:
      POSTGRES_USER: app
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      POSTGRES_DB: app
      TZ: Asia/Taipei
    command: ["postgres", "-c", "max_connections=200", "-c", "shared_buffers=256MB"]
    ports:
      - "127.0.0.1:5432:5432"
    volumes:
      - pgdata:/var/lib/postgresql
      - ./initdb:/docker-entrypoint-initdb.d:ro
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -h 127.0.0.1 -U app -d app"]
      interval: 2s
      timeout: 3s
      retries: 30
    shm_size: 256mb
    restart: unless-stopped

volumes:
  pgdata:
設定説明
POSTGRES_USER: appスーパーユーザーの名前が app に変わり、postgres というユーザーは作成されません
command: ["postgres", "-c", ...]-c で PostgreSQL の設定を渡すため、別途設定ファイルを用意する必要はありません
pg_isready -h 127.0.0.1PostgreSQL に組み込まれたチェックツールです。必ず -h 127.0.0.1 を追加してください。理由は下の実測結果をご覧ください
shm_size: 256mbDocker のデフォルトでは共有メモリ /dev/shm は 64 MB しかありません。複雑なクエリでは could not resize shared memory segment エラーが発生することがあります
$ docker compose up -d --wait
[+] up 3/3
 ✔ Network pg-demo_default Created                                                                                                                0.0s
 ✔ Volume pg-demo_pgdata   Created                                                                                                                0.0s
 ✔ Container pg-demo-db-1  Healthy                                                                                                               11.3s

$ docker compose exec db psql -U app -h 127.0.0.1 -c "SELECT * FROM products;"
 id |   name   | price
----+----------+-------
  1 | 珍珠奶茶 |    65
  2 | 鳳梨酥   |    45
  3 | 牛肉麵   |   180
(3 rows)


$ docker compose logs db 2>&1 | grep -E "running /docker-entrypoint-initdb.d|init process complete|listening on IPv4"
db-1  | /usr/local/bin/docker-entrypoint.sh: running /docker-entrypoint-initdb.d/01-init.sql
db-1  | PostgreSQL init process complete; ready for start up.
db-1  | 2026-10-13 08:52:58.663 CST [1] LOG:  listening on IPv4 address "0.0.0.0", port 5432

$ docker compose exec db psql -U app -c "SHOW max_connections;" -c "SHOW shared_buffers;" -c "SELECT now();"
 max_connections
-----------------
 200
(1 row)

 shared_buffers
----------------
 256MB
(1 row)

              now
-------------------------------
 2026-10-13 08:53:01.293902+08
(1 row)


$ docker compose exec db df -h /dev/shm
Filesystem      Size  Used Avail Use% Mounted on
shm             256M  1.1M  255M   1% /dev/shm

$ docker compose exec db psql -U app -c "\dx"
                                             List of installed extensions
  Name   | Version | Default version |   Schema   |                            Description
---------+---------+-----------------+------------+-------------------------------------------------------------------
 pg_trgm | 1.6     | 1.6             | public     | text similarity measurement and index searching based on trigrams
 plpgsql | 1.0     | 1.0             | pg_catalog | PL/pgSQL procedural language
(2 rows)
  • Healthy になるまで 11.3 秒かかりました。これは初期化と pg_sleep(8) にかかった時間と一致します。ヘルスチェック後にすぐ TCP 接続すると、データがすべてあり、中国語も正しく表示されます。
  • ログから、初期化スクリプトが実行され、初期化が完了してから 0.0.0.0:5432 でリッスンを開始したことがわかります。
  • max_connections は 200、shared_buffers は 256MB で、command のパラメーターが反映されています。now() はタイムゾーンが +08 であることを示します。
  • /dev/shm は 256M で、shm_size が反映されています。
  • \dx にはインストール済みの拡張機能が表示され、pg_trgm が初期化スクリプトによって作成されています。

ヘルスチェックの落とし穴:pg_isready に -h を付けないと healthy が早く返る

よく見かける書き方は pg_isready -U app -d app(-h なし)です。この書き方に変更して実測してみます。

$ docker compose up -d --wait
[+] up 3/3
 ✔ Network pg-demo_default Created                                                                                                                0.0s
 ✔ Volume pg-demo_pgdata   Created                                                                                                                0.0s
 ✔ Container pg-demo-db-1  Healthy                                                                                                                3.2s

$ docker compose exec db psql -U app -h 127.0.0.1 -c "SELECT count(*) FROM products;"
psql: error: connection to server at "127.0.0.1", port 5432 failed: Connection refused
	Is the server running on that host and accepting TCP/IP connections?

$ docker compose logs db 2>&1 | grep -E "pg_sleep|init process complete|listening on IPv4"

わずか 3.2 秒 で Healthy と報告されますが、TCP 接続すると Connection refused が返されます。

理由は MySQL と同じです。初期化中、起動スクリプトは initdb 内のスクリプトを実行するために、Unix ソケット接続のみを受け付ける一時サーバーを先に起動します。pg_isready に -h を付けないとソケット接続を使うため、初期化が完了する前に接続可能と報告してしまいます。それに依存するアプリケーション(depends_on の condition: service_healthy)はこの時点で起動し、TCP 接続に失敗します。-h 127.0.0.1 を追加して TCP 接続を強制すれば、本番サーバーが起動するまで待てます。

接続と psql

psql を使った操作

コンテナ内には psql クライアントがあります。対話形式で使うには docker compose exec db psql -U app(単独のコンテナの場合は docker exec -it pg psql -U postgres)を実行し、app=# プロンプトが表示されたら SQL または以下のコマンドを入力します。-c を使って直接実行することもできます。

$ docker compose exec db psql -U app -c "SELECT version();"
                                                      version
--------------------------------------------------------------------------------------------------------------------
 PostgreSQL 18.6 (Debian 18.6-1.pgdg13+2) on x86_64-pc-linux-gnu, compiled by gcc (Debian 14.2.0-19) 14.2.0, 64-bit
(1 row)


$ docker compose exec db psql -U app -c "\l"
                                                 List of databases
   Name    | Owner | Encoding | Locale Provider |  Collate   |   Ctype    | Locale | ICU Rules | Access privileges
-----------+-------+----------+-----------------+------------+------------+--------+-----------+-------------------
 app       | app   | UTF8     | libc            | en_US.utf8 | en_US.utf8 |        |           |
 postgres  | app   | UTF8     | libc            | en_US.utf8 | en_US.utf8 |        |           |
 template0 | app   | UTF8     | libc            | en_US.utf8 | en_US.utf8 |        |           | =c/app           +
           |       |          |                 |            |            |        |           | app=CTc/app
 template1 | app   | UTF8     | libc            | en_US.utf8 | en_US.utf8 |        |           | =c/app           +
           |       |          |                 |            |            |        |           | app=CTc/app
(4 rows)


$ docker compose exec db psql -U app -c "\dt"
          List of tables
 Schema |   Name   | Type  | Owner
--------+----------+-------+-------
 public | products | table | app
(1 row)


$ docker compose exec db psql -U app -c "\d products"
                            Table "public.products"
 Column |  Type   | Collation | Nullable |               Default
--------+---------+-----------+----------+--------------------------------------
 id     | integer |           | not null | nextval('products_id_seq'::regclass)
 name   | text    |           | not null |
 price  | integer |           | not null |
Indexes:
    "products_pkey" PRIMARY KEY, btree (id)


$ docker compose exec db psql -U app -c "\du"
                             List of roles
 Role name |                         Attributes
-----------+------------------------------------------------------------
 app       | Superuser, Create role, Create DB, Replication, Bypass RLS
コマンド役割
\lデータベースを一覧表示する
\c 名前データベースを切り替える
\dtテーブルを一覧表示する
\d テーブルテーブルの構造を確認する
\duユーザー(ロール)を一覧表示する
\dxインストール済みの拡張機能を一覧表示する
\q終了する

\du には app が Superuser と表示され、\l ではすべてのデータベースの Owner も app です。POSTGRES_USER を設定すると、デフォルトの postgres に代わってそのユーザーが使われます。

コンテナ内でパスワードが不要な理由

上記の psql コマンドではパスワードを入力していません。データディレクトリにある pg_hba.conf(PostgreSQL の接続認証ルール)を確認します。

$ docker compose exec db grep -v "^#" /var/lib/postgresql/18/docker/pg_hba.conf | grep -v "^$"
local   all             all                                     trust
host    all             all             127.0.0.1/32            trust
host    all             all             ::1/128                 trust
local   replication     all                                     trust
host    replication     all             127.0.0.1/32            trust
host    replication     all             ::1/128                 trust
host all all all scram-sha-256

$ docker run --rm --network pg-demo_default -e PGPASSWORD=wrong postgres:18 psql -h db -U app -c "SELECT 1;"
psql: error: connection to server at "db" (172.19.0.2), port 5432 failed: FATAL:  password authentication failed for user "app"

$ docker run --rm --network pg-demo_default -e PGPASSWORD=change-this-password postgres:18 psql -h db -U app -c "SELECT current_user, inet_server_addr();"
 current_user | inet_server_addr
--------------+------------------
 app          | 172.19.0.2
(1 row)
  • 公式イメージの設定では、コンテナ内からの接続(Unix ソケット、127.0.0.1、::1)にはすべて trust が適用され、パスワードは確認されません。
  • その他の接続元(最後の行の host all all all)では、scram-sha-256 によるパスワード認証が使われます。
  • 同じ Compose ネットワーク内の別のコンテナから db に接続する場合、パスワードが間違っていると password authentication failed が返り、正しいパスワードでのみ接続できます。

つまり、コンテナに入れる人はデータベースを直接操作できます。そのため Docker の権限を適切に保護する必要があります(Docker のセキュリティを参照)。ホストから -p で割り当てたポート経由で接続する場合、接続元 IP アドレスは Docker ネットワークのゲートウェイとなり、同じくパスワードが必要です。

ホストや他のコンテナから接続する

postgres://app:パスワード@127.0.0.1:5432/app   # ホストから(GUI ツール、アプリケーション)
postgres://app:パスワード@db:5432/app          # 同じ Compose プロジェクトの他のサービスから

よくある接続エラー

$ docker compose exec db psql -c "SELECT 1;"
psql: error: connection to server on socket "/var/run/postgresql/.s.PGSQL.5432" failed: FATAL:  role "root" does not exist

$ docker compose exec db psql -U postgres -c "SELECT 1;"
psql: error: connection to server on socket "/var/run/postgresql/.s.PGSQL.5432" failed: FATAL:  role "postgres" does not exist

$ docker compose exec db psql -U app -d shop -c "SELECT 1;"
psql: error: connection to server on socket "/var/run/postgresql/.s.PGSQL.5432" failed: FATAL:  database "shop" does not exist

$ docker compose exec -e PGPASSWORD=wrong db psql -h 127.0.0.1 -U app -c "SELECT 1;"
 ?column?
----------
        1
(1 row)


$ docker compose exec db psql -U app -h 127.0.0.1 -p 5433 -c "SELECT 1;"
psql: error: connection to server at "127.0.0.1", port 5433 failed: Connection refused
	Is the server running on that host and accepting TCP/IP connections?
エラー原因
role "root" does not existpsql に -U を付けていないため、現在のシステムユーザー名(コンテナ内では root)がデフォルトで使われます
role "postgres" does not existPOSTGRES_USER を設定したため、デフォルトの postgres ユーザーが存在しません
database "shop" does not existPOSTGRES_DB で作成されるのは初期化時のみです。他のデータベースは自分で CREATE DATABASE を実行して作成します
Connection refusedポートが間違っている、データベースの起動が完了していない、または接続先のホストが間違っています
password authentication failedパスワードが間違っているか、別のパスワードで初期化された Volume を使っています

4 つ目のコマンドに注目してください。コンテナ内では、間違ったパスワードを使って 127.0.0.1 に接続しても成功しています。これは上記の trust ルールによるものです。

バックアップと復元

$ docker compose exec -T db pg_dump -U app app > app.sql

$ ls -lh app.sql && grep -E "^CREATE (TABLE|EXTENSION)" app.sql
-rw-r--r--    1 root     root        2.3K Oct 13 00:53 app.sql
CREATE EXTENSION IF NOT EXISTS pg_trgm WITH SCHEMA public;
CREATE TABLE public.products (

$ docker compose exec -T db pg_dump -U app -Fc app > app.dump

$ ls -lh app.dump
-rw-r--r--    1 root     root        3.1K Oct 13 00:53 app.dump

$ docker compose exec db psql -U app -c "DROP TABLE products;"
DROP TABLE

$ docker compose exec -T db pg_restore -U app -d app --clean --if-exists < app.dump

$ docker compose exec db psql -U app -c "SELECT count(*) FROM products;"
 count
-------
     3
(1 row)


$ rm app.sql app.dump
コマンド説明
pg_dump app > app.sqlSQL のプレーンテキスト形式でエクスポートします。直接読んだり、psql でインポートしたりできます
pg_dump -Fc app > app.dumpカスタム形式で、圧縮されています。pg_restore で復元でき、特定のテーブルだけを復元することもできます
pg_restore --clean --if-exists重複を避けるため、復元前に既存のオブジェクトを削除します
exec -TCompose の exec はデフォルトで TTY を割り当てます。リダイレクトを使うときは -T を付けて無効にします

バックアップには CREATE EXTENSION が含まれているため、新しいデータベースに復元すると拡張機能も作成されます。このサンプルのデータは少ないため、カスタム形式(3.1K)のほうがプレーンテキスト(2.3K)より大きくなっています。データ量が多い場合は、カスタム形式のほうがかなり小さくなります。

その他のよく使うコマンド:

# すべてのデータベースとロール(ユーザー、パスワード)をバックアップ
docker compose exec -T db pg_dumpall -U app > all.sql

# SQL のプレーンテキスト形式を復元
docker compose exec -T db psql -U app -d app < app.sql

上記のコマンドと cron を組み合わせて定期的にバックアップし、ファイルを別のマシンやクラウドストレージにコピーできます。

Windows ユーザーのバックアップと復元

PowerShell は < をサポートしていません。また、Windows PowerShell 5.1 の > はファイルのエンコーディングを変更し、-Fc のバイナリバックアップは破損してしまいます。代わりに、コンテナ内で pg_dump -f を使ってファイルを作成し、docker compose cp でコピーします。この方法はすべてのシステムで使えます。

# バックアップ
docker compose exec db pg_dump -U app -Fc -f /tmp/app.dump app
docker compose cp db:/tmp/app.dump app.dump

# 復元
docker compose cp app.dump db:/tmp/restore.dump
docker compose exec db pg_restore -U app -d app --clean --if-exists /tmp/restore.dump

このコマンドでは $(pwd)、<、> を使わないため、bash、PowerShell、CMD でそのまま実行できます。実際に(テーブルを作成し、バックアップ、削除、復元)した結果:

$ docker compose exec db psql -U app -c 'CREATE TABLE t (id int); INSERT INTO t VALUES (1),(2);'
CREATE TABLE
INSERT 0 2

$ docker compose exec db pg_dump -U app -Fc -f /tmp/app.dump app

$ docker compose cp db:/tmp/app.dump app.dump
 pgwin-db-1 Copying pgwin-db-1:/tmp/app.dump to app.dump
 pgwin-db-1 Copied pgwin-db-1:/tmp/app.dump to app.dump

$ ls -l app.dump
-rw-rw-rw-    1 root     root          1251 Oct 13 05:30 app.dump

$ docker compose exec db psql -U app -c 'DROP TABLE t;'
DROP TABLE

$ docker compose cp app.dump db:/tmp/restore.dump
 pgwin-db-1 Copying app.dump to pgwin-db-1:/tmp/restore.dump
 pgwin-db-1 Copied app.dump to pgwin-db-1:/tmp/restore.dump

$ docker compose exec db pg_restore -U app -d app /tmp/restore.dump

$ docker compose exec db psql -U app -c 'SELECT count(*) FROM t;'
 count
-------
     2
(1 row)

メジャーバージョンのアップグレード(例:16 → 18)

マイナーバージョンの更新(例:18.5 → 18.6)では、新しいイメージを取得してコンテナを再作成するだけです。メジャーバージョンの場合は異なります。PostgreSQL のメジャーバージョンが異なると、データファイル形式に互換性がありません。

まず、バージョン 16 でデータを作成します。

$ docker run -d --name pg16 -e POSTGRES_PASSWORD=secret -v pg16data:/var/lib/postgresql/data postgres:16
20691764a98828d24c958eaaa71e83c08ebff29b984350ff7f6782ba8d74b4ca

$ docker exec pg16 psql -U postgres -c "CREATE TABLE notes (id serial PRIMARY KEY, body text); INSERT INTO notes (body) VALUES ('written by 16');"
CREATE TABLE
INSERT 0 1

$ docker stop pg16
pg16

イメージを直接切り替えると失敗する

postgres:18 でバージョン 16 のデータを開きます(ここでは PGDATA で古いパスを指定し、タグを 16 から 18 に直接変更した場合を再現します)。

$ docker run --name pg18 -e POSTGRES_PASSWORD=secret -e PGDATA=/var/lib/postgresql/data -v pg16data:/var/lib/postgresql/data postgres:18 2>&1 | tail -n 3

2026-10-13 00:54:09.740 UTC [1] FATAL:  database files are incompatible with server
2026-10-13 00:54:09.740 UTC [1] DETAIL:  The data directory was initialized by PostgreSQL version 16, which is not compatible with this version 18.6 (Debian 18.6-1.pgdg13+2).

$ docker rm pg18
pg18

database files are incompatible with server:データディレクトリはバージョン 16 で初期化されているため、18.6 では使用できません。

エクスポートしてからインポート

最もシンプルで安全な方法は、旧バージョンの pg_dumpall ですべてのデータをエクスポートし、新しいバージョンの新しい Volume にインポートすることです。

$ docker start pg16
pg16

$ docker exec pg16 pg_dumpall -U postgres > upgrade.sql && ls -lh upgrade.sql
-rw-r--r--    1 root     root        3.4K Oct 13 00:54 upgrade.sql

$ docker run -d --name pg18 -e POSTGRES_PASSWORD=secret -v pg18data:/var/lib/postgresql postgres:18
ec651837b76a0c9cc8b2468ec5a2ff4002334dcf015514ef94490a6c38cfe73d

$ docker exec -i pg18 psql -U postgres -q < upgrade.sql
ERROR:  role "postgres" already exists
 set_config
------------

(1 row)

 set_config
------------

(1 row)

 setval
--------
      1
(1 row)


$ docker exec pg18 psql -U postgres -c "SHOW server_version;" -c "SELECT * FROM notes;"
        server_version
-------------------------------
 18.6 (Debian 18.6-1.pgdg13+2)
(1 row)

 id |     body
----+---------------
  1 | written by 16
(1 row)


$ rm upgrade.sql
  • インポート時の ERROR: role "postgres" already exists は無視できます。新しいバージョン 18 のコンテナには postgres ユーザーがすでに作成されており、pg_dumpall の出力でもう一度作成しようとしているためです。
  • 最後にバージョンが 18.6 であることと、バージョン 16 で書き込んだ written by 16 のデータが残っていることを確認します。
  • 新しいコンテナの Volume は /var/lib/postgresql(バージョン 18 の新しいパス)にマウントされていることに注意してください。

データとアプリケーションが正常に動作することを確認してから、古いコンテナと Volume を削除します。データ量が非常に多く、長時間の停止を許容できない場合は、pg_upgrade や論理レプリケーション(logical replication)を検討できますが、手順はかなり複雑なので、まずテスト環境で練習してください。

まとめ

  • PostgreSQL 18 の Volume は /var/lib/postgresql にマウントします。
  • ヘルスチェックには pg_isready -h 127.0.0.1 を使います。
  • コンテナ内の接続は trust で、外部から接続するにはパスワードが必要です。
  • メジャーバージョンのアップグレード:旧バージョンの pg_dumpall でエクスポートし、新しいバージョンの新しい Volume にインポートします。

練習問題

練習 1:psql を使って app データベースにテーブル notes を作成し、\dt で確認してください。

解答
docker compose exec db psql -U app -c "CREATE TABLE notes (id serial PRIMARY KEY, body text);"
docker compose exec db psql -U app -c "\dt"

練習 2:カスタム形式(-Fc)のバックアップとプレーンテキストの SQL には、どのような違いがありますか?

解答

カスタム形式は圧縮されており、復元には pg_restore を使います。一部のテーブルだけを復元することもできます。プレーンテキストはそのまま読めて、psql でインポートできます。

よくある質問

postgres:18を起動するとすぐ終了するのはなぜですか?

18では /var/lib/postgresql をマウントする必要があります。古い /var/lib/postgresql/data をマウントすると、互換性のないディレクトリが検出されて終了します。実際の動作はこの章で確認します。

マイナーバージョンの更新(18.5 → 18.6)はどうすればよいですか?

新しいイメージを取得してコンテナを再作成します:docker compose pull db && docker compose up -d db。エクスポートとインポートが必要なのはメジャーバージョンの更新だけです。

Windowsで pg_restore が失敗するのはなぜですか?

PowerShellは < をサポートせず、5.1の > はバイナリバックアップを壊します。コンテナ内で pg_dump -f を使ってファイルを作成し、docker compose cp でコピーします。この章ではその方法を紹介します。

更新日 2026年10月14日