【GCP】CloudRun × GitHub Actionsを使用したデプロイ自動化を実装する

Docker

どうも、株式会社KIYONOにてエンジニアをしております。

GCP上でAWSのFargateに相当するコンテナサービスを探していましたらCloud Runが非常に便利そうだと感じたのでGitHubActionsと絡めたAPIのデプロイ自動化の流れをご紹介致します。

1.前提条件

  • GCPアカウントをセットアップ済み
  • “Hello, World”などを返す最小単位のAPIが構築済みである

2.使用技術

名称 説明
Go 1.18 今回使用するプログラミング言語(※任意)
Gin 今回使用するhttpフレームワーク(※任意)
Container Registry コンテナレジストリサービス
Cloud Run コンテナ実行環境
Github Actions GitHubで使用できるCI/CDサービス

3.全体構成

構成としては、

mainブランチにプッシュ→GitHubActions起動→GCRへイメージをプッシュ→CloudRunへデプロイ

といったシンプルなかたちとなります。

4.準備

本記事ではDockerコンテナ上で動作する基本的なAPIが構築済みの前提で話を進めていきます。

プロジェクト構成

.
├── .github
│ └── workflows
│  └── deploy.yml
├── Dockerfile
├── go.mod
├── go.sum
└── main.go

主要なファイル

  • main.go

Hello, Worldをレスポンスする最小構成のAPIを定義します。

package main

import (
  "log"
  "net/http"
  "os"
  "github.com/gin-gonic/gin"
)

func main() {
  environment := os.Getenv("ENV")
  if environment == "PRODUCTION" {
    gin.SetMode(gin.ReleaseMode)
  }

  router := gin.Default()
  router.GET("/", func(ctx *gin.Context) {
   ctx.JSON(http.StatusOK, gin.H{"message": "Hello, World"})
  })


  if err := router.Run(":8080"); err != nil {
   log.Fatal("Server failed: ", err)
  }
}
  • Dockerfile

Goはビルド済みバイナリでの実行が可能なので実行ステージにランタイムが不要です。

# Build stage
FROM golang:1.18-alpine3.15 AS builder
WORKDIR /app
COPY . .
RUN go build -o main main.go

# Run stage
FROM alpine:3.15

ARG ENV
ENV ENV ${ENV}

WORKDIR /app
COPY --from=builder /app/main .

EXPOSE 8080
CMD [ "/app/main" ]
  • .github/workflows/deploy.yml

GitHub Actionsのジョブを定義します。

name: Deploy

on:
  push:
    branches:
      - main

env:
  SERVICE_NAME: ${{ secrets.SERVICE_NAME }}
  PORT: ${{ secrets.PORT }}
  GCP_PROJECT_ID: ${{ secrets.GCP_PROJECT_ID }}
  GCP_REGION: ${{ secrets.GCP_REGION }}
  IMAGE: asia.gcr.io/${{ secrets.GCP_PROJECT_ID }}/${{ secrets.SERVICE_NAME }}:${{ github.sha }}

jobs:
  deploy-to-cloud-run:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout the repository
        uses: actions/checkout@v2

      - id: "auth"
        uses: "google-github-actions/auth@v0"
        with:
          credentials_json: "${{ secrets.GCP_SA_KEY }}"

      - name: Configure docker to use the gcloud cli
        run: gcloud auth configure-docker --quiet

      - name: Build a docker image
        run: docker build -t ${{ env.IMAGE }} .

      - name: Push the docker image
        run: docker push ${{ env.IMAGE }}

      - name: Deploy to Cloud Run
        run: |
            gcloud run deploy $SERVICE_NAME \
              --image $IMAGE \
              --port $PORT \
              --project $GCP_PROJECT_ID \
              --region $GCP_REGION \
              --platform=managed \
              --allow-unauthenticated \
              --quiet \
              --set-env-vars=ENV=PRODUCTION

上記ファイルの内の${{ secrets.GCP_PROJECT_ID }}などはGitHubリポジトリ単位で設定する必要のあるシークレット変数です。設定した値は公開されることが無くジョブ内で参照されるため機密性の高い情報やプロジェクトに依存する文字列の格納に適しています。

設定する各シークレットは以下の通りになります。

名称 説明
GCP_PROJECT_ID
使用するGCPプロジェクトのID
GCP_REGION
リージョン(※今回はasia-northeast1に設定)
GCP_SA_KEY
使用するGCPサービスアカウントのクレデンシャルjson
PORT
使用するポート番号(※今回は8080に設定)
SERVICE_NAME
任意のサービス名称

GCPサービスアカウントの作成

「IAMと管理」→「サービスアカウント」を選択しサービスアカウントを作成します。

サービスアカウントに対し適切なロールを付与します。最効率のロール設定ではありませんが以下の通りで問題無いです。

作成後はサービスアカウントの鍵(json形式)を作成しGitHubのシークレット(GCP_SA_KEY)として設定します。

準備としては以上となります。

5.実行

mainブランチにプッシュする

mainブランチにプロジェクトをpushするとGitHub Actionのジョブが動き出します。リポジトリ画面にて進捗を確認できます。

Cloud Runを確認する

ジョブが成功し、デプロイが完了したらGCPコンソールのCloud Runへ移動します。

以下のようにSERVICE_NAMEアプリケーションが展開されているはずなので、選択し自動割当されたドメインにブラウザでアクセスします。

アクセス後、{“message”:”Hello, World”} のようなJSONが表示されましたら成功です。

6.まとめ

いかがでしたでしょうか。実際CloudRunを使用してみた感想ですが、Fargateと同じく非常に使い勝手がよく手軽にアプリケーションを検証できるところにもメリットがあると感じました。デフォルトでSSL化をサポートしているのもスロングポイントです。ただし本番運用する場合はセキュリティ上、VPC、NAT、ルーティングの設定を行うなどより複雑な設定が求められると思いますのでそちら注意が必要です。

コメント

タイトルとURLをコピーしました