Cloud Runにgolangアプリケーションをデプロイ

# 概要
先日私が担当しているサービスをAWSからGCPに移行する作業を行いました。
元々はAWSのEKSで動いていたのですが、この度GCPのCloud Runにサービスを移行することとなりました。
その際Cloud Runに触ったことがなかったためキャッチアップした内容をまとめていきます。

この記事では下記構成を目標にまとめていきます。
ローカル環境からコマンドを叩くことで、Cloud Runをとりあえず動かすことができる、を目指します。

![スクリーンショット 2022-11-20 15.48.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/434850/fe964712-0776-6ef6-f4dd-cdd533424df7.png)


# Cloud Run とは
Webアプリケーションをコンテナとして構築できるサーバレスサービスです
サーバーレスであるためサーバー管理の手間が少なく、負荷増大などに対する対策も元々の機能として持っていることが大きなメリットだと感じています。

下記のような機能を備えています。
- コンテナイメージを使ったデプロイによる実行環境の流用
- コンテナのオートスケーリング（0～1000コンテナインスタンス）
- トラフィックのコントロール(内部トラフィックのみを許可、ロードバランサからのトラフィックのみを許可など)
- Cloud Buildを用いた自動デプロイ
- 従量課金制: 使用したリソース（CPU、メモリ）に対して課金

# docker imageの作成
Cloud Runではdockerイメージを元にデプロイを行うため、dockerイメージとソースコードを用意しておくことが前提となります。
今回は私が作成したgolangアプリケーションのイメージを使います。
makefileなどを使用しているのでわかりづらいかもしれません・・
GCPが[golangのサンプルのイメージ](https://github.com/GoogleCloudPlatform/golang-samples/tree/main/run/helloworld)を用意してくれているのでこちらを使用するでもいいと思います。

作成したDockerfileがローカルでbuildできることを確認してください。

```dockerfile
FROM golang:1.19-buster AS build

WORKDIR /go/src/github.com/qiita/myapp

COPY . /go/src/github.com/qiita/myapp

RUN apt-get update && apt-get install -y unzip clang-format

RUN set -e && make myapp.build-for-docker

FROM alpine:3.16.2

WORKDIR /app

RUN apk --update add --no-cache ca-certificates dumb-init

COPY --from=build /go/src/github.com/toreta/myapp/bin/myapp /app

EXPOSE 8080

ENTRYPOINT ["/usr/bin/dumb-init", "--"]
CMD ["./myapp"]
```

# Cloud Build上でイメージをbuildする
次にGCPのCloud Build上でdockerイメージをbuildします。
ローカルでbuildしたイメージをArtifact Registryにpushするということも可能なのですが、コマンドを管理していくのが面倒なので今回は`cloudbuild.yaml`を使います。

下記のようなyamlを`cloudbuild.yaml`というファイル名で用意してください。
この時、GCPのArtifact Registryで `test-golang-repo` というリポジトリを作成しておいてください。
`${PROJECT_ID}`にはご自身のGCPのプロジェクトIDを入れてください。

```yaml
steps:
  - name: gcr.io/cloud-builders/docker
    args:
      - build
      - --no-cache
      - -t
      - asia-northeast1-docker.pkg.dev/${PROJECT_ID}/test-golang-repo/api:latest
      - .
      - -f
      - Dockerfile
    id: build the container image
```

その後、下記コマンドをローカルで実行してください
`cloudbuild.yaml`の設定値を元に、Cloud Buildを起動できます。
```bash
gcloud builds submit --config=cloudbuild.yaml 
```

このコマンドを実行すると、GCPのUIでCloud Buildが起動していることを確認できると思います。
Cloud Buildでイメージのbuildができることを確認できるはずです。

# イメージをArtifact Registryにpushする
上記までの作業で、イメージをbuildするところまでできました。
ですがCloud Runがデプロイするには、Artifact Registryからイメージをpullする必要があります。
なのでCloud BuildからArtifact Registryにイメージをpushする記述を追加します。

```yaml
steps:
  - name: gcr.io/cloud-builders/docker
    args:
      - build
      - --no-cache
      - -t
      - asia-northeast1-docker.pkg.dev/${PROJECT_ID}/test-golang-repo/api:latest
      - .
      - -f
      - Dockerfile
    id: build the container image

  - name: gcr.io/cloud-builders/docker
    args:
      - push
      - asia-northeast1-docker.pkg.dev/${PROJECT_ID}/test-golang-repo/api:latest
    id: push the container image to Artifact Registry
```

# Cloud Runにデプロイする
これでArtifact Registryにイメージが格納されました。
最後にCloud Runでイメージをpullしてデプロイします。

```yaml
steps:
  - name: gcr.io/cloud-builders/docker
    args:
      - build
      - --no-cache
      - -t
      - asia-northeast1-docker.pkg.dev/${PROJECT_ID}/test-golang-repo/api:latest
      - .
      - -f
      - Dockerfile
    id: build the container image

  - name: gcr.io/cloud-builders/docker
    args:
      - push
      - asia-northeast1-docker.pkg.dev/${PROJECT_ID}/test-golang-repo/api:latest
    id: push the container image to Artifact Registry

  - name: gcr.io/google.com/cloudsdktool/cloud-sdk
    entrypoint: gcloud
    args:
      - run
      - deploy
      - api
      - --allow-unauthenticated
      - --image
      - asia-northeast1-docker.pkg.dev/${PROJECT_ID}/test-golang-repo/api:latest
      - --region
      - asia-northeast1
      - --platform
      - managed
```

もしアプリケーションの起動に環境変数が必要な場合は ` --set-env-vars` を使用すればCloud Runの環境変数に設定できます。
```yaml
  - name: gcr.io/google.com/cloudsdktool/cloud-sdk
    entrypoint: gcloud
    args:
      - run
      - deploy
      - api
      - --allow-unauthenticated
      - --image
      - asia-northeast1-docker.pkg.dev/${PROJECT_ID}/test-golang-repo/api:latest
      - --region
      - asia-northeast1
      - --platform
      - managed
      - --set-env-vars
      - DB_HOST=XXXXXXXX
```

# Cloud RunのAPIを叩く
Cloud RunのUIを見にいくと、画像のような表示になっているはずです。
このURLに対してAPIを叩くことで、アプリケーションの機能を使うことができます。


![スクリーンショット 2022-11-20 16.54.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/434850/bb919319-7264-2143-0d2c-7b1a9d38d451.png)

# 補足
画像右上の`継続的デプロイ`を選択することで、githubなどと連携してCloud Runに差分をデプロイすることが可能です。
その際の構成図は下記のようになります。

![スクリーンショット 2022-11-20 17.09.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/434850/e7c023fc-1ce5-f27f-a99a-0d1e8984826a.png)

# まとめ
今回はCloud Runにごく簡単にデプロイするまでをまとめました

サーバーなので当然かもしれませんが、ロードバランサと連携することができたり、Cloud SQLというDBサービスと連携させたり、環境変数では暗号化のためにSecret Managerと連携したりすることができます。
作ったアプリケーションをサーバーで動かしCI/CDなどで継続運用する、サーバーはオートスケーリングなどの機能を備えていて最低限の使用に耐えうるというところを達成するまでがかなり簡単だなと感じました。
GCPのドキュメントもかなりわかりやすく整備されているので一度試していただければと思います。

# さいごに

トレタでは一緒に開発する仲間を募集しています。<br>
興味がある方は是非カジュアル面談へお越しください！

https://www.wantedly.com/companies/toreta/projects