機械学習エンジニアの備忘録

主に自分が勉強したことのメモ

Github + Amazon ECR + CircleCIで独自のdocker image上でpytestを自動実行する

はじめに

CI/CD環境を構築するためにしばしばJenkinsが使われますが、Jenkinsは運用・メンテナンスが面倒だったりGUIベースの設定なのでノウハウが属人化してしまいがちであるという課題があります。

そこで、SaaSを使ったモダンなCI/CD環境を作りたいという思いから今回Github + Amazon ECR + CircleCIを連携したpytestの自動テストの仕組みを作ったので、備忘録として手順を残しておきます。

ビルドパイプライン概要

今回 GithubAmazon ECR、CircleCIを組み合わせて以下のようなパイプラインを構築してみました。

f:id:rikeiin:20191226155127p:plain
ビルドパイプライン

それぞれについて解説していきます。

CircleCIでdocker imageを自動で作成し、Amazon ECRにプッシュする

パイプライン図の①②③では、Githubにコミットがプッシュされたことを検知してCircleCIがDocker imageのビルドを開始します。ビルドが完了すると作成されたイメージをAmazon ECRにプッシュします。

CircleCI

CircleCIは簡単に言うとSaaS型のCI/CDサービスです。
Jenkinsと比べるとCircleCIはSaaSなので自分で運用・構築する必要がない、YAMLファイルで設定するので設定が職人芸化しないなどのメリットがあります。
無料枠もあるので開発規模によっては無料でも全く問題なく使えるます。

circleci.com

Amazon ECR

Amazon Elastic Container RepositoryはAWSの完全マネージドのコンテナレポジトリサービスです。
Docker hubのプライベート用みたいの感じで、Docker imageの保存・管理等が簡単にできるようになります。
GCPやAzureにも同様のサービスがありますが、私は開発環境をAWSで作っているので今回ECRを採用しました。

CircleCIとECRの連携

基本的には以下の記事と同様の方法で連携できます。

www.seeds-std.co.jp

まずはAWS上でECRの作成とCircleCIからECRを操作するためのIAMユーザの作成をします。
IAMユーザの権限として"AmazonEC2ContainerRegistryFullAccess"を付与しておきます。

次にCircleCIとGithubの連携を行います。
CircleCIにアクセスして自分のGithubアカウントでログインします。
ログインすると自分のGithubレポジトリの一覧が出てくるのでCIを動かしたいレポジトリをフォローします。これで連携の準備ができました。

次にCircleCIのジョブの設定を行います。CircleCIのジョブの画面よりEnvironment Variablesを開き、ジョブ実行に必要な環境変数をセットします。

  • AWS_ACCOUNT_ID(AWSのアカウント番号)
  • AWS_ACCESS_KEY_ID(circleciユーザのアクセスキー)
  • AWS_SECRET_ACCESS_KEY(circleciユーザのシークレットアクセスキー)
  • AWS_REGION(例:ap-northeast-1)
  • AWS_ECR_ACCOUNT_URL(ECRのリポジトリURL XXXXXXXX.dkr.ecr.ap-northeast-1.amazonaws.com/)
  • AWS_RESOURCE_NAME_PREFIX(ECRのリポジトリ名)

GitHubにプッシュされた場合にCircleCIの動作を制御するための設定ファイルを用意します。
.circleciというフォルダを作成し、その中にconfig.ymlというファイルを作成します。
config.ymlでCircleCIの動作を制御するのですが、ECRリポジトリへのアップロードするためのOrbs(※ジョブ、コマンドなどの設定要素をまとめた共有可能なパッケージのこと)をCircleCIが公式に提供しています。
これらを利用してGitHubにプッシュされた場合、DocerkイメージをビルドしてECRにアップロードするといった内容のconfig.ymlを作成します。

https://circleci.com/orbs/registry/orb/circleci/aws-ecr?version=6.1.0


config.yml

version: 2.1
orbs:
  aws-ecr: circleci/aws-ecr@6.1.0

jobs:
  build-and-push-image:
    executor:
      name: aws-ecr/default
    steps:
      - aws-ecr/build-and-push-image:
          account-url: AWS_ECR_ACCOUNT_URL
          repo: "${AWS_RESOURCE_NAME_PREFIX}"
          region: AWS_REGION
          tag: "${CIRCLE_SHA1}"

workflows:
  version: 2
  build-and-push:
    jobs:
      - build-and-push-image:

作成したconfig.ymlをgithubにプッシュしてみましょう。
CircleCIのダッシュボード上からジョブが動いている様子が確認できます。
また、ビルドとプッシュが完了するとAWSのECR上に新しいイメージがあることが確認できるはずです。

作成したDocker imageをプルしてpytestを実行

それでは先程作成したイメージを使ってpytestを実行します。
設定は先程作成したconfig.ymlと合わせると以下のようになります。

version: 2.1
orbs:
  aws-ecr: circleci/aws-ecr@6.1.0

jobs:
  build-and-push-image:
    executor:
      name: aws-ecr/default
    steps:
      - aws-ecr/build-and-push-image:
          account-url: AWS_ECR_ACCOUNT_URL
          repo: "${AWS_RESOURCE_NAME_PREFIX}"
          region: AWS_REGION
          tag: "${CIRCLE_SHA1}"


  test:
    docker:
      - image: "${AWS_ECR_ACCOUNT_URL}/${AWS_RESOURCE_NAME_PREFIX}:${CIRCLE_SHA1}"
    steps:
      - checkout
      - run:
          name: run tests
          command: |
            pytest -v .
workflows:
  version: 2
  build-and-push-and-test:
    jobs:
      - build-and-push-image:
      - test:
          requires:
            - build-and-push-image

Githubにpytestのファイルを作成してプッシュしてあげると、CircleCI上でpytestが自動で実行されることが確認できます。
Github上でもテスト結果が以下のように確認できます。

f:id:rikeiin:20191226170225p:plain

まとめ

今回Github + Amazon ECR + CircleCIを連携して独自のDocker imageを使ったpytestの自動実行の仕組みを構築しました。
CircleCIはJenkinsより設定が圧倒的に楽でいいですね。
今後はコンテナをデプロイしてE2Eテストも自動で行うような仕組みも作りたいなと思います。