CircleCI のデプロイフローを改善したときにやったこと

CircleCI のデプロイフローを改善したときにやったこと

概要

今回は、内山が担当しているプロジェクトで実施した CircleCI のデプロイフローの改善策について、ご紹介します。

改善前は、以下のような問題点がありました。

  • デプロイが完了するまでの時間が長い
  • 数年前に設定したものを使いまわしているので、CircleCI の機能を活かせていない

これらの問題を解決するために、以下のような改善を行いました。

  • 脱 Docker Compose
  • orb を活用
  • commands で設定を共通化

この結果、以下のような改善が見られました。

  • デプロイが完了するまでの時間を短縮した
  • CircleCI の設定ファイルの内容がシンプルになった

それぞれの改善策について、ご紹介します。

脱Docker Compose

これまで、CircleCI上で Docker Compose を使い、テストやデプロイを行っていました。
この利点としては、手元のPCで実行しているフローを共通化できることでした。
しかし、CircleCIの実行結果を確認してみると、docker-compose build コマンドの処理に時間がかかってしまっていることが判明しました。

この点を改善するために、脱Docker Composeすることを決めました。

Docker Composeで行っていたことは、以下のようなコンテナを用意することです。

  • テストで使うDB(MySQL)コンテナ
  • Go言語プログラムのテスト・ビルド用のコンテナ
  • Serverless Frameworkを使用したデプロイ用のコンテナ

これはCircleCIの機能で代替できることです。
具体的には、 .circleci/config.yml で以下のような設定をしています。

jobs:
  build:
    docker:
      - image: cimg/go:1.16
      - image: circleci/mysql:5.7
        environment:
          MYSQL_DATABASE: golang_db
          MYSQL_ROOT_PASSWORD: golang
          MYSQL_ROOT_HOST: '%'

docker の項目に、必要なDockerイメージを設定します。
この例では、「cimg/go:1.16」と「circleci/mysql:5.7」を設定しています。
この項目で、必要なコンテナが作成されるようになります。

この対応により、docker-compose buildの処理を行う必要がなくなった分、ビルド時間を短縮することができました。

また、副次的にGo言語のテスト実行処理時間が短くなりました。
この現象に関しては、調査はまだ行えていないので、明確な要因は不明なままです。
Docker Composeで立ち上げたコンテナ上でテスト実行することが、かなりコストが掛かっていたと考えています。

orb を活用

orbとは、CircleCIの機能で、再利用可能なYAML設定です。
プログラムにおける ライブラリ のようなものですね。

https://circleci.com/orbs/

Slack通知処理やAWS CLIコマンドのインストールなどを行うために、
YAML設定を数十行書いていました。
orbを利用することにより、同じ処理を数行単位で行えるようになりました。

具体的には、 .circleci/config.yml で以下のような設定をしています。

orbs:
  slack: circleci/slack@3.4.2
  aws-cli: circleci/aws-cli@2.0.3
  node: circleci/node@4.5.1

jobs:
   ...略
   deploy:
      ...略
      - aws-cli/setup # aws-cliの設定
      - node/install    # nodeインストール
      - slack/status:  # Slackにメッセージを送信
          success_message: ':white_check_mark: $CIRCLE_BRANCH のデプロイが完了しました\n:github: User:$CIRCLE_USERNAME'
          failure_message: ':exclamation: $CIRCLE_BRANCH の デプロイが失敗しました\n:github: User:$CIRCLE_USERNAME'
          webhook: "${SLACK_WEBHOOK}"

orbを使用することにより、config.ymlの内容がすっきりとします。
なにか設定をしたい場合は、まずは良いorbがないかどうかを調べていくのが良いと思います。

commands で設定を共通化

commandsは、CircleCIの機能で、ジョブで実行される一連のステップを再利用可能にするものです。
プログラムにおける 関数 のようなものですね。

https://circleci.com/docs/2.0/configuration-reference/#commands-requires-version-21

関数 のようなものなので、パラメータを受け取ることもできます。
複数のジョブで呼び出す際に、パラメータを渡すことができます。
今回は、Slackの通知処理を共通化しました。

具体的には、以下のような設定をしています。

commands:
  notify_slack: # コマンド名
    parameters:
      action:  # 引数名
        type: string
        default: "ビルド"
    steps:
      - slack/status:
          success_message: ':white_check_mark: $CIRCLE_BRANCH の << parameters.action >>が完了しました\n:github: User:$CIRCLE_USERNAME'
          failure_message: ':exclamation: $CIRCLE_BRANCH の << parameters.action >>が失敗しました\n:github: User:$CIRCLE_USERNAME'
          webhook: "${SLACK_WEBHOOK}"

...略

jobs:
  build:
    steps:
    ...略
    - notify_slack:
        action: ビルド

  deploy:
    steps:
    ...略
    - notify_slack:
        action: デプロイ

上記のように、複数のジョブで似たような設定をまとめることができました。

改善後の成果

これまでの対応で、以下のような成果を得られました。

  • 脱Docker Composeによって、5分くらいかかっていたビルドが1分くらいに短縮
  • orbとcommandsの活用によって、設定ファイルの内容がシンプルになった

以上です。ご参考になれば幸いです。