はじめに

こちらは YouTube の CircleCI チャンネル、CircleCI Japanese (日本語)再生リストに収録の【チュートリアル】03 CircleCI で PostgreSQL のビルド済み Docker イメージを使おう!をブログにしたものです。

また、使用しているリポジトリはこちらです。

やりたいこと

CircleCI を使って、ビルド、テスト、リリース、デプロイを行う中で、とりわけテストの際に、データベースを使用したテストを行いたい場合があります。データを永続的に取り扱う場合に、CRUD と呼ばれる 4 つの基本機能については、データの登録順序などに依存せず、正しく動作しているかどうか、開発の初期段階、及び(テーブル構成の変化を伴うような)機能の追加・削除時に確実にテストしておきたいものです。

  • Create: データの作成
  • Read: データの読み出し
  • Update: データの更新
  • Delete: データの削除

今回は、CircleCI のコンフィグの中で、PostgreSQL を使用する方法、とりわけ、テスト用途に特化した(つまり、コンテナサイズの小さい、軽量な)CircleCI 作成のビルド済みコンテナを使った方法をご紹介します。

コンフィグ中でビルド済みコンテナを使用する

先ほど紹介させていただいたリポジトリの中のコンフィグ config.yml を見ていきましょう。

ジョブ定義: ビルド済み Docker イメージの指定方法

それでは、build ジョブの定義を先頭から見ていきましょう。まずは、Docker イメージの指定に関わる部分です。

このジョブの中では2つの Docker イメージを指定してしています。

  • cimg/python - データベースにアクセスするプログラムを実行
  • cimg/postgres - データベース(PostgreSQL)を実行

名前空間 cimg/ はこれらのイメージが CircleCI によって用意されたビルド済みコンテナのイメージ(CircleCI では「コンビニエンス イメージ」と呼んでいます)のうち、次世代の CircleCI イメージであることを示しています。コンビニエンス イメージの一覧は、circleci デベロッパーサイトこちらのページから見ることが可能です。

CircleCIコンビニエンスイメージ

さて、順番が前後してしまいますが、先に cimg/postgres の利用に関わるコンフィグの記述を見ていきましょう。

jobs:
  build:
    docker:
      - image: cimg/postgres:13.3
        auth:
          username: $DOCKER_HUB_USERNAME
          password: $DOCKER_HUB_ACCESS_TOKEN
        environment:
          POSTGRES_USER: circleci
          POSTGRES_DB: postgres_test
          POSTGRES_HOST_AUTH_METHOD: trust
          TZ: "/usr/share/zoneinfo/Asia/Tokyo"

イメージを指定した後の auth: 以下、username, password で Docker Hub にログインするためのユーザ名とパスワード(アクセストークン)を指定しています。これは、Rate Limit によるイメージダウンロード制限回避のためです。また、実際のユーザ名、アクセストークンは(今回の例では)コンテクスト中に格納してあります(プロジェクトの環境変数にも格納可能ですが、プロジェクトを跨って共有するため)。

その後に、cimg/postgres イメージが使用する環境変数 POSTGRES_USER, POSTGRES_DB, POSTGRES_HOST_AUTH_METHOD, 及び TZ がコンフィグ中に指定されています。本ブログ公開時点では cimg/postgres イメージは、ベータ版公開となっていますが、下記 URL に Docker Hub へのリンク、GitHub リポジトリへのリンクも用意されているので、合わせてご覧ください。

CircleCI のビルド済み Docker イメージに関しては、下記のオンラインマニュアルも合わせてご覧ください。

次に、cimg/python の利用に関わるコンフィグを見ていきましょう。

jobs:
  build:
    docker:
      - image: cimg/python:3.9.5
        auth:
          username: $DOCKER_HUB_USERNAME
          password: $DOCKER_HUB_ACCESS_TOKEN
        environment:
          TEST_DATABASE_URL: postgres://circleci@localhost:5432/postgres_test
          TZ: "/usr/share/zoneinfo/Asia/Tokyo"
          PAGER: cat

ここでは3つの環境変数が定義されています。TEST_DATABASE_URL は、cimg/postgres によって起動されるデータベースに接続する際に使用する URL です。TZは先ほどと同様にタイムゾーンの指定です。

なお、PAGER については注意が必要かも知れません。後ほど、テストの際に psqlコマンドを使って、データベースに SQL 文を発行した際の実行結果を表示しているのですが、デフォルトのページャーでは表示が一部、うまくいかなかったためにここでは cat をページャーとして使用する定義をしています。

ジョブ定義: ステップ内での処理

それでは、build ジョブで実際に steps 内で実行しているステップを追って見ていきましょう。

- run: |
    sudo rm -rf /var/lib/apt/lists/*
    sudo apt update
    sudo apt install postgresql-client-12

上のステップでは、PostgreSQL に接続するためのクライアントツールをapt installでインストールしています。

- run: |
    dockerize -wait tcp://localhost:5432 -timeout 1m

上のステップは注意が必要かも知れません。cimg/python イメージの起動が完了した時点で、cimg/postgres イメージの起動が完了している(=PostgreSQL サーバに接続可能な状態になっている)ことは必ずしも保証されていないので、localhost:5432 が接続可能になるまで、最大 1m(1 分)、ここで待ち処理を行う定義をしています(PostgreSQL サーバの起動が完了しておらず、接続できない時に、テストをエラーとして終了させたい訳ではないため)。

- run: |
    psql \
    -d $TEST_DATABASE_URL \
    -c "CREATE TABLE test (name text)"

PostgreSQL サーバに接続可能になったら、クライアントツール(psql)を使用して、CREATE TABLE文で test テーブルを作成します。

- run: |
    psql \
    -d $TEST_DATABASE_URL \
    -c "INSERT INTO test (name) VALUES ('舟木'), ('森本'), ('ローズ'), ('ズーバー')"

次に、作成した test テーブルに対して、レコードの挿入を行います。ここでは、4 行分のレコードを挿入しています。

- run: |
    psql \
    -d $TEST_DATABASE_URL \
    -c "SELECT * from test"

最後に、挿入したレコードをSELECT文で取得し、表示することで動作を確認しています。次のように結果が表示されるのを CircleCI のダッシュボードから確認します。

ダッシュボードの確認

さいごに

今回のサンプルでは、アプリケーション自身がデータベースに接続し、処理を依頼するのではなく、コンフィグの中からデータベースに接続し、処理の依頼を行いましたが、ご自身で書いたコードからデータベースに接続するようなテストを実行する場合であっても、コード中で同様の処理を行うことになります。

データベースに接続するようなコードのテストを自動化する上で、デモ動画での説明と合わせ、ぜひご参考にしていただければと思います。

合わせて、他のチュートリアル動画も鋭意増強中です。合わせてご参照をいただければと思います。