どうも、株式会社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、ルーティングの設定を行うなどより複雑な設定が求められると思いますのでそちら注意が必要です。
コメント