GitHub ActionsでPostgreSQLを使ったCIを組むなら、結論は「service containerでPostgreSQLを起動し、ヘルスチェックで起動完了を待ってからマイグレーションとテストを流す」です。十数行のYAMLを足すだけで、プルリクエストのたびに本物のデータベースで結合テストまで自動実行できます。
この記事では、コピーして使える最小構成のYAMLから、ポートやホスト名の指定ルール、CIを速くする設定、よくあるエラーの直し方、Self-hosted Runnerを選ぶときの注意点までを順番に解説します。バージョンや料金は2026年10月時点の公式情報で確認した内容です。
- service container・ランナー直起動・Self-hosted Runnerのどれを選ぶべきか
- そのまま動く
ci-postgres.ymlと、各行の意味 - 「localhostなのか、postgresなのか」で迷わない接続先の決め方
- ECONNREFUSEDや
role "root" does not existなどの定番エラーの原因と対処 - 無料枠・同時実行数・料金の最新の数字
GitHub Actions×PostgreSQLをCIに組み込む理由:DBが動く“本番同等”テスト環境でバグを未然に防ぐ
「ユニットテストは通るのに、本番投入したら N+1 クエリで500エラー……」──そんな悲劇を回避する最短ルートは、CI で本物の Postgres を立ち上げて結合テストまで自動化することです。
GitHub Actions には service container という仕組みがあり、わずか十数行の YAML で Postgres をジョブごとに自動起動できます。
ジョブ終了後はコンテナごと破棄されるため、後片付けも不要です。さらにプライベートリポジトリでもGitHub Free は月2,000分、GitHub Pro は月3,000分までは追加コストなしで使えるので、個人開発ならまず無料の範囲で収まります。パブリックリポジトリなら、標準のGitHubホストランナーは無料です。
PostgreSQL を CI に組み込むメリット
- 本番と同一バージョンで検証:
postgres:18-alpineのようにタグでメジャーバージョンを固定すれば、バージョン不一致の事故を防げます。マイナーバージョンまで揃えたい場合はpostgres:18.6-alpineのように指定します。 - マイグレーション忘れを撲滅:ワークフロー内で空のDBにマイグレーションを毎回流すので、スキーマ差分の取りこぼしをPRの時点で検知できます。
- 並列ジョブごとに独立した DB:ジョブごとに専用のコンテナが立つため、PR どうしのデータ衝突が起きず、レビューフローがスムーズです。
- ローカル依存ゼロ:手元に Postgres を入れていない人でも、プッシュすれば同じ条件でテスト結果を確認でき、オンボーディングが速くなります。
- SQLiteやモックでは拾えない差を検出:JSONB、配列型、
ON CONFLICT、トランザクション分離レベルなど、PostgreSQL固有の挙動はPostgreSQLでしか確かめられません。
service container/VM 直起動/Self-hosted Runner 比較
GitHub ActionsでPostgreSQLを用意する方法は大きく3つあります。迷ったらservice containerを選んでおけば問題ありません。
| 方式 | 起動の手間 | バージョン指定 | データ保持 | 向くケース |
|---|---|---|---|---|
| service container | YAMLに書くだけ(イメージの取得と起動を自動で実施) | イメージのタグで自由に指定 | ジョブ終了で削除 | ユニット〜統合テスト全般 |
| VM 直起動 | ランナーに入っているPostgreSQLをsystemctlで起動 | ランナーイメージ任せ(Ubuntu 24.04は16系) | ジョブ終了で削除 | Dockerを使えない・使いたくない場合 |
| Self-hosted Runner | ランナー側で常駐させる | 自分で管理 | 永続可 | 重量級 E2E/社内ネットワーク内のリソースが必要な場合 |
Self-hosted Runner は構成次第で高速にできますが、OS更新やパッケージ衝突を自前で管理する必要があります。社内ネットに直接接続する場合はファイアウォールや IAM 制御も忘れずに。
なお、service container はDockerコンテナとして動くため、Linuxランナーでしか使えません。runs-on に windows-latest や macos-latest を指定したジョブでは使えないので、DBを使うテストはUbuntuのジョブに寄せましょう。
まずは動かす:GitHub Actions+PostgreSQLの最小構成YAML
.github/workflows/ci-postgres.yml を下記のように用意しましょう。Node.jsのプロジェクトを例にしていますが、services の部分はどの言語でも共通です。
name: CI with Postgres
on:
push:
branches: [main]
pull_request:
jobs:
test:
runs-on: ubuntu-latest
timeout-minutes: 15
services:
postgres:
image: postgres:18-alpine
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: myapp_test
ports:
# ホスト側ポートをあえて指定しないことで
# 空いているポートが自動で割り当てられる
- 5432
options: >-
--health-cmd "pg_isready -U postgres -d myapp_test"
--health-interval 10s
--health-timeout 5s
--health-retries 5
env:
DB_HOST: 127.0.0.1
DB_USER: postgres
DB_PASSWORD: postgres
DB_NAME: myapp_test
steps:
- uses: actions/checkout@v6
- name: Set up Node
uses: actions/setup-node@v7
with:
node-version: '24'
cache: npm
- name: Export DB port
# 自動割り当てされたポート番号を以降のステップに渡す
run: echo "DB_PORT=${{ job.services.postgres.ports[5432] }}" >> "$GITHUB_ENV"
- name: Install deps, migrate & test
run: |
npm ci
npm run migrate # ここで DB が出来ている想定
npm test
上記のポイントは 127.0.0.1 と動的ポートです。Node.js 17以降は localhost の名前解決結果をOSが返した順のまま使うため、環境によってはIPv6の ::1 へ先につなぎに行って接続に失敗することがあります。明示的に 127.0.0.1 を指定しておけば、この問題を避けられます。
自動割り当てポートは ${{ job.services.postgres.ports[5432] }} の形で取り出せるので、固定 5432 を前提にしない運用が安全です。もちろん 5432:5432 と固定で書いても動きますが、Self-hosted Runner のように同じマシンで複数ジョブが並ぶ環境では、ポートの取り合いで失敗する原因になります。
YAMLの各設定の意味
| 設定 | 役割 |
|---|---|
image | Docker Hubの公式イメージとタグ。タグを省略すると latest になり、新しいメジャーバージョンが出た日に突然バージョンが上がるので、必ず指定します |
POSTGRES_PASSWORD | スーパーユーザーのパスワード。公式イメージでは必須で、未設定だとコンテナが初期化に失敗します |
POSTGRES_USER / POSTGRES_DB | 作成するユーザー名と、最初に作るデータベース名。省略時はどちらも postgres |
ports | コンテナのポートをランナー(ホスト)側へ公開する指定 |
options の --health-* | pg_isready でDBが接続を受け付けるまで待つ設定。これがあると、GitHub Actionsはコンテナがhealthyになってからステップを開始します |
timeout-minutes | ジョブの打ち切り時間。DB待ちでハングしたときに、無料枠を使い切るのを防ぎます(未指定時の上限は6時間) |
ひとつ注意したいのが、job.services はジョブ直下の env: では参照できない点です。job コンテキストが使えるのはステップの中だけなので、上の例ではステップ内で $GITHUB_ENV に書き出し、後続のステップから DB_PORT として読めるようにしています。ステップごとの env: に直接書く方法でも構いません。
テスト用DBのパスワードをYAMLに直書きしていますが、このコンテナはジョブの中だけで生きて消える使い捨てのDBなので問題ありません。逆に、本番やステージングのDBへつなぐ認証情報は必ずSecretsに入れてください。
接続先は「ジョブをどこで動かすか」で変わる
GitHub ActionsでPostgreSQLにつながらない原因で特に多いのが、ホスト名の指定ミスです。ジョブをランナー上で直接動かすのか、container: を指定してコンテナの中で動かすのかで、接続先が変わります。
| ジョブの実行場所 | ホスト名 | ポート | ports の指定 |
|---|---|---|---|
ランナー上で直接(container: なし) | 127.0.0.1(localhost) | ホスト側に割り当てたポート | 必要 |
コンテナ内(container: あり) | サービス名(例:postgres) | 5432 | 不要 |
コンテナ内でジョブを動かす場合、ジョブのコンテナとservice containerは同じDockerネットワークに入り、services の下に書いたキー名がそのままホスト名になります。
jobs:
test:
runs-on: ubuntu-latest
container: node:24-bookworm-slim
services:
postgres:
image: postgres:18-alpine
env:
POSTGRES_PASSWORD: postgres
POSTGRES_DB: myapp_test
options: >-
--health-cmd "pg_isready -U postgres"
--health-interval 10s
--health-timeout 5s
--health-retries 5
env:
DB_HOST: postgres # サービス名がそのままホスト名
DB_PORT: 5432
steps:
- uses: actions/checkout@v6
- run: npm ci
- run: npm test
この形で DB_HOST を localhost にすると、ジョブ用コンテナ自身を指してしまうので接続できません。「ローカルのdocker composeでは動くのにCIだけ落ちる」ときは、まずこの表を確認してみてください。
フレームワーク別:接続情報の渡し方
接続情報を1本のURLで受け取るフレームワークでは、DATABASE_URL を組み立てて渡すのが簡単です。Rails、Prisma、Symfony(Doctrine)などはこの形式に対応しています。
- name: Run tests
env:
DATABASE_URL: postgresql://postgres:postgres@127.0.0.1:${{ job.services.postgres.ports[5432] }}/myapp_test
run: npm test
- Rails:
DATABASE_URLがあればconfig/database.ymlより優先されます。bin/rails db:schema:loadかdb:migrateをテスト前に実行します。 - Laravel:
DB_CONNECTION=pgsqlとDB_HOST/DB_PORT/DB_DATABASE/DB_USERNAME/DB_PASSWORDを環境変数で渡し、php artisan migrateを流します。 - Symfony:
DATABASE_URLの末尾に?serverVersion=18&charset=utf8を付け、php bin/console doctrine:migrations:migrate --no-interactionを実行します。 - Django:
settings.pyのDATABASESで環境変数を読む形にしておけば、テスト用DBはDjangoが自動で作成します。
拡張機能や初期データを入れたいとき
公式イメージには /docker-entrypoint-initdb.d に置いたSQLを初回起動時に実行する仕組みがありますが、service containerはリポジトリをチェックアウトする前に起動するため、リポジトリ内のSQLファイルをここへ渡すことができません。初期化はステップの中で psql を実行するのが確実です。UbuntuのGitHubホストランナーには psql が最初から入っています。
- name: Prepare database
env:
PGPASSWORD: postgres
run: |
psql -h 127.0.0.1 -p "$DB_PORT" -U postgres -d myapp_test \
-c 'CREATE EXTENSION IF NOT EXISTS "uuid-ossp";' \
-c 'CREATE EXTENSION IF NOT EXISTS pg_trgm;'
psql -h 127.0.0.1 -p "$DB_PORT" -U postgres -d myapp_test -f db/seed.sql
uuid-ossp や pg_trgm のように公式イメージへ同梱されている拡張は、これだけで有効になります。PostGISやpgvectorのように同梱されていない拡張を使う場合は、image をその拡張入りのイメージに差し替えてください。
Docker を使わず VM 直起動するパターン
Docker に制限がある環境では、ランナーのVM上でPostgreSQLを直接動かす方法もあります。UbuntuのGitHubホストランナーにはPostgreSQLがあらかじめインストールされており(Ubuntu 24.04のイメージは16系)、サービスが停止した状態になっているので、起動するだけで使えます。
- name: Start preinstalled PostgreSQL
run: |
sudo systemctl start postgresql.service
pg_isready
sudo -u postgres psql -c "ALTER USER postgres PASSWORD 'postgres';"
sudo -u postgres createdb myapp_test
ただし、この方法はバージョンをランナーイメージに握られます。ubuntu-latest が指すOSは定期的に切り替わり、2026年11月にはUbuntu 26.04へ移行すると案内されています。同梱されるPostgreSQLのバージョンもそのタイミングで変わり得るので、直起動を使うなら runs-on: ubuntu-24.04 のようにOSを固定しておきましょう。別のバージョンをAPTで入れることもできますが、リポジトリ追加やバージョン固定を自前スクリプトで管理することになり、メンテナンスコストは高めです。CI のボトルネック分析後に “どうしても必要” となるまでは service container がおすすめです。
PostgreSQLのバージョンはどう選ぶ?固定の仕方と複数バージョンでのテスト
CIのPostgreSQLは、本番で動いているメジャーバージョンに合わせるのが基本です。2026年10月時点でコミュニティがサポートしているのは14〜18で、最新の安定版は18系です(19はベータ版の段階)。14は2026年11月にサポートが終了します。
| メジャーバージョン | 初回リリース | サポート終了 |
|---|---|---|
| 18 | 2025年9月 | 2030年11月 |
| 17 | 2024年9月 | 2029年11月 |
| 16 | 2023年9月 | 2028年11月 |
| 15 | 2022年10月 | 2027年11月 |
| 14 | 2021年9月 | 2026年11月 |
ライブラリやOSSのように複数バージョンをサポートしたい場合や、本番のバージョンアップ前に互換性を確かめたい場合は、matrix でイメージのタグを切り替えると、同じテストを複数バージョンに対して並列で流せます。
jobs:
test:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
postgres: ['16', '17', '18']
services:
postgres:
image: postgres:${{ matrix.postgres }}-alpine
env:
POSTGRES_PASSWORD: postgres
POSTGRES_DB: myapp_test
ports:
- 5432
options: >-
--health-cmd "pg_isready -U postgres"
--health-interval 10s
--health-timeout 5s
--health-retries 5
fail-fast: false を付けておくと、1つのバージョンで失敗しても残りのジョブが止まらず、「17では通るが18で落ちる」といった切り分けがしやすくなります。
GitHub ActionsのPostgreSQL CIを高速化するベストプラクティス
Postgres コンテナ自体は軽量でも、マイグレーションやフィクスチャ投入で1〜2分かかることがあります。効果が出やすい順に見直していきましょう。
- 軽いイメージを使う:
-alpineタグのイメージはサイズが小さく、毎回のイメージ取得が短く済みます。ただしAlpine版はmuslのロケール実装を使うため、文字列の並び順(照合順序)がDebian版と変わることがあります。ソート結果を厳密に検証するテストがある場合は、本番と同じ系統のイメージを選んでください。 - 依存パッケージをキャッシュする:
actions/setup-nodeのcache: npmのように、言語ごとのセットアップアクションが持つキャッシュ機能を有効にします。DBより依存インストールのほうが時間を食っていることは珍しくありません。 - ロケールとエンコーディングを固定する:
POSTGRES_INITDB_ARGS: "--encoding=UTF8 --locale=C"を指定すると、環境によらず同じ並び順でテストできます。POSTGRES_INITDB_ARGSはinitdbに引数を渡すための環境変数です。 - 巨大な初期データを毎回ロードしない:テストに不要な大きなCSVやダンプは読み込まず、必要最小限のフィクスチャに絞ります。どうしても必要なデータはリポジトリに置かず、外部ストレージから取得してキャッシュする形にします。
- テストのシャーディング:
matrix戦略でテストを複数ジョブに分割して並列化します。標準のGitHubホストランナーの同時実行ジョブ数は、Freeで20、Proで40、Teamで60です(2026年10月時点)。ジョブごとに別のPostgresコンテナが立つので、DBの取り合いは起きません。 - マイグレーションよりスキーマのロードを使う:履歴が長いプロジェクトでは、マイグレーションを1本ずつ流すより、スキーマダンプを一括で読み込むほうが速くなります。マイグレーション自体の検証は、別の軽いジョブで1回だけ流せば十分です。
テスト専用DBなら耐久性の設定を切る
CIのDBはジョブが終われば捨てるものなので、ディスクへの確実な書き込みを保証する設定は不要です。service container には起動コマンドの引数を渡す項目がないため、起動後に ALTER SYSTEM で設定を書き換えて再読み込みします。
- name: Tune Postgres for tests
env:
PGPASSWORD: postgres
run: |
psql -h 127.0.0.1 -p "$DB_PORT" -U postgres -d myapp_test \
-c "ALTER SYSTEM SET fsync = off;" \
-c "ALTER SYSTEM SET synchronous_commit = off;" \
-c "ALTER SYSTEM SET full_page_writes = off;" \
-c "SELECT pg_reload_conf();"
書き込みの多いテストスイートほど効果が出ます。言うまでもなく、本番や消えては困るデータを持つDBでは絶対に使わない設定です。効果はプロジェクトによって差があるので、導入前後でジョブの所要時間を比べてから採用を決めてください。
無料枠と料金を把握しておく
高速化は、そのまま利用時間の節約にもなります。2026年10月時点のGitHub公式ドキュメントに基づく、プライベートリポジトリの無料枠は次のとおりです。
| プラン | 無料の実行時間(月) | 同時実行ジョブ数 |
|---|---|---|
| GitHub Free | 2,000分 | 20 |
| GitHub Pro | 3,000分 | 40 |
| GitHub Team | 3,000分 | 60 |
| GitHub Enterprise Cloud | 50,000分 | 500 |
- 無料枠を超えた分は従量課金で、Linuxの標準ランナー(2コア)は1分あたり0.006ドルです。GitHubホストランナーの単価は2026年1月に引き下げられました。
- WindowsやmacOSのランナーはLinuxより単価が高く設定されています。DBを使うテストはLinuxでしか動かせないので、この点でもLinuxに寄せるのが合理的です。
- パブリックリポジトリでは、標準のGitHubホストランナーは無料で使えます(larger runnerは課金対象)。
- service container を使っても追加料金はかかりません。課金の対象はあくまでジョブの実行時間です。
GitHub Actions×PostgreSQLでよくあるエラーと安全なリセット方法
つまずきやすいエラーを、原因と対処のセットでまとめます。
ECONNREFUSED/Connection refused で接続できない
コンテナが起動し切る前に接続しているか、接続先のホスト名・ポートが間違っている可能性が高いです。次の順で確認します。
optionsに--health-cmdを書いているか。書いていないと、DBの準備ができる前にステップが走ります。- ランナー上で直接動かすジョブなのに
portsを書き忘れていないか。 container:を使うジョブで、ホスト名をlocalhostにしていないか(正しくはサービス名)。- 動的ポートを使っているのに、アプリ側が5432固定で接続していないか。
初期化に時間がかかる構成では、--health-retries を 5→10 に増やすと解消することもあります。
FATAL: role “root” does not exist がログに出続ける
ヘルスチェックの pg_isready にユーザーを指定していないと、コンテナ内のOSユーザー名(root)で接続を試みるため、Postgresのログにこのメッセージが繰り返し記録されます。--health-cmd "pg_isready -U postgres" のように -U でユーザーを指定すれば消えます。
同じ理屈で、ステップ内の psql に -U を付け忘れると role "runner" does not exist になります。ランナーのOSユーザーが runner だからです。
パスワード認証失敗(password authentication failed)
.env と CI 環境変数のダブル管理ミスが典型です。services の POSTGRES_PASSWORD と、アプリに渡している DB_PASSWORD や DATABASE_URL が一致しているか確認しましょう。リポジトリにコミットされた .env.test が環境変数より優先されて、古い値で接続しているケースもよくあります。
Secretsを使っている場合は、フォークからのプルリクエストにはSecretsが渡されない点にも注意が必要です。値が空文字になり、認証失敗として現れます。使い捨てのテストDBであれば、Secretsを使わず固定値にしておくほうがトラブルになりません。
サービスコンテナの初期化に失敗する/database does not exist
- コンテナが起動直後に落ちる:
POSTGRES_PASSWORDが未設定だと、公式イメージは初期化を中止します。ジョブのログにある「Initialize containers」を開くと、コンテナ側のエラーメッセージを確認できます。 - database “xxx” does not exist:
POSTGRES_DBとアプリ側のDB名が食い違っています。POSTGRES_USERだけを変えてPOSTGRES_DBを省略すると、DB名もユーザー名と同じになる点に注意してください。 - macOS/Windowsのジョブで動かない:前述のとおり、service container はLinuxランナー専用です。
テスト間でデータ残骸が残るときのリセット方法
service container はジョブごとに作り直されるので、ジョブをまたいでデータが残ることはありません。問題になるのは、1つのジョブ内でテスト同士がデータを汚し合うケースです。
スキーマ丸ごと消す場合は DROP SCHEMA public CASCADE; CREATE SCHEMA public; が便利ですが、アプリ側マイグレーションツールが Public スキーマ外を参照する場合は壊れる恐れがあります。また、publicスキーマに入れた拡張機能も一緒に消えるので、作り直しが必要です。事前にロールバックテストし、必要なら次のような方法を使う方が安全です。
- テストごとにトランザクションをロールバックする:多くのテストフレームワークが標準で備えている方式で、最も高速です。
TRUNCATE ... RESTART IDENTITY CASCADEでテーブルを空にする:スキーマは残したまま、データと連番だけを初期化できます。- DB Cleaner 系のライブラリを使う:上の2つを状況に応じて切り替えてくれます。
pg_restore --cleanでダンプから戻す:決まった初期状態へ確実に戻したいE2Eテスト向きです。
Self-hosted Runner でPostgreSQLを使うときの注意点
自己ホストランナーはキャッシュ済みのコンテナイメージや常駐 DB を使えるぶん速くできますが、メリットとトレードオフがはっきりしています。
PostgreSQL を永続化する場合のポイントとしては、コンテナ内のデータディレクトリをホスト側にマウントするのが基本です。
例:
docker run -d \
--name my-postgres \
-e POSTGRES_PASSWORD=postgres \
-v /srv/postgres:/var/lib/postgresql \
postgres:18
このように-vオプションでホストに保存すれば、コンテナの再作成や再起動後もデータが保持されます。ここで気を付けたいのがマウント先です。公式イメージはPostgreSQL 18から、マウント先が /var/lib/postgresql に変わりました(データ本体はその下のバージョン別ディレクトリに置かれます)。17以前のイメージでは従来どおり /var/lib/postgresql/data にマウントします。17以前で /var/lib/postgresql にマウントすると、コンテナを作り直したときにデータが残りません。
また、メジャーバージョンを上げるときは、イメージのタグを変えるだけではデータを引き継げません。pg_upgrade か、pg_dump で書き出して新バージョンへリストアする手順が必要です。バックアップにはpg_dumpやpgBackRestの活用もおすすめです。
- セキュリティ:GitHubは、Self-hosted Runner をプライベートリポジトリだけで使うよう推奨しています。パブリックリポジトリでは、フォークからのプルリクエスト経由で、ランナーのマシン上で任意のコードを実行される恐れがあるためです。どうしても使う場合は、ジョブごとに使い捨ての環境で隔離し、プライベートネットワークに閉じること。
- ジョブ間のデータ汚染:常駐DBを複数ジョブで共有すると、前のジョブの残骸や同時実行中の別ジョブの書き込みでテストが不安定になります。ジョブごとにDB名を変える(例:
myapp_test_${{ github.run_id }})か、Self-hosted Runner でも service container を使ってジョブ単位で作り直すのが安全です。 - リソース競合:複数リポジトリが同じ Runner を共有し、CPU/I/O が飽和するとテストが不安定化。Prometheus + Grafana などでの監視を用意しておきましょう。
- 運用コスト:OS アップデート、Postgres バージョン更新、SELinux/AppArmor 設定など “インフラ運用業” が増える点に注意しましょう。
- 料金の動向:2026年10月時点で、Self-hosted Runner の利用自体にGitHub側の料金はかかりません。ただしGitHubは2025年12月に、プライベートリポジトリでの利用へ1分あたり0.002ドルを課金する計画を発表し、その後に延期しています。長期で採用するなら、公式の料金ページを定期的に確認しておくと安心です。
CI/CDやインフラまで見られるエンジニアは、転職市場でも評価されやすいスキルセットです。キャリアの選択肢を広げたい方は、こちらの記事も参考にしてください。
レバテックキャリアの評判は?ITエンジニア転職のメリット・注意点【2026年】GitHub Actions×PostgreSQLのよくある質問
ヘルスチェックの代わりに sleep で待ってもいい?
動きはしますが、おすすめしません。待ち時間が短ければたまに失敗する不安定なテストになり、長ければ毎回ムダな時間を払うことになります。--health-cmd を使えば、準備ができた時点ですぐ次へ進みます。
docker compose を使う方法と、どちらがいい?
ローカル開発ですでに compose.yaml を使っていて、CIでもまったく同じ構成を再現したいなら、ステップ内で docker compose up -d --wait を実行する方法も有力です。初期化SQLのマウントや起動コマンドの引数指定など、service container ではできない設定も使えます。一方で、DBだけあれば足りるならservice containerのほうが記述が少なく、後片付けも自動です。
ランナーに入っている psql とサーバーのバージョンが違っても大丈夫?
SQLの実行やファイルの読み込みといった用途であれば、基本的に問題ありません。接続時にバージョン違いの警告が表示されることがあります。pg_dump だけは、サーバーより古いバージョンのクライアントでは実行できないので、ダンプを取りたい場合は docker exec でコンテナ内の pg_dump を使ってください。
1つのジョブで複数のDBやRedisも一緒に使える?
使えます。services の下に postgres と並べて redis などを追加するだけです。それぞれのキー名がホスト名になり、ポートも job.services.redis.ports[6379] のようにサービスごとに取得できます。
まとめ:Postgres 付き GitHub Actions で“データベースごと安心”な CI を
数行の YAML を追加するだけで、データベース由来のバグを PR 時点で潰せる開発体験が手に入ります。押さえておきたいポイントは次の5つです。
- まずは service container。イメージのタグで本番と同じメジャーバージョンに固定する
--health-cmd "pg_isready -U postgres"で起動完了を待つ- ランナー上なら
127.0.0.1+割り当てポート、コンテナ内ならサービス名+5432で接続する - 遅くなってきたら、キャッシュ・並列化・耐久性設定の順に見直す
- Self-hosted Runner は、セキュリティと運用負荷を秤にかけてから選ぶ
まずは service container で小さく始め、テストが遅く感じたら並列化や自己ホストに進む──このステップアップ型が現場では失敗しにくい王道パターンです。今日のプルリクからぜひ導入してみてください。
DB付きのCIが整ったら、次はブラウザを動かすE2Eテストの自動化にも挑戦してみてください。
Pantherでスクリーンショット&デバッグ自動化|PHP製E2Eテスト環境を完全ガイド








