Goで書いたサーバーをデプロイする先を探していて、Google App Engine(SE)やArukas、Herokuなどを試してきたが、今回は新たにCloud Runを試したのでその手順をここに記しておく。
前提
- Google Cloud Platformのアカウント(請求先の登録が必要)
- Google Cloud Platformのプロジェクト作成
- Google Cloud SDKのインストール
- Dockerがインストールされていること+起動していること
この辺りの説明は省略。
Cloud Runの有効化(初回のみ)

Cloud consoleでCloud Runのページを開き、Cloud Runを有効にしておく。フルマネージド環境で使う場合は「CLOUD RUNの使用を開始する」を選べばOK。
検証用サーバープログラムの準備
リクエストがくるとHello worldを返すだけのシンプルなHTTPサーバーを用意した。
Cloud Runで動かすコンテナは、環境変数PORT
で指定されたポートでListenできるようにしておかなければいけないので、Listenするポート番号を引数で指定できるようにしている。(環境変数を直接参照しても良いが)
package main
import (
"fmt"
"net/http"
"os"
"strconv"
)
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello world\n")
}
func main() {
port, _ := strconv.Atoi(os.Args[1])
fmt.Printf("Starting server at Port %d", port)
http.HandleFunc("/", handler)
http.ListenAndServe(fmt.Sprintf(":%d", port), nil)
}
動作確認のため、ローカル3000版ポート指定で起動してみる。
go run main.go 3000
別のShellからcurlでリクエストを送ってみて、Hello worldが返ってきたらOK。サーバーを停止する。
curl http://localhost:3000/
Dockerイメージの作成
FROM golang:latest as builder
ENV CGO_ENABLED=0
ENV GOOS=linux
ENV GOARCH=amd64
WORKDIR /go/src/github.com/yokoe/cloudrunexp
COPY . .
RUN go build main.go
# runtime image
FROM alpine
COPY --from=builder /go/src/github.com/yokoe/cloudrunexp /app
CMD /app/main $PORT
alpineをベースに、最小限のサーバーのイメージを作る。サーバー起動時の引数に環境変数$PORT
を渡すことで、$PORT
番号のポートでListenするようにする。
docker build -t cloudrunexp .
ビルドに失敗する場合はDockerが起動しているか確認する。
docker run -e "PORT=3000" -p 3000:3000 -t cloudrunexp
動作確認用に$PORT
=3000で、サーバーを起動してみる。ポートフォワーディングをして、http://localhost:3000/
でコンテナ内のサーバーにアクセスし、レスポンスが返ってくることを確認する。
curl http://localhost:3000/
Container RegistryへのPush
作成したイメージをGoogle Container Registry(GCR)にPushする。
Container Registry APIの有効化(初回のみ)
Container Registry APIを有効にしたことがない場合は、コンソールから有効にしておく。

Docker認証ヘルパーの有効化(初回のみ)
gcloud auth login
gcloud auth configure-docker
gcloudで認証し、Docker認証ヘルパーを有効にすることで、docker push
コマンドでGCRにイメージをPushできるようになる。
タグをつける
docker tag cloudrunexp gcr.io/go-server-exp/cloudrunexp:firstbuild
アップデートしていく時に、どのイメージがどのビルドかわかるようにタグをつけておく。今回は最初なのでfirstbuild
というタグをつけた。
GCRにイメージをPushする
docker push gcr.io/go-server-exp/cloudrunexp:firstbuild
docker push
コマンドを使って、firstbuild
タグのついたイメージをGCRにPushする。

Pushに成功すると、Cloud consoleのContainer Registry画面でPushされたイメージのリストを確認できる。
サービスの作成
Container Registryでイメージの確認

Container Registryのイメージのメニューから「Cloud Runへデプロイ」を選ぶと、Cloud Runのサービス作成画面が開く。
サービスの作成

自分で管理しているGKE上で動かしたいわけではないので、フルマネージドを選ぶ。また、パブリック(誰でもアクセスできる)なウェブサーバーとして動かしたいので「未認証の呼び出しを許可」を選択。

コンテナイメージが、先ほどContainer Registryで選んだイメージになっていることを確認して「作成」する。

作成完了すると、早速利用可能となり、自動生成されたURLが表示される。アクセスしてみて、Hello worldが表示されれば成功。カスタムドメインを割り当てたい場合は、URL横のinfoボタンから、「MANAGE CUSTOM DOMAINS」に進み、マッピングを追加すれば簡単に利用できた。
なお、今回はサービスの設定、デプロイはWeb UI経由で行ったがCI経由、Terraformなどを使っても操作できる。
制限
リクエストを返した後の処理は停止されてしまうため、go routineを使って非同期処理を発火させる、みたいなことはできない。重い処理を実行する場合はCloud Tasksなどの処理と組み合わせる必要があり、若干手間がかかる。
感想
GKEでDeploymentやService、Ingressの設定をするのに比べると非常に楽だった。カスタムドメインの割当ても簡単だったし、ちょっとしたHTTPサーバーを立ち上げるのには結構良さそう。
HerokuのDocker Deployも同様に簡単で良かったが、GCSやCloudSQLなどGCP系のサービスと組み合わせる場合はCloud Runも良さそう。
参考