はじめに
最近は Go でのバックエンド開発やインフラ周りも少しずつ触る機会が増えてきたので備忘録としてまとめてみました。
この記事で書くこと
- Go と Docker で作ったアプリを docker-compose で起動する方法
- 上記で作ったアプリを Github Actions 経由で Cloud Run にデプロイする方法
この記事で書かないこと
- Go言語の基礎
- Docker / docker-compose の基礎
- Github Actions の基礎
事前準備
以下の項目は事前に設定しておいてください。
すでに登録済みの方はスルーでOKです。
GCPアカウントの作成
- Google Cloud の公式サイトにアクセス
- ページ右上の [無料で始める] ボタンをクリック
- Google アカウントでログインしてください。もし Google アカウントをお持ちでない場合は、[アカウントを作成] ボタンをクリックして新しい Google アカウントを作成
- アカウント作成フォームに必要事項を入力(必要な情報については、Google の指示に従ってください)
- 必要な情報を入力したら、Google Cloud Platform にアクセスするための支払い情報を入力(クレジットカード情報を入力するか、銀行
- 口座情報を使用して支払いを行うことができます。ただし、無料枠を超えた場合にのみ、料金が発生することに注意してください。)
プロジェクトの作成
- アカウントを作成した後、Google Cloud Console にアクセスして、[プロジェクトを作成] ボタンをクリック
- プロジェクト名を入力し、[作成] ボタンをクリック。プロジェクトIDが自動的に生成されます。
- Cloud Run APIを有効にします。左側のメニューから[APIとサービス] > [ダッシュボード]をクリックします。[Cloud Run API] を検索し、APIを有効にする。
gcloud コマンドを使えるように
gcloudコマンド
は、Google Cloud Platformの様々なリソースを管理するために使用されるコマンドラインツールです。gcloudコマンドを使用することで、仮想マシン、データストレージ、データベース、アプリケーションサービスなどのGoogle Cloud Platformのリソースを作成、管理、監視することができます。
- こちらから gcloud コマンドをインストール
- gcloudコマンドを使用してログイン。gcloudコマンドを使用して、Google Cloud Platformにログインすることができます。以下のコマンドを使用してログインしてください。
gcloud auth login
- 作成したプロジェクト一覧を以下のコマンドで確認。プロジェクトが作成されていたら表示されるはず。
gcloud projects list
手順 1. Go と Docker の環境構築
早速 Docker コンテナ上で Go言語を使ってアプリを作成していきましょう。ここでは
- docker-compose でコンテナを起動
- ルートパス("/")にリクエストが来たときに HTTP レスポンスとして "Hello, World!!" という文字列を返す
までやっていきます。
プロジェクトの作成
適当なディレクトリでプロジェクトを作成し、以下のようなディレクトリ構成を作成します。go.mod と go.sum は go mod init
した時に自動生成されるので手動で作る必要はありません。
project
├── Dockerfile
├── README.md
├── backend
│ ├── cmd
│ │ └── main.go
│ ├── go.mod
│ └── go.sum
└── docker-compose.yml
Goプロジェクトの作成
backend ディレクトリに移動し、以下のコマンドを実行してGoプロジェクトを作成します。ここでgo.mod と go.sumが生成されます。
cd backend
go mod init example.com/myproject
main.go を作成します。
mkdir cmd
cd cmd
touch main.go
main.go ファイルにアプリケーションのコードを追加します。
package main
import (
"fmt"
"net/http"
)
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, World!!")
})
http.ListenAndServe(":8080", nil)
}
Dockerfile の作成
プロジェクトのルートディレクトリに Dockerfile を作成します。
FROM golang:1.18-alpine
WORKDIR /app
COPY backend/ .
RUN go build -o main ./cmd/main.go
EXPOSE $PORT
CMD ["/app/main"]
-
FROM golang:1.18-alpine
: golang:1.18-alpine イメージをベースにして新しいイメージを作成します。これは、Go 1.18 がインストールされた軽量な Alpine Linux ベースのイメージです。 -
WORKDIR /app
: 作業ディレクトリを /app に設定します。以降のコマンドはこのディレクトリで実行されます。 -
COPY backend/ .
: backend/ ディレクトリの内容を、現在の作業ディレクトリ(/app)にコピーします。 -
RUN go build -o main ./cmd/main.go
: go build コマンドを実行し、./cmd/main.go をコンパイルして実行可能なバイナリ main を作成します。 -
EXPOSE $PORT
: 環境変数 $PORT で指定されたポート番号を公開します。これにより、コンテナ外からアプリケーションにアクセスできるようになります。 -
CMD ["/app/main"]
: コンテナが実行されると、/app/main バイナリが実行されます。これにより、アプリケーションが起動します。
docker-compose.yml の作成
version: '3'
services:
backend:
build:
context: .
dockerfile: Dockerfile
ports:
- '8080:8080'
-
version: '3': この
docker-compose.yml
ファイルが使用する Docker Compose のバージョンを3
に設定します。 -
services: このセクションでは、Docker Compose で定義するサービス(コンテナ)をリストします。
-
backend: サービス名として
backend
を定義します。このサービスは、以下の設定に従ってコンテナを作成および実行します。-
build: このセクションでは、Docker イメージのビルド方法を指定します。
- context: .: イメージのビルドコンテキストとして、現在のディレクトリを指定します。
-
dockerfile: Dockerfile:
Dockerfile
という名前のファイルを使用してイメージをビルドします。
-
ports: ホストとコンテナ間で公開するポートのマッピングを指定します。
-
- '8080:8080': ホストのポート
8080
をコンテナのポート8080
にマッピングします。これにより、ホストからコンテナ内のアプリケーションにアクセスできるようになります。
-
- '8080:8080': ホストのポート
-
build: このセクションでは、Docker イメージのビルド方法を指定します。
-
backend: サービス名として
イメージの作成とアプリケーションの起動
docker-compose up --build
http://localhost:8080/ にアクセスすると Hello World が表示されているはず。ここまでできたら Github への push も忘れずにしましょう。
手順 2. コンテナを Cloud Run にデプロイ
docker-compose で起動できることが確認できたらまずは手動で cloud run へデプロイしてみましょう。
Dockerイメージをビルド/プッシュする
手順1で作成した Dockerfile を下記コマンドでビルドします。
docker build -t gcr.io/[PROJECT_ID]/[IMAGE_NAME]:[TAG] .
gcr.io/[PROJECT_ID]/[IMAGE_NAME]:[TAG]
は Google Container Registry(GCR)を使ってイメージを管理する場合のリポジトリ名の形式です。gcr.io は GCR のホスト名、[PROJECT_ID] は GCP プロジェクトの ID、[IMAGE_NAME] はイメージ名、[TAG] はタグ名です。
次にビルドしたコンテナイメージを、Google Container Registry(GCR)などのコンテナレジストリにアップロードします。
docker push gcr.io/[PROJECT_ID]/[IMAGE_NAME]:[TAG]
Cloud Run にデプロイする
下記コマンドを実行すると Clou Run にデプロイできます。
gcloud run deploy [SERVICE-NAME] \
--image gcr.io/[PROJECT-ID]/[IMAGE-NAME]:[TAG] \
--platform managed \
--allow-unauthenticated \
--region [REGION]
手順 3. GitHub Actions で自動デプロイ
Cloud Run へのデプロイを Github Actions 経由で自動デプロイできるようにしていきます。
deploy.yml の作成
プロジェクトのルートに .github/workflows/deploy.yml
を作成してください。
name: Deploy to Google Cloud Run
on:
push:
branches:
- main
# 下記は適宜書き換えてください
env:
GCP_PROJECT_ID: プロジェクトの名前
GCP_REGION: リージョン
IMAGE_NAME: gcr.io/プロジェクトの名前/イメージの名前
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Set up Cloud SDK
uses: google-github-actions/setup-gcloud@v1
- name: Authenticate with Google Cloud
uses: google-github-actions/auth@v0.4.0
with:
credentials_json: ${{ secrets.GCP_SA_KEY }}
- name: Configure Docker
run: gcloud auth configure-docker
- name: Build and push Docker image
run: |
TAG=$(echo $GITHUB_SHA | head -c7)
docker build -t ${IMAGE_NAME}:${TAG} .
docker push ${IMAGE_NAME}:${TAG}
- name: Deploy to Cloud Run
run: |
TAG=$(echo $GITHUB_SHA | head -c7)
gcloud run deploy web-push-demo \
--image ${IMAGE_NAME}:${TAG} \
--platform managed \
--region ${GCP_REGION} \
--allow-unauthenticated
-
name: ワークフローの名前です。この例では、
Deploy to Google Cloud Run
としています。 -
on: ワークフローのトリガーとなるイベントを指定します。この例では、
main
ブランチへのpush
イベントがトリガーとなります。 -
env: ワークフロー全体で使用する環境変数を定義します。この例では、
GCP_PROJECT_ID
、GCP_REGION
、IMAGE_NAME
の 3 つの環境変数が設定されています。 -
jobs: ワークフロー内で実行されるジョブを定義します。この例では、
deploy
という名前のジョブが 1 つあります。 -
runs-on: ジョブが実行される GitHub Actions のランナーを指定します。この例では、
ubuntu-latest
を使用しています。 -
steps: ジョブの中で実行されるステップを定義します。この例では、以下のステップがあります。
-
Checkout code:
actions/checkout@v2
アクションを使用して、リポジトリのコードをチェックアウトします。 -
Set up Cloud SDK:
google-github-actions/setup-gcloud@v1
アクションを使用して、Google Cloud SDK をセットアップします。 -
Authenticate with Google Cloud:
google-github-actions/auth@v0.4.0
アクションを使用して、Google Cloud への認証を行います。GCP_SA_KEY
シークレットを使用して、サービスアカウントの認証情報を提供します。 -
Configure Docker:
gcloud auth configure-docker
コマンドを実行して、Docker クライアントが Google Container Registry への認証を行えるように設定します。 -
Build and push Docker image: Docker イメージをビルドし、Google Container Registry にプッシュします。このステップでは、
GITHUB_SHA
(コミットの SHA)を使用してタグを生成し、イメージをビルドしてプッシュします。 -
Deploy to Cloud Run: Cloud Run にデプロイを行います。先ほどビルドされた Docker イメージを使用して、Cloud Run サービスをデプロイします。環境変数
GCP_REGION
およびIMAGE_NAME
が使用されます
-
Checkout code:
GCPコンソールからサービスアカウントの作成
- 先ほど作成したGCPのプロジェクトへ移動し、左側のナビゲーション メニューから、IAM と管理 をクリックし、「サービス アカウント」を選択します。
- 「サービスアカウント」ページが表示されます。「+サービスアカウントの作成」ボタンをクリックします。
- 「サービスアカウント名」フィールドに、わかりやすい名前を入力します。オプションで「サービスアカウントの説明」も入力できます。 「作成」ボタンをクリックして次に進みます。
- 「サービスアカウントの権限を付与する」画面で、このサービスアカウントに必要なロールを追加します(他のサイトでは「Cloud Run サービスエージェント」「Cloud Run 管理者」「ストレージ管理者」だけ追加しておけばOKと書いてたのですが、自分は「storageオブジェクト」の権限も付与しないと上手くいきませんでした)
- オプションで、ユーザーアカウントやサービスアカウントを追加して、このサービスアカウントのリソースへのアクセスを制御することができます。設定が完了したら、「完了」をクリックします。
GitHub リポジトリに秘密鍵を設定
deploy.yml
では、秘密鍵は ${{ secrets.GCP_SA_KEY }}
として参照されています。この値は、GitHub リポジトリのシークレットから取得されます。シークレットは、リポジトリ設定の「Secrets」セクションに保存されており、GitHub Actions のワークフローでのみアクセス可能です。
GCPコンソールからの操作
- 先ほどGCPコンソール上から作成したサービスアカウントの行にある「編集」アイコン(鉛筆)をクリックします。
- 「キー」タブに移動し、「キーの追加」ボタンをクリックし、「JSON」を選択して、「作成」をクリックします。
- サービスアカウントキーの JSON ファイルがダウンロードされます。このファイルには、サービスアカウントの認証情報が含まれています
Github リポジトリからの操作
- ソースコードを管理してる Github リポジトリを開き、Settings > Secrets And Variables を開き、New repository secret をクリックしてください
- Name を GCP_SA_KEY、Secret に先ほどダウンロードしたJSON形式の秘密鍵を貼り付けてください
ここまで設定できると main ブランチにマージされることで Cloud Run に自動デプロイされるようになっているはずです。
デプロイされたURLにアクセスすると「Hello World」が表示されます。
さいごに
備忘録として Go と Docker で使ったアプリを Github Actions を使って Cloud Run へデプロイする方法をまとめてみました。もし不明点やおかしな点があればご指摘ください。