💻

[保存版] CircleCI 2.0による自動デプロイの導入手順まとめ

2020/02/05に公開

こんにちは、たつきちです。

自動デプロイのためのCircleCIの導入手順が端的にまとまっている情報が意外とググっても見つけにくいなと思ったので、自分用のメモ書きを清書して記事にしておきます👌

CIの導入はプロジェクトの開始時に一度しかやらない作業なので、僕も毎回やり方を忘れてます。わざわざ覚えておく必要なんて全然ないと思いますので、プロジェクトの開始時に毎回この記事を見に来てもらえたらいいかなと思います。

今回はPHP製のデプロイツール「deployer」を使って物理サーバーにデプロイするケースを例に、具体的な手順を説明していきます。

ちなみに、自動デプロイの概念自体がまだよく分かっていないという方には、僕が以前にSchoo(スクー)さんで行った講義 が参考になると思いますので、ぜひご覧ください。

1. CircleCI上にプロジェクトを追加

まず、ダッシュボードの PROJECTS で、目的のGitHubリポジトリを選択してプロジェクトを追加します。

2. デプロイキーを登録

次に、CircleCIからデプロイ先サーバーにssh接続できるようにするために、デプロイキーを登録します。

具体的には、ローカルでキーペアを作って、秘密鍵のほうをCircleCIに、公開鍵のほうをデプロイ先サーバーに登録します。

2-1. CircleCIに秘密鍵を登録

以下のように ssh-keygen コマンドでキーペアを作ります。

$ ssh-keygen -t rsa -f id_rsa.tmp -C "CircleCI / プロジェクト名" -N "" -m PEM

パラメータの意味は以下のとおりです。

  • -t rsa RSA方式を指定
  • -f id_rsa.tmp カレントディレクトリに id_rsa.tmp というファイル名でキーペアを生成
  • -C "CircleCI / プロジェクト名" 公開鍵の末尾に記載されるコメントを指定(あとで見分けやすいように)
  • -N "" パスフレーズなしを指定
  • -m PEM macOS Mojave以降だとデフォルトでOpenSSH形式の鍵が生成されてしまい、CircleCIが対応していないので、PEM形式を指定

秘密鍵のほうをクリップボードにコピーします。

# macOSの場合
$ pbcopy < id_rsa.tmp

# それ以外の場合
$ cat id_rsa.tmp
# 出力された内容を手でコピー

ダッシュボードのビルド一覧画面の各行の右端の ... から Project Settingsを開いてプロジェクトの設定画面を開きます。 以下のようなURLの画面です。

https://app.circleci.com/settings/project/github/<user>/<repo>

メニューにある SSH Keys を開いて、 Add SSH Key から秘密鍵を登録します。

Hostname は空のままで、 Private Key に先ほどコピーしておいた秘密鍵を貼り付けて送信すればOKです。

登録すると、SSHキーのfingerprintが表示されます。これは後で使いますので、どこかにコピーしておいてください。

2-2. デプロイ先サーバーに公開鍵を登録

続けて、公開鍵をデプロイ先のサーバーの ~/.ssh/authorized_keys に追記します。

# macOSの場合
$ pbcopy < id_rsa.tmp.pub

# それ以外の場合
$ cat id_rsa.tmp.pub
# 出力された内容を手でコピー
$ ssh [ターゲットユーザー]@[ターゲットサーバー]
% vi ~/.ssh/authorized_keys   # 末尾にクリップボードの内容をペースト
% exit
$ rm id_rsa.tmp*   # もう要らないので削除

あるいは、 ssh-copy-id コマンドがインストールされている場合であれば(Mac なら brew install ssh-copy-id で入れられます)、以下のような方法でもっと簡単に追記することもできます。

$ ssh-copy-id -i id_rsa.tmp.pub [ターゲットユーザー]@[ターゲットサーバー]
$ rm id_rsa.tmp*   # もう要らないので削除

3. プロジェクトの環境変数にDockerHubの認証情報を追加

2020/11/1より、DockerHubにおいてイメージのpullに 回数制限 が設けられました。

この制限を少しでも緩和するため、イメージをpullする際にDockerHubユーザーでログインすることが推奨されています。

ちなみに、認証なしだと6時間あたり100回、無料ユーザーは6時間あたり200回がpullの上限となっています。有料ユーザーは無制限です。(参考

具体的には、公式ドキュメント に書かれているとおり、後述の設定ファイルにDockerHubの認証情報を書き足せばよいのですが、認証情報を直接書きたくないので、プロジェクトの環境変数に格納しておいて、それを参照するようにします。

プロジェクト設定画面の Environment Variables を開いて、 Add Variable から環境変数を登録します。

Name Value
DOCKERHUB_USERNAME {DockerHubのログインユーザー名}
DOCKERHUB_PASSWORD {DockerHubのログインパスワード}

上記のように2つ環境変数を登録しておきましょう。

4. プロジェクトのコードベースにCircleCIの設定ファイルを追加

/.circleci/config.yml というファイルパスでCircleCIの設定ファイルを設置します。

最初にCircleCIにプロジェクトを追加したときに雛形が表示されたと思うので、それを元に改変するのがよいでしょう。

設定ファイルのDSLの詳細は 公式リファレンス に細かく記載されています。

PHPプロジェクトであれば この辺 も参考になります。

ただし、これらの雛形にはビルドジョブの設定しかなく、自動デプロイまでは想定されていないため、そこは自力で書く必要があります。

例えばPHPプロジェクトの場合ならおおよそ以下のような内容になるかと思います。

.circleci/config.yml の例

version: 2
jobs:
  test:
    docker:
      - image: circleci/php:7.2-cli-node-browsers
        auth:
          username: $DOCKERHUB_USERNAME
          password: $DOCKERHUB_PASSWORD
    working_directory: ~/wd

    steps:
      - checkout

      - run: sudo composer self-update

      - restore_cache:
          keys:
            - composer-v1-{{ checksum "composer.json" }}
      - restore_cache:
          keys:
            - node-v1-{{ checksum "package.json" }}

      - run: composer install -n --prefer-dist

      - save_cache:
          key: composer-v1-{{ checksum "composer.json" }}
          paths:
            - vendor
      - save_cache:
          key: node-v1-{{ checksum "package.json" }}
          paths:
            - node_modules

      # test
      - run: vendor/bin/phpunit

  deploy:
    docker:
      - image: composer
        auth:
          username: $DOCKERHUB_USERNAME
          password: $DOCKERHUB_PASSWORD
    working_directory: ~/wd

    steps:
      - checkout

      - add_ssh_keys:
          fingerprints:
            - xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx

      - run:
          name: install deployer
          command: |
            composer global require deployer/deployer
            echo 'export PATH=/tmp/vendor/bin:$PATH' >> $BASH_ENV

      - deploy:
          name: dep deploy
          command: |
            dep deploy production -vvv

workflows:
  version: 2
  test_and_deploy:
    jobs:
      - test
      - deploy
      - deploy:
          requires:
            - test
          filters:
            branches:
              only: master

以下のあたりがポイントです。

  • deploy ジョブからデプロイ先サーバーにssh接続させるために、 add_ssh_keys ディレクティブ を使って、先ほど登録したSSHキーのfingerprintを指定している
  • Dockerイメージを使用する際に、先ほど登録した環境変数 $DOCKERHUB_USERNAME $DOCKERHUB_PASSWORD を使ってDockerHubにログインしている
  • デプロイを実行するための環境として、ここでは composer Dockerイメージを使っており、deployerをインストールしたパスを PATH 環境変数に追加するために $BASH_ENV 環境変数 を利用している

5. プロジェクトのコードベースにdeployerの設定ファイルを追加

/deploy.php というファイルパスで deployer の設定ファイルを設置します。

deployerをインストール して、プロジェクトルートで

$ dep init

を実行すれば雛形を作成することができます。

一例として、シンプルなPHPプロジェクトであれば以下のような内容になるかなと思います。

deploy.php の例

<?php
namespace Deployer;

require 'recipe/common.php';

// Configs

set('repository', 'git@github.com:<user>/<repo>.git');
set('git_tty', true);
set('shared_files', ['.env']);
set('shared_dirs', []);
set('writable_dirs', []);

// Hosts

host('production')
    ->hostname('<hostname>')
    ->user('<user>')
    ->addSshOption('StrictHostKeyChecking', 'no')
    ->set('deploy_path', '/path/to/target');

// Tasks

task('deploy', [
    'deploy:info',
    'deploy:prepare',
    'deploy:lock',
    'deploy:release',
    'deploy:update_code',
    'deploy:shared',
    'deploy:writable',
    'deploy:vendors',
    'deploy:clear_paths',
    'deploy:symlink',
    'deploy:unlock',
    'cleanup',
    'success'
]);

after('deploy:failed', 'deploy:unlock');

6. その他

以上で自動デプロイの設定は完了ですが、ついでにSlack通知の設定方法と、READMEにCircleCIのステータスバッジを埋め込む方法についてもメモ書き程度に書いておきます。

6-1. CircleCIから結果をSlackに通知する

プロジェクト設定画面のメニュー Chat Notifications から設定できます。

SlackでCircleCI連携を設定した上で、発行されたWebhook URLを上記の画面に入力するだけでOKです。

6-2. READMEにCircleCIのステータスバッジを埋め込む

プロジェクト設定画面のメニュー Status Badges で、ステータスバッジを表示するためのMarkdownスニペットが取得できるので、それを README.md に貼り付けるだけです。

ただし、プライベートリポジトリの場合は先に以下の手順でAPIトークンを作っておく必要があるので要注意です。

プロジェクト設定画面のメニュー API PermissionsCreate Token をクリックし、

  • スコープは Status のまま
  • Token label は何でもいいけど to-get-build-status など分かりやすい名前を適当に付ける

上記のような内容でトークンを作成します。

この状態で Status Badges の画面を開くと、 API Token という欄で先ほどの to-get-build-status が選択できるので、それを指定してあげればOKです。

GitHubで編集を提案

Discussion