Skip to main content

Docker サービス コンテナーとの通信

Docker サービス コンテナーを使って、データベース、Web サービス、メモリ キャッシュ、その他のツールをワークフローに接続する方法について説明します。

Docker サービス コンテナーとの通信

サービスコンテナは、ワークフロー中でアプリケーションをテストもしくは運用するのに必要になるかもしれないサービスをホストするための、シンプルでポータブルな方法を提供するDockerコンテナです。 たとえば、ワークフローでデータベースやメモリキャッシュへのアクセスを必要とする結合テストを実行する必要があるかもしれません。

サービスコンテナは、ワークフロー中のそれぞれのジョブに対して設定できます。 GitHub は、ワークフローで構成されたサービスごとに新しい Docker コンテナーを作成し、ジョブの完了時にサービス コンテナーを破棄します。 ジョブ内のステップは、同じジョブに含まれるすべてのサービスコンテナと通信できます。 ただし、複合アクション内でサービスコンテナーを作成して使用することはできません。

メモ

ワークフローで Docker コンテナー アクション、ジョブ コンテナー、またはサービス コンテナーが使われる場合は、Linux ランナーを使う必要があります。

  • GitHubホストランナーを使うなら、Ubuntuランナーを使わなければなりません。
  • セルフホストランナーを使っているなら、ランナーとしてLinuxマシンを使い、Dockerをインストールしておかなければなりません。

ワークフロー中のジョブは、直接ランナーマシン上で実行するようにも、Dockerコンテナ中で実行するようにも設定できます。 ジョブと、ジョブのサービスコンテナとの通信は、ジョブがランナーマシン上で直接実行されているか、コンテナ内で実行されているかによって異なります。

コンテナ内でのジョブの実行

コンテナーでジョブを実行すると、 GitHub は、Docker のユーザー定義ブリッジ ネットワークを使用してサービス コンテナーをジョブに接続します。 詳しくは、Docker ドキュメントの「ブリッジ ネットワーク ドライバー」を参照してください。

コンテナ内でジョブとサービスを実行すれば、ネットワークアクセスはシンプルになります。 サービスコンテナへは、ワークフロー中で設定したラベルを使ってアクセスできます。 サービスコンテナのホスト名は、自動的にラベル名にマップされます。 たとえば、redis というラベルでサービスコンテナを作成したなら、そのサービスコンテナのホスト名は redis になります。

サービスコンテナでポートを設定する必要はありません。 デフォルトで、すべてのコンテナは同じDockerネットワークの一部となってお互いにすべてのポートを公開し合い、Dockerネットワークの外部へはポートは公開されません。

ランナーマシン上でのジョブの実行

ランナーマシン上でジョブを直接実行する場合、localhost:<port>127.0.0.1:<port> を使ってサービスコンテナにアクセスできます。 GitHub は、サービス コンテナーから Docker ホストへの通信を有効にするようにコンテナー ネットワークを構成します。

ジョブがランナーマシン上で直接実行されている場合、Dockerコンテナ内で実行されているサービスは、ランナー上で実行しているジョブに対してデフォルトではポートを公開しません。 サービスコンテナ上のポートは、Dockerホストに対してマップする必要があります。 詳しくは、「Docker サービス コンテナーとの通信」をご覧ください。

サービスコンテナの作成

          `services` キーワードを使って、ワークフロー内のジョブの一部であるサービスコンテナを作成できます。 詳細については、「[`jobs.<job_id>.services`](/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idservices)」を参照してください。

この例では、redis という名前のジョブで container-job という名前のサービスが作成されます。 この例の Docker ホストは node:16-bullseye コンテナです。

YAML
name: Redis container 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:16-bullseye

    # Service containers to run with `container-job`
    services:
      # Label used to access the service container
      redis:
        # Docker Hub image
        image: redis

Dockerホストとサービスコンテナのポートのマッピング

ジョブがDockerコンテナ内で実行されるなら、ポートをホストあるいはサービスコンテナにマップする必要はありません。 ジョブがランナーマシン上で直接実行されるなら、必要なサービスコンテナのポートはホストランナーマシンのポートにマップしなければなりません。

サービスコンテナのポートは、ports キーワードを使って Docker ホストにマップできます。 詳細については、「jobs.<job_id>.services」を参照してください。

| ports の値 | 説明 | |------------------|--------------| | 8080:80 | コンテナのTCPのポート80をDockerホストのポート8080にマップします。 | | 8080:80/udp | コンテナのUDPポート80をDockerホストのポート8080にマップします。 | | 8080/udp | Docker ホストでランダムに選択したポートをコンテナーの UDP ポート 8080 にマップします。 |

          `ports` キーワードを使用してポートをマップする場合、GitHubは `--publish` コマンドを使用してコンテナーのポートを Docker ホストに発行します。 詳しくは、Docker ドキュメントの [Docker コンテナー ネットワーク](https://docs.docker.com/config/containers/container-networking/)に関するページを参照してください。

コンテナー ポートを指定したが Docker ホスト ポートを指定しなかった場合、コンテナー ポートは空きポートにランダムに割り当てられます。 GitHub は、サービス コンテナー コンテキストで割り当てられたコンテナー ポートを設定します。 たとえば redis サービスコンテナに対し、Docker ホストのポート 5432 を設定したなら、対応するコンテナのポートには job.services.redis.ports[5432] コンテキストを使ってアクセスできます。 詳しくは、「コンテキスト リファレンス」をご覧ください。

Redisのポートのマッピングの例

以下の例は、サービスコンテナ redis のポート 6379 を、Docker ホストのポート 6379 にマップします。

YAML
name: Redis Service Example
on: push

jobs:
  # Label of the container job
  runner-job:
    # You must use a Linux environment when using service containers or container jobs
    runs-on: ubuntu-latest

    # Service containers to run with `runner-job`
    services:
      # Label used to access the service container
      redis:
        # Docker Hub image
        image: redis
        #
        ports:
          # Opens tcp port 6379 on the host and service container
          - 6379:6379

イメージレジストリによる認証

イメージ レジストリで認証する必要がある場合は、サービス コンテナーの資格情報を指定できます。 これにより、プライベート レジストリのイメージを使用したり、DockerHub のレート制限を引き上げたりすることができます

Docker Hub と GitHubContainer registryを使用した認証の例を次に示します。

YAML
jobs:
  build:
    services:
      redis:
        # Docker Hub image
        image: redis
        ports:
          - 6379:6379
        credentials:
          username: ${{ secrets.dockerhub_username }}
          password: ${{ secrets.dockerhub_password }}
      db:
        # Private registry image
        image: ghcr.io/octocat/testdb:latest
        credentials:
          username: ${{ github.repository_owner }}
          password: ${{ secrets.ghcr_password }}

サービス コンテナーのエントリポイントとコマンドのカスタマイズ

既定では、サービス コンテナーは、Docker イメージで定義されたエントリポイントとコマンドを使用して実行されます。 これらのキーは、 entrypoint キーと command キーを使用してオーバーライドできます。 これは、カスタム ラッパー イメージを作成せずに、サービス (データベースなど) にフラグを渡すか、イメージエントリポイントを完全にスワップする必要がある場合に便利です。

          `command` キーは、イメージの既定のコマンド (`CMD`) をオーバーライドします。 ほとんどのシナリオでは、 `command`のみが必要です。イメージには既に適切なエントリ ポイントがあり、フラグを渡すだけで済みます。
YAML
services:
  mysql:
    image: mysql:8
    command: --sql_mode=STRICT_TRANS_TABLES --max_allowed_packet=512M
    env:
      MYSQL_ROOT_PASSWORD: test
    ports:
      - 3306:3306
          `entrypoint` キーは、イメージの`ENTRYPOINT`をオーバーライドします。 それを `command` と組み合わせて、カスタム エントリポイントに引数を渡すことができます。
YAML
services:
  etcd:
    image: quay.io/coreos/etcd:v3.5.17
    entrypoint: etcd
    command: >-
      --listen-client-urls http://0.0.0.0:2379
      --advertise-client-urls http://0.0.0.0:2379
    ports:
      - 2379:2379

名前付けと動作は Docker Compose と一致します。 詳細については、jobs.<job_id>.services.<service_id>.command および jobs.<job_id>.services.<service_id>.entrypoint を参照してください。

参考資料

  •         [AUTOTITLE](/actions/using-containerized-services/creating-redis-service-containers)
    
  •         [AUTOTITLE](/actions/using-containerized-services/creating-postgresql-service-containers)