半年に一度続きが読めるバックエンドエンジニア、リョウタの記事へようこそ。
(前回の記事はこちら:感謝の気持ちをCloud KMSで暗号化して送ってみた)
今回はWordPressのサイトのデプロイを、CI/CDを使って楽にする方法についてお話しします。基本的にはGCPのサービスで完結できるようにします。
目次
使うサービス
- Cloud Source Repositories
- Cloud KMS
- Cloud Build
- Google Compute Engine
- Slack Incomming Webhook
Cloud Source Repositories
GCPのGitリポジトリサービスです。プルリクなどの機能がなく、とにかく簡素です。今回のチュートリアルはCloud Buildを使うので、GitHubやBitbucketと連携をすることもできます。
Cloud KMS
前回の記事で使用した暗号化・複合化のためのサービスです。マストではありませんが、サーバーへ接続する際の秘密鍵を暗号化・複合化するのに使います。
Cloud Build
今回の要です。Gitリポジトリの変更をトリガーにしてクラウド上で実行されるCI/CDツールです。
- Slackへの開始通知
- resourciesのビルド
- 秘密鍵の複合化
- テーマファイルをサーバーへ転送
- Slackへの終了通知
Google Compute Engine
Webサーバーなら下記の要件を満たしていれば何でも構いません
- WordPressがインストールされ動作する
- rsyncコマンドが使える
- キーペアでログインができる
Slack Incomming Webhook
開始と終了の通知用に使います。こちらもマストではありません。
ビルドの途中でエラーが起きた際は終了の通知が飛びません(Pub/Subを併用することで異常系の通知ができるようになりますが、今回は割愛します)。エンドポイントを事前に取得しておいてください。
やってみる
ローカルに環境を作る
ローカルにプロジェクトを作成します。WordPressはwpというディレクトリに格納しています。
構成はこんな感じです。
├── .gitignore
├── package.json
├── resources
│ └── images
│ └── test.png
└── wp
└── wp-content
├── plugins
│ └── test_plugin
│ └── index.php
└── themes
└── test_pj
├── footer.php
├── functions.php
├── header.php
├── index.php
└── style.css
案件の場合はここにビルド用の設定ファイルや、dockerファイルなどが含まれます。
.gitignoreは以下のようにしています。
node_modules
*.log
/wp/*
!/wp/wp-content/
/wp/wp-content/*
!/wp/wp-content/plugins/
!/wp/wp-content/languages/plugins/
!/wp/wp-content/themes/
/wp/wp-content/themes/*
/wp/wp-content/themes/*/assets/
!/wp/wp-content/themes/test_pj/
WordPressのコアファイルやuploads配下のファイル、ビルドされたアーティファクトはGitに含めません。
最後にgit initしてローカルをGitリポジトリにします。
リポジトリにプッシュする
Cloud Source Repositriesに入って「リポジトリを追加」を押下します。
手順に沿ってに進めます。
「ローカル Git リポジトリからコードを push」を選択し、下に表示されるコードを実行します。
無事にプッシュできましたでしょうか? できない場合は証明書周りでつまずいてるかもしれません。
正常にコミット・プッシュされていればこのようになります。
リモートサーバーに環境を作る
いきなり端折ってごめんなさい。すでにWordPressがあることを前提で話を続けます。
ここで大事なのはリモートサーバーにキーペアでログインができること。また、リモートサーバーでrsyncが使えることです。
秘密鍵を暗号化する
リモートサーバーにログインするための秘密鍵をCloud KMSを使って暗号化します。手順は前回の記事とほぼ同じです。
証明書をKMSで暗号化し、base64エンコードします。
cat 証明書のパス | \
gcloud --project GCPプロジェクト名 kms encrypt \
--plaintext-file=- \
--ciphertext-file=- \
--location=global \
--keyring=キーリング名 \
--key=キー名 | base64
出力された値をメモしておいてください。このあと使います。
トリガーを作る
続いてCloud Buildにトリガーを作ります。
名前を入力し、「ソース」→「リポジトリ」から先ほど作成したリポジトリを選択します。
※1はトリガーが起動するブランチです。デプロイする環境に対応したブランチを指定しましょう。
※2は実行される処理が記載されたファイル名です。今回はデフォルトのままにします。
代入変数を設定する
サーバーの情報などはGit管理したくないので、ここに値を持たせておきます。
今回はこのようにいきます。
また、「_SSH」には、ユーザー名@ホスト:wp-contentまでのパスを入力します(例:hoge@111.111.111.111:/var/www/htdocks/wp-content)。
入力ができたら「保存」します。
cloudbuild.yamlを作る
Gitリポジトリのルートにcloudbuild.yamlというファイルを作成します。以下のようなものが中身です。
steps:
- name: 'gcr.io/cloud-builders/gcloud'
entrypoint: bash
args:
- '-c'
- |
curl -X POST -H 'Content-type: application/json' -d '{"text":"Start Deployment:${REPO_NAME} ${BRANCH_NAME} ${_COMMIT_LINK}${SHORT_SHA}"}' ${_SLACK_INCOMMING_WEBHOOK}
- name: node:14.16.0
entrypoint: npm
args: ['ci']
- name: node:14.16.0
entrypoint: npm
args: ['run','production']
- name: 'gcr.io/cloud-builders/gcloud'
entrypoint: bash
args:
- '-c'
- |
echo "$_ENC" | base64 -d >/workspace/decrypt-base64
- name: 'gcr.io/cloud-builders/gcloud'
args:
- kms
- decrypt
- --ciphertext-file=/workspace/decrypt-base64
- --plaintext-file=/workspace/ssh-key
- --location=global
- --keyring=$_KEYRING
- --key=$_KEYNAME
- name: 'gcr.io/cloud-builders/gcloud'
entrypoint: bash
args:
- '-c'
- |
chmod 0600 /workspace/ssh-key
- name: 'gcr.io/cloud-builders/gcloud'
entrypoint: bash
args:
- '-c'
- |
apt-get update
apt-get -y install rsync
rsync -auz --delete -e "ssh -o 'StrictHostKeyChecking no' -p ${_PORT} -i /workspace/ssh-key" /workspace/wp/wp-content/themes ${_SSH}
rsync -auz --delete -e "ssh -o 'StrictHostKeyChecking no' -p ${_PORT} -i /workspace/ssh-key" /workspace/wp/wp-content/plugins ${_SSH}
- name: 'gcr.io/cloud-builders/gcloud'
entrypoint: bash
args:
- '-c'
- |
curl -X POST -H 'Content-type: application/json' -d '{"text":"Finish Deployment:${REPO_NAME} ${BRANCH_NAME} ${_COMMIT_LINK}${SHORT_SHA}"}' ${_SLACK_INCOMMING_WEBHOOK}
何をやっているのかざっくり解説します。
開始のSlack通知を送る
- name: 'gcr.io/cloud-builders/gcloud'
entrypoint: bash
args:
- '-c'
- |
curl -X POST -H 'Content-type: application/json' -d '{"text":"Start Deployment:${REPO_NAME} ${BRANCH_NAME} ${_COMMIT_LINK}${SHORT_SHA}"}' ${_SLACK_INCOMMING_WEBHOOK}
Cloud Buildには先ほど設定した変数とは別に、デフォルトでいくつかの環境変数が用意されています(一覧はこちら)。どのリポジトリの、どのブランチの、どのコミットから実行されたかをSlackの通知に含めてわかりやすくしています。
このように届きます。
npm installとbuild
node modulesのインストールと、ビルドを実行します。ビルドに使うnode.jsのdocker imageは開発環境とバージョンを合わせるようにしましょう。
- name: node:14.16.0
entrypoint: npm
args: ['ci']
- name: node:14.16.0
entrypoint: npm
args: ['run','production']
暗号鍵を複合化
まずはbase64でコードした文字列をファイルに書き出します。
- name: 'gcr.io/cloud-builders/gcloud'
entrypoint: bash
args:
- '-c'
- |
echo "$_ENC" | base64 -d >/workspace/decrypt-base64
続いて、そのファイルをCloud KMSを使って複合化します。複合化したファイルはssh-keyという名前で保存します。
- name: 'gcr.io/cloud-builders/gcloud'
args:
- kms
- decrypt
- --ciphertext-file=/workspace/decrypt-base64
- --plaintext-file=/workspace/ssh-key
- --location=global
- --keyring=$_KEYRING
- --key=$_KEYNAME
パーミッションを変更します。
- name: 'gcr.io/cloud-builders/gcloud'
entrypoint: bash
args:
- '-c'
- |
chmod 0600 /workspace/ssh-key
リモートサーバーに送り込む
今回は直接wp-contentディレクトリにrsyncを使ってファイルを送り込みます。
- name: 'gcr.io/cloud-builders/gcloud'
entrypoint: bash
args:
- '-c'
- |
apt-get update
apt-get -y install rsync
rsync -auz --delete -e "ssh -o 'StrictHostKeyChecking no' -p ${_PORT} -i /workspace/ssh-key" /workspace/wp/wp-content/themes ${_SSH}
rsync -auz --delete -e "ssh -o 'StrictHostKeyChecking no' -p ${_PORT} -i /workspace/ssh-key" /workspace/wp/wp-content/plugins ${_SSH}
※deleteオプションをつけているので、Gitで管理されているファイルと、buildされたファイル以外は基本的に消えますので注意してください。最初はdry-runのオプションをつけて試行すると良いでしょう。
終了の通知を受け取る
開始と同様に終了を通知します。
- name: 'gcr.io/cloud-builders/gcloud'
entrypoint: bash
args:
- '-c'
- |
curl -X POST -H 'Content-type: application/json' -d '{"text":"Finish Deployment:${REPO_NAME} ${BRANCH_NAME} ${_COMMIT_LINK}${SHORT_SHA}"}' ${_SLACK_INCOMMING_WEBHOOK}
Cloud Buildを動かしてみる
さて、設定ファイルもできたので、これをGitに含めてプッシュします。
うまくいっていればビルドが走るはずです。Cloud Buildの管理画面から「履歴」を開きます。
成功していれば、このように表示されます。
まとめ
初めて挑戦したときはなかなか思うようにデプロイがされず試行錯誤しましたが、慣れると本当に楽になります。人為的ミスは私たちが人間である以上常に潜んでる罠です。
自動化できるところは自動化して、浮いた心の余裕をクリエイティブに注力していきましょう。
では。また半年後に……。
LIGはWebサイト制作を支援しています。ご興味のある方は事業ぺージをぜひご覧ください。