GitHub Actionsでサービスコンテナとしてデータベースを起動して通信してみる

GitHub Actionsでサービスコンテナとしてデータベースを起動して通信してみる

GitHub Actionsジョブランナーからサービスコンテナとの通信は、ポートマッピングしたホストから通信とブリッジネットワークでのコンテナ間通信がある
2025.05.07

GitHub Actionsにはサービスコンテナという機能があり、データベースやキャッシュサーバーなど、ワークフローが依存するサービスをコンテナ起動させる仕組みがあります。

name: PostgreSQL service example on: push jobs: # Label of the container job container-job: # Containers must run in Linux based operating systems runs-on: ubuntu-latest # Docker Hub image that `container-job` executes in container: node:20-bookworm-slim # Service containers to run with `container-job` services: # Label used to access the service container postgres: # Docker Hub image image: postgres # Provide the password for postgres env: POSTGRES_PASSWORD: postgres # Set health checks to wait until postgres has started options: >- --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 

ランナージョブの実行方法は2通りあります

  1. ランナーマシン上でジョブを実行
  2. コンテナ内でジョブを実行

ローカル開発で、データベースだけコンテナ化した場合に相当するのが 「1.ランナーマシン上でジョブを実行」 の構成です。
ポートマッピングでDockerホスト環境からコンテナと通信できるように設定します。

Docker Compose のようにまるっとコンテナ化するのが 「2.コンテナ内でジョブを実行」 の構成です。
同じユーザー定義・ブリッジ・ネットワークでサービス名からコンテナ間通信するため、ネットワーク的にシンプルです。

Pythonからサービスコンテナで起動したPostgreSQLと通信する場合を例に、それぞれの構築例を紹介します。

本記事に対応するGitHubレポジトリを公開しています。

GitHub - quiver/github-actions-service-contaner-sample-python

1. ランナーマシン上でジョブを実行

PostgreSQLをサービスコンテナとして起動し、ランナー実行ホスト環境からコンテナと通信できるようにポートマッピング設定(ports)を追加します。

ランナーマシンからサービスコンテナと通信する場合のワークフローファイル

name: PostgreSQL service container running jobs in runner machines on: push jobs: # Label of the container job container-job: # Containers must run in Linux based operating systems runs-on: ubuntu-latest # Service containers to run with `container-job` services: # Label used to access the service container postgres: # Docker Hub image image: postgres:17 # Provide the password for postgres env: POSTGRES_PASSWORD: postgres # Set health checks to wait until postgres has started options: >- --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 ports: # Maps tcp port 5432 on service container to the host - 5432:5432 steps: # Downloads a copy of the code in your repository before running CI tests - name: Check out repository code uses: actions/checkout@v4 - name: Install dependencies run: pip install -r requirements.txt - name: Connect to PostgreSQL run: python client.py env: # The hostname used to communicate with the PostgreSQL service container POSTGRES_HOST: localhost # The default PostgreSQL port POSTGRES_PORT: 5432 

より具体的には services のブロックの最後の次の箇所が該当します。

 ports: # Maps tcp port 5432 on service container to the host - 5432:5432 

アプリケーション(Dockerホスト)からは、ローカルホストにexposeしたポートでPostgreSQLと通信します。より具体的には次の env が該当します。

 - name: Connect to PostgreSQL run: python client.py env: # The hostname used to communicate with the PostgreSQL service container POSTGRES_HOST: localhost # The default PostgreSQL port POSTGRES_PORT: 5432 

2. コンテナ内でジョブを実行

PostgreSQLをサービスコンテナとして起動し、ランナージョブもコンテナ起動し、サービスコンテナとコンテナ間通信します。

サービスコンテナとコンテナ間通信する場合のワークフローファイル

name: PostgreSQL service container running jobs in containers on: push jobs: # Label of the container job container-job: # Containers must run in Linux based operating systems runs-on: ubuntu-latest # Docker Hub image that `container-job` executes in container: python:3.13-slim # Service containers to run with `container-job` services: # Label used to access the service container postgres: # Docker Hub image image: postgres:17 # Provide the password for postgres env: POSTGRES_PASSWORD: postgres # Set health checks to wait until postgres has started options: >- --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 steps: - name: Check out repository code uses: actions/checkout@v4 - name: Install dependencies run: pip install -r requirements.txt - name: Connect to PostgreSQL run: python client.py env: # The hostname used to communicate with the PostgreSQL service container POSTGRES_HOST: postgres # The default PostgreSQL port POSTGRES_PORT: 5432 

より具体的には、次の container: python:3.13-slim のように、ジョブを実行するコンテナイメージを指定します。

jobs: # Label of the container job container-job: # Containers must run in Linux based operating systems runs-on: ubuntu-latest # Docker Hub image that `container-job` executes in container: python:3.13-slim 

アプリケーション(ジョブコンテナ)からは、サービスコンテナの定義で利用したラベル名(postgres) でサービスコンテナと通信します。より具体的には次の env が該当します。

 - name: Connect to PostgreSQL run: python client.py env: # The hostname used to communicate with the PostgreSQL service container POSTGRES_HOST: postgres # The default PostgreSQL port POSTGRES_PORT: 5432 

疎通確認

PostgreSQLサービスコンテナと通信するPythonクライアントアプリケーションです。

環境変数でわたってくるPostgreSQLのホスト(POSTGRES_HOST)の中身が実行方式によって異なります。

import os import psycopg2 def main(): host = os.environ.get("POSTGRES_HOST") port = os.environ.get("POSTGRES_PORT") user = "postgres" password = "postgres" dbname = "postgres" conn = psycopg2.connect( host=host, port=port, user=user, password=password, dbname=dbname ) with conn.cursor() as cur: cur.execute("SELECT version()") result = cur.fetchone() print(f"PostgreSQL Version: {result[0]}") if __name__ == "__main__": main() 

GitHub Actionsのジョブ履歴から、期待通り実行されていることを確認しましょう

Run python client.py python client.py shell: /usr/bin/bash -e {0} env: POSTGRES_HOST: postgres POSTGRES_PORT: 5432 PostgreSQL Version: PostgreSQL 17.4 (Debian 17.4-1.pgdg120+2) on x86_64-pc-linux-gnu, compiled by gcc (Debian 12.2.0-14) 12.2.0, 64-bit 

設定ファイルの違い

  1. ランナーマシン上でジョブを実行
  2. コンテナ内でジョブを実行

の違いを設定ファイルの diff から確認します

@@ -6,8 +6,6 @@ container-job: # Containers must run in Linux based operating systems runs-on: ubuntu-latest - # Docker Hub image that `container-job` executes in - container: python:3.13-slim # Service containers to run with `container-job` services: @@ -24,6 +22,9 @@ --health-interval 10s --health-timeout 5s --health-retries 5 + ports: + # Maps tcp port 5432 on service container to the host + - 5432:5432 steps: - name: Check out repository code uses: actions/checkout@v4 @@ -35,6 +36,6 @@ run: python client.py env: # The hostname used to communicate with the PostgreSQL service container - POSTGRES_HOST: postgres + POSTGRES_HOST: localhost # The default PostgreSQL port POSTGRES_PORT: 5432 

diff ファイルで + となっている ランナーマシン上でジョブを実行方式 では、サービスコンテナをポートマッピングしてローカルホストから通信しています。

diff ファイルで- となっている コンテナでジョブを実行する方式 では、ジョブを実行するコンテナイメージを container で定義し、サービス名(postgres)でサービスコンテナと通信しています。

最後に

GitHub Actionsでサービスコンテナを利用する場合、ランナージョブとサービスコンテナの通信方式は2通りあります。

ジョブもコンテナとして実行させると、ネットワーク面含めて一貫してきれいになる一方で、アドオン的にデータベース等がサービスコンテナで必要になった場合は、従来のワークフローファイルを極力維持し、ランナーマシン上からサービスコンテナの見えるようにサービスコンテナを追加したほうが変更・影響範囲を小さくできると思います。

参考

この記事をシェアする

FacebookHatena blogX

関連記事