はじめに
タイトルの通り、GitHub Actions を使って Rails の自動テストを設定した際に、テスト前のテーブル作成時点で MySQL に接続できず、その後のテストが自動で実行できない状況が発生しました。
原因の特定と解決に時間がかかったため、備忘録として記事にまとめてみました。
環境
- Ruby:3.4.3
- Rails:8.0.3
- MYSQL:8.4.4
現象
下記の設定で、db:prepare(DB作成等のコマンド)を実行した際に、ActiveRecord::DatabaseConnectionErrorが発生し、ジョブが終了してしまいました。
test:
runs-on: ubuntu-latest
services:
mysql:
image: mysql
env:
MYSQL_ALLOW_EMPTY_PASSWORD: true
ports:
- 3306:3306
options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
steps:
〜割愛〜
- name: Setup DB
run: bin/rails db:prepare
env:
RAILS_ENV: test
DB_HOST: mysql
- name: Run tests
env:
RAILS_ENV: test
DB_HOST: mysql
run: bin/rspec
原因調査
原因調査として以下の内容を調査してみました。
-
Setup DBステップ実行前にsleepを入れて、MYSQLの起動ができているかを確認 -
pingやmysqlコマンドを使用してホストの接続確認
結果、接続先として指定している DB_HOST 環境変数の mysql が DNS で名前解決できず、エラーになっていました。ただし、公式ドキュメントには、サービスコンテナにはサービス名(この設定の場合mysql)でアクセスでき、ポートやIPの指定は不要と書かれています。
コンテナ内でジョブとサービスを実行すれば、ネットワークアクセスはシンプルになります。
サービスコンテナへは、ワークフロー中で設定したラベルを使ってアクセスできます。 サービスコンテナのホスト名は、自動的にラベル名にマップされます。 たとえば、redisというラベルでサービスコンテナを作成したなら、そのサービスコンテナのホスト名はredisになります。
公式ドキュメント:サービスコンテナについて
対策
サービスコンテナ側でポートを開放し、DB作成ジョブやテストジョブで使用するDB_HOST環境変数に127.0.0.0を指定することで解決しました。
test:
runs-on: ubuntu-latest
services:
mysql:
image: mysql
env:
MYSQL_ALLOW_EMPTY_PASSWORD: true
ports:
- 3306:3306
options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
steps:
〜割愛〜
- name: Setup DB
run: bin/rails db:prepare
env:
RAILS_ENV: test
DB_HOST: 127.0.0.0
- name: Run tests
env:
RAILS_ENV: test
DB_HOST: 127.0.0.0
run: bin/rspec
設定変更後、DBに接続できていることを確認できました。
おわりに
GitHub Actions で Rails の自動テストを実行する際は、サービスコンテナのホスト指定やポート指定に注意することで、DB 接続エラーを防ぐことができます。
DNS 名前解決の問題やコンテナ間ネットワークの挙動も踏まえて設定を確認することが重要だと感じました。
今回、サービス名での名前解決がうまくいかなかった原因については、今後さらに調査してみようと思います。もしご存知の方がいらっしゃれば、コメントで教えていただけると嬉しいです。
最後までご覧いただき、ありがとうございました。

