GitHub ActionsでPostgreSQLやRedisを使ったCIを回していると、「普段は通るのに、たまにだけ落ちる」が一番しんどいですよね。この記事は、GitHub Actions service containerの挙動で悩んでいる人に向けて、2026年4月アップデートで追加されたentrypoint/command上書きも含めて、今日から使える安定化手順をまとめました。読むと、起動待ち・接続先・再実行依存を切り分けて、再現性の高いCIに寄せられます。
こんな方におすすめ
- GitHub ActionsのDB系テストがたまに失敗して困っている方
postgresとlocalhostの使い分けで迷っている方- 再実行で押し切る運用から卒業したい方
- ラッパーイメージなしでservice containerを制御したい方
この記事でわかること
- 2026-04-02追加の
entrypoint/command上書き仕様 - PostgreSQL・Redisの公式準拠healthcheck設定
- job container実行とrunner実行の接続先設計
- 再実行50回上限時代のfail-fast運用の作り方
GitHub Actions service containerが不安定に見える3つの原因
最初に結論です。不安定の正体は「運」ではなく、設定の前提が揃っていないことです。GitHub Actionsは便利ですが、service containerは「コンテナが起動した」だけでは十分ではありません。アプリが接続できる状態になるまでの待機、どのホスト名に接続するか、失敗時の再実行ルールまで含めて設計してはじめて安定します。
- 起動順のズレ — DBコンテナが立ち上がっても、初期化が終わる前にテストが走ると失敗しやすいです。
- 接続先の混同 — job container実行なら
postgresやredis、runner直接実行ならlocalhostです。ここが逆だと名前解決エラーになります。 - 再実行頼み — 2026-04-10以降、workflow再実行は50回上限です。失敗をrerunで吸収する前提は持続しにくいです。
さらに、workflow 1回あたりのjobは最大256まで増やせるので、マトリクス運用では「小さな不安定」が一気に表面化します。つまり、失敗率1%でも母数が増えると体感はかなり悪くなります。先に土台を整えておくのが、結果的に最短です。
2026年4月アップデート|entrypoint/command上書きの要点
2026-04-02の更新で、service containerにentrypointとcommandをYAMLから直接書けるようになりました。公式Changelogはこちら、構文仕様はworkflow syntaxで確認できます。イメージを作り直さずに挙動を調整できるので、CI専用ラッパーイメージの保守コストが下がります。
| キー | 上書き対象 | よくある用途 | 注意点 |
|---|---|---|---|
command |
DockerのCMD | 起動オプション調整 | ENTRYPOINTはそのままです |
entrypoint |
DockerのENTRYPOINT | 起動バイナリ差し替え | 引数は別で渡します |
| 両方指定 | ENTRYPOINT + 引数 | etcdなど詳細制御 | commandはentrypointの引数として渡ります |
services:
mysql:
image: mysql:8
command: --sql_mode=STRICT_TRANS_TABLES --max_allowed_packet=512M
etcd:
image: gcr.io/etcd-development/etcd:v3.5.0
entrypoint: etcd
command: --listen-client-urls http://0.0.0.0:2379 --advertise-client-urls http://0.0.0.0:2379
公式ドキュメントでは、Composeと同じ命名・挙動で考えられると整理されています。イメージとしては「ローカルComposeで試した起動オプションを、そのままActionsに寄せやすくなった」ということです。
PostgreSQL CI安定化レシピ|healthcheckと接続先の使い分け
PostgreSQLの安定化で最初に見るべきは、実行方式です。jobをどこで走らせるかで、接続先が変わります。ここを曖昧にしたまま調整すると、設定を足しても失敗します。
| 実行方式 | 接続先 | ポート公開 | 向いている場面 |
|---|---|---|---|
| job container内で実行 | postgres |
不要 | Node/Pythonをコンテナで統一したい時 |
| runner上で直接実行 | localhost |
必要(5432:5432) | 標準ランナーで素早く回したい時 |
| self-hosted runner | 環境依存(基本はlocalhost) | 設計次第 | 既存ネットワーク制約がある時 |
services:
postgres:
image: postgres:16
env:
POSTGRES_PASSWORD: postgres
POSTGRES_DB: app_test
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
この10s / 5s / 5は公式チュートリアル準拠です(PostgreSQL例)。最初はこの値から始めて、DB初期化が重いプロジェクトだけ調整するのがおすすめです。いきなり再試行回数を増やすより、起動判定の精度を上げたほうが安定します。
DATABASE_HOST=postgresにして落ちるケースは本当に多いです。逆にjob container実行でlocalhostを使っても同じように詰まります。まず「どこでテストを実行しているか」を固定してから値を決めると早いです。
Redis CI安定化レシピ|軽量設定とタイムアウト設計
Redisも考え方は同じですが、さらにシンプルに安定化しやすいです。要点は、healthcheckを必ず入れることと、CI用の軽量起動に寄せることです。公式例もredis-cli pingでの監視を使っています(Redis例)。
services:
redis:
image: redis:7
command: --save "" --appendonly no
ports:
- 6379:6379
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5
command上書きで永続化を切ると、CIでは起動が軽くなります。もちろん本番設定をそのまま真似る必要はありません。CIは「テストに必要な最小構成」を狙うのがコツです。
- 接続先を固定 — runner実行なら
localhost:6379、job containerならredis:6379です。 - 待機失敗に上限を付ける — 無限待機を避け、30〜60秒で失敗に倒すと原因追跡が早くなります。
- ログを残す — 失敗時にサービスログを吐いておくと再現確認が1回で済みます。
つまり、Redisは「軽く起動して、早く失敗させる」設計が相性いいです。ここを徹底すると、flakeの体感がかなり下がります。
失敗パターン集と実運用テンプレート|再実行50回上限時代の設計
現場でよく詰まるポイントを先に潰しておくと、運用が楽になります。とくにservices.optionsで何でも解決しようとする設計は危険です。仕様上、--networkは非対応なので、ネットワーク制御をそこに逃がすとハマります。詳細は公式仕様を先に確認しておくと安心です。
- 名前解決エラー —
could not translate host name "postgres"は実行方式と接続先の不一致が典型です。 - 待機ループの長期化 — healthcheckなしでsleep連打すると、遅いのに原因が見えません。
- rerun依存 — 2026-04-10以降は50回上限なので、失敗を設計で減らす方が確実です。
jobs:
test:
runs-on: ubuntu-latest
timeout-minutes: 15
strategy:
fail-fast: true
matrix:
node: [20, 22]
services:
postgres:
image: postgres:16
env:
POSTGRES_PASSWORD: postgres
POSTGRES_DB: app_test
ports: ["5432:5432"]
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
redis:
image: redis:7
command: --save "" --appendonly no
ports: ["6379:6379"]
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5
運用で見るべき最小指標
- job失敗率(週次)
- rerun回数(50回上限に近づいていないか)
- 失敗理由の内訳(接続失敗/起動待ち/テストロジック)
CI整備を案件価値に変えたいなら、設定レビュー観点も武器になります。僕が受けているフリーランスエンジニアのキャリア相談でも、最近は「テストが安定している人のほうが評価される」という話が増えています。
設定を後回しにすると起きやすい3つの損失
service containerの前提を知らないまま運用すると、コードが悪くないのに「CIが不安定なチーム」という評価を受ける可能性があります。さらに、rerunを繰り返す運用はレビュー待ちを長くし、リリース速度を落とします。最後に、失敗原因の切り分け時間が積み上がると、改善より消火対応に時間を使う比率が増えます。つまり、知らないままだと品質より先に体力が削られます。
この記事を書いている理由
僕自身、2025年10月から福祉事業のIT全般を担当しつつ、テックビズ経由のAI×SaaS案件でもCIを継続運用しています。複数案件を並行すると、1回のflakeがそのままスケジュール遅延になります。結婚式Web招待状サービスで90日以上のログイン継続率を作れたのも、リリース後の品質運用を先に仕組み化したからです。だからこそ、再実行で祈る運用より、失敗しにくい設計を先に共有したいと思って書いています。
次のアクション
まずは1本のworkflowで、healthcheckと接続先ルールだけ先に統一してみてください。動いたらentrypoint/command上書きまで広げる流れが最短です。
今日からできるアクション
- PostgreSQL/Redisに公式準拠のhealthcheck(10s/5s/5)を入れる
- runner実行は
localhost、job container実行はサービス名に固定する - 運用で詰まったらフリーランスエンジニアのキャリア相談で状況を投げてもらえたら、改善の優先順位を一緒に整理します