以下の記事でGoogle App EngineにTwitter Botをデプロイしましたが、GAEの制約(HTTPリクエストが10分間来なかったらインスタンスがシャットダウンされる)を知らなかったため、24時間常に起動していてほしいBotのデプロイ先としては適していないことがわかりました。
GitHub Actions と Google App Engine でCI/CD
今回は、そのリベンジとしてGCEにデプロイして、問題なく動かすことができました。
CI/CDの自動化まで行ったので、手順を記録します。
ゴール
- GCEにコンテナ化したアプリケーションをデプロイして動かすことができる
- デプロイを自動化する
アプリケーションのDocker化
以下の記事に別途まとめました。
TypeScriptで作ったアプリケーションをコンテナで実行する
まずは手動でGCEにコンテナをデプロイしてみる
GCP Container Registory にイメージをpushする
ローカル環境でビルドしたDockerイメージをContainer Registoryにpushします。
次のステップで、GCEのインスタンスをたてるときにイメージを指定するためです。
ローカルのイメージにレジストリ名をタグ付けします。ホストはasia, イメージ名にはappを指定しました。
docker tag [IMAGE_NAME] asia.gcr.io/[PROJECT-ID]/app
タグ付けされたイメージをContainer Registoryにpushします。
docker push HOSTNAME/PROJECT-ID/IMAGE
GCEインスタンスにコンテナをデプロイする
Google Cloud Consoleから、Compute Engineの管理画面に行き、「インスタンスを作成」→「コンテナイメージをデプロイ」を選択します。
コンテナイメージには、先程pushしたイメージを指定します。
また、環境変数もここで設定可能です。
マシンタイプには「f1-micro」を指定しました。f1-microには無料枠があるので、1台までなら無料で使用できるようです。
ここまでできたら、「作成」をクリックでインスタンスが作成されます。
ちなみに、「コンテナイメージをデプロイ」を選択すると、Compute EngineのOSには、Docker コンテナの実行に最適化されたContainer-Optimized OSというOSが自動で選択されます。
以上で、手動で単一のコンテナをGCEにデプロイすることができました。
デプロイを自動化する
GitHub Actions を使って、masterブランチへのpush毎に、イメージのビルド・push、GCEのコンテナの更新を行うようにします。
buildのジョブでイメージのビルド・pushを行います。
deployのジョブでコンテナの更新を行います。gcloud compute instances update-container
コマンドで、インスタンスの停止→再起動と、起動時に新しいイメージをダウンロードしてコンテナの起動まで行ってくれます。
name: CI/CD
on:
push:
branches: [master]
env:
IMAGE: asia.gcr.io/dev-article-twitter-bot/app:${{ github.sha }}
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
os: [ubuntu-latest]
node-version: [14.x]
steps:
- name: checkout the repository
uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- name: yarn install, and test
run: |
yarn
yarn test
env:
CI: true
build:
runs-on: ubuntu-latest
steps:
- name: checkout the repository
uses: actions/checkout@v2
- name: set up Cloud SDK
uses: google-github-actions/setup-gcloud@master
with:
project_id: ${{ secrets.GCP_PROJECT_ID }}
service_account_key: ${{ secrets.GCP_SA_KEY }}
export_default_credentials: true
- name: configure docker to use the gcloud cli
run: gcloud auth configure-docker --quiet
- name: build a docker image
run: docker build . -t $IMAGE
- name: push the docker image
run: docker push $IMAGE
deploy:
needs: [test, build]
runs-on: ubuntu-latest
steps:
- name: set up Cloud SDK
uses: google-github-actions/setup-gcloud@master
with:
project_id: ${{ secrets.GCP_PROJECT_ID }}
service_account_key: ${{ secrets.GCP_SA_KEY }}
export_default_credentials: true
- name: set project
run: gcloud config set project $GCP_PROJECT_ID
env:
GCP_PROJECT_ID: ${{ secrets.GCP_PROJECT_ID }}
- name: deploy to GCE
run: gcloud compute instances update-container $GCP_PROJECT_ID --container-image $IMAGE --zone=us-west1-b
env:
GCP_PROJECT_ID: ${{ secrets.GCP_PROJECT_ID }}
以上でデプロイの自動化までできました!
できあがったもの
dev.toの公開記事取得APIを使用して、リプライで受け取った単語を検索キーワードとし、ヒットした記事のタイトルとリンクをリアルタイムにリプライするTwitter Botです。
よかったら使ってみてください。
https://twitter.com/dev_reply_bot
リポジトリ
https://github.com/EringiV3/dev-article-reply-twitter-bot
感想
gcloudコマンドがとても便利で、デプロイの自動化も特に詰まることなくできました。
コマンド一つでGCEインスタンス上のコンテナ更新できるの凄いです。
ただ、GCEにデプロイできるコンテナは1つまでらしいので、複数のコンテナをデプロイする必要がある場合はGoogle Kubernetes Engineを使用してくださいと公式のドキュメントに書いてありました。
GCPのドキュメントは丁寧かつ知識のない人でも読みやすいようにできていて、これからもGCPを積極的に使いたいという気持ちになります。
GAE, GCEにデプロイするワークフローの作成を体験できたので、次なにかデプロイするときはCloud Runを使ってみたいです。
常時起動しておく必要があるアプリケーションの場合は、GAEは向かず、GCEのほうが適していることはわかりましたが、HTTPリクエストのたびに起動すればよいアプリケーションの場合、GAEとCloud Runどちらが適しているか、手を動かして理解したくなりました。