CircleCIで自動デプロイする

参考サイト

Circle CIでwebサイトを自動デプロイ


GitHubのmasterブランチへマージされたらサーバーにデプロイされるようにする方法です。
ソースコードはPHPを前提としています。

こちらのCircleCIを動かす基本設定は完了している前提とします。
Circle CIでプルリク時にUnitテストが走るようにする

CI用ユーザ準備

まず、CircleCIからデプロイするサーバーへSSH接続する為の鍵ペアを作成します。
既存の鍵ペアを使っても動きますが、念のためCI用は別にしておいた方が良いと思います。

ssh-keygen -t rsa -b 4096 -C "ci@nonsensej.xyz" -f ~/.ssh/ci-key

上記コマンドを実行するとパスフレーズを2回聞かれますが、どちらも空のままエンターで良いです。

鍵生成が完了したらホームディレクトリの.ssh配下にci-key(秘密鍵)とci-key.pub(公開鍵)が生成されます。
ci-key.pubは後工程で使いますので、中身を確認しておいてください。
※上記コマンドで鍵ファイル名をci-keyと指定していますが、これは任意の名前で良いです。

次に、デプロイするサーバー上でデプロイする為のユーザーを作成し、
さきほど作成した鍵ペアでSSH接続できるようにします。
こちらも既存ユーザーを使っても動きますが、念のためCI用は別にしておいた方が良いと思います。

adduser -g nginx ciuser
su - ciuser
mkdir .ssh
vim .ssh/authorized_keys
// ci-key.pubの内容を貼り付け

CircleCI管理画面設定

次にCircleCIのWEBコンソールで設定をします。
該当プロジェクトの画面にて設定(歯車アイコン)をクリックし、設定画面を開きます。

SSH Keyの設定

左メニューより『PERMISSIONS > SSH Permissions』を開き、『Add SSH Key』をクリックします。

ポップアップが開くので、以下を設定します。
Hostname : デプロイするサーバーのホスト名
Private Key : 最初に作ったci-keyの中身全て

完了したら、今登録した鍵情報のFingerprintが表示されるので確認しておきます。
(後工程のCircleCI設定ファイル編集時に使います)

環境変数の設定

後工程で編集するCircleCI設定ファイルで環境変数を使うことができるので設定します。
この作業は別に必須ではないです。
設定ファイルを使いまわしたい場合は、環境により変動する部分を環境変数にしておいてもいいかもしれません。

左メニューより『BUILD SETTINGS > Environment Variables』を開き、『Add Variable』をクリックします。

ポップアップが開くので設定したい変数名と値を登録します。
例えばUSER_NAMEという変数にciuserという値を設定する場合は下図のようになります。

CircleCI設定ファイル編集

前回作った.circleci/config.ymlに以下の行を追記していきます。
以下例では前手順の環境変数を多数利用していますが、config.ymlに値を直接書いても構いません。

まず、デプロイするサーバーへ接続するための鍵情報(fingerprint)を登録します。
環境変数には以下が設定されているとします。
KEY_FINGERPRINT : さきほど確認したSSH鍵のfingerprint

      - add_ssh_keys:
          fingerprints:
            - "${KEY_FINGERPRINT}"
          # 環境変数を使わない場合はこのようにベタがきすればよいです    
          # - "a1:b2:c3:・・・:x8:y9:z0"

次にSSH接続がコケないように設定しておきます。
環境変数には以下が設定されているとします。
SSH_PORT : デプロイするサーバーのSSHポート
HOST_NAME : デプロイするサーバーのホスト名

      - run:
          name: Start ssh-keyscan
          command: |
            ssh-keyscan -p ${SSH_PORT} ${HOST_NAME} >> ~/.ssh/known_hosts

次にデプロイします。
環境変数は上記までに出てきたものに加えて以下が設定されているとします。
USER_NAME : デプロイするユーザー名(ciuser)
APP_PATH : デプロイするパス(/var/www/htmlなど)

      - deploy:
          name: Start master deploy
          command: |
            if [ "${CIRCLE_BRANCH}" == "master" ]; then
                rsync -av --delete --rsh="ssh -p ${SSH_PORT}" --exclude='.git' --exclude='.circleci' ./ ${USER_NAME}@${HOST_NAME}:${APP_PATH}
            fi

できあがったconfig.ymlはこのようになります。

# PHP CircleCI 2.0 configuration file
#
# Check https://circleci.com/docs/2.0/language-php/ for more details
#
version: 2
jobs:
  build:
    docker:
      # specify the version you desire here
      - image: circleci/php:7.1-fpm-node-browsers
      
      # Specify service dependencies here if necessary
      # CircleCI maintains a library of pre-built images
      # documented at https://circleci.com/docs/2.0/circleci-images/
      # - image: circleci/mysql:9.4

    working_directory: ~/repo

    steps:
      - checkout

      # Download and cache dependencies
      - restore_cache:
          keys:
          - v1-dependencies-{{ checksum "composer.json" }}
          # fallback to using the latest cache if no exact match is found
          - v1-dependencies-

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

      - save_cache:
          paths:
            - ./vendor
          key: v1-dependencies-{{ checksum "composer.json" }}
        
      # run tests!
      - run: vendor/phpunit/phpunit/phpunit tests/

      - add_ssh_keys:
          fingerprints:
            - "${KEY_FINGERPRINT}"

      - run:
          name: Start ssh-keyscan
          command: |
            ssh-keyscan -p ${SSH_PORT} ${HOST_NAME} >> ~/.ssh/known_hosts
 
      - deploy:
          name: Start master deploy
          command: |
            if [ "${CIRCLE_BRANCH}" == "master" ]; then
                rsync -av --delete --rsh="ssh -p ${SSH_PORT}" --exclude='.git' --exclude='.circleci' ./ ${USER_NAME}@${HOST_NAME}:${APP_PATH}
            fi

※補足
SSHポートをデフォルト(22)のままにしているのであれば
config.yml内のsshコマンドにてSSHポートを指定する必要はありません。

これで、masterにマージしたらデプロイが走るようになります。

関連する記事