【コンテナ自動ビルド/デプロイ】Google Cloud Cloud Buildのcloudbuild.yamlの書き方

# はじめに
担当案件でCI/CDを利用したコンテナ自動ビルド/デプロイをせよという要求があった。
これまでの案件の中でCI/CDや自動化そのものをほとんど利用していなかったため最初は戸惑ったが、なんとかコンテナを自動ビルドするところまで行けた。
本記事ではcloudbuild.yamlファイルの内容について最小限の書き方の説明をする。

## cloudbuild.yamlとは
Cloud Buildでビルドを開始するために使用できるビルド構成ファイル。ファイルの内容としては、利用したいコマンドを1つずつ書いていくようなイメージ。

## コンテナイメージをビルドしてCloud Runにデプロイするcloudbuild.yamlの例
※${PROJECT_ID}部分はビルド時に自動的にプロジェクトIDが入るようになっている。「リポジトリ名」、「Dockerイメージ名」、「Cloud Runサービス名」部分は各自で利用している名前に置き換えて実行して欲しい。
※東京リージョン利用の前提。他のリージョンの場合「asia-northeast1」部分を該当するリージョンに変更して欲しい。

```yaml:cloudbuild.yaml
steps:
  # (1)コンテナイメージのビルドを実行
  - name: "gcr.io/cloud-builders/docker"
    args:
      [
        "build",
        "-t",
        "asia-northeast1-docker.pkg.dev/${PROJECT_ID}/「リポジトリ名」/「Dockerイメージ名」",
        ".",
      ]
  # (2)ビルドしたコンテナイメージをArtifact Registryにプッシュ
  - name: "gcr.io/cloud-builders/docker"
    args:
      [
        "push",
        "asia-northeast1-docker.pkg.dev/${PROJECT_ID}/「リポジトリ名」/「Dockerイメージ名」",
      ]
  # (3)Artifact RegistryのコンテナイメージをCloud Runにデプロイ
  - name: "gcr.io/cloud-builders/gcloud"
    args:
      - "run"
      - "deploy"
      - "「Cloud Runサービス名」"
      - "--image"
      - "asia-northeast1-docker.pkg.dev/${PROJECT_ID}/「リポジトリ名」/「Dockerイメージ名」"
      - "--region"
      - "asia-northeast1"
```

## cloudbuild.yamlの説明
#### (0)cloudbuild.yamlの基本な文法について
・steps:ビルドステップ(Cloud Buildに実行させるアクションのまとまり)を記載
・name:ビルドステップで実行するアクション(実体はコマンドを実行するイメージ)を記載
→主要なコマンドはGoogle CloudのコンテナレジストリでDockerイメージが提供されている。"gcr.io/cloud-builders/docker"は、dockerコマンドを実行できる。
・args:「name:」で指定したアクション(コマンド)の引数を記載
→[]形式でも、-形式でも書ける模様

「steps:」のネストの中に必要な分の「name:」と「args:」を記載していくイメージ。

上記は最低限の設定であり、他にも記載できる内容がある。詳細は以下参照。
https://cloud.google.com/build/docs/build-config-file-schema?hl=ja

#### (1)コンテナイメージのビルドを実行
以下のコマンドを実行するイメージ。

```bash
docker build -t asia-northeast1-docker.pkg.dev/${PROJECT_ID}/「リポジトリ名」/「Dockerイメージ名」 .
```
※カレントディレクトリにDockerファイルとソースコードがある前提。

#### (2)ビルドしたコンテナイメージをArtifact Registryにプッシュ
以下のコマンドを実行するイメージ。

```bash
docker push asia-northeast1-docker.pkg.dev/${PROJECT_ID}/「リポジトリ名」/「Dockerイメージ名」
```
※Artifact Registryのレジストリ(asia-northeast1-docker.pkg.dev/${PROJECT_ID}/「リポジトリ名」部分)は事前に作成している前提。
※ビルド用の作業領域が(1)から引き継がれており、(1)で作成したコンテナイメージがそのままアップロードされる。
※タグの指定をしていないので、自動的に「latest」タグが付与される。

#### (3)Artifact RegistryのコンテナイメージをCloud Runにデプロイ
以下のコマンドを実行するイメージ。

```bash
gcloud run deploy　「Cloud Runサービス名」　--image　asia-northeast1-docker.pkg.dev/${PROJECT_ID}/「リポジトリ名」/「Dockerイメージ名」　--region　asia-northeast1
```
※(2)でアップロードしたArtifact Registryのコンテナイメージを利用して既存Cloud Runサービスの新リビジョンをデプロイ。タグの指定をしていないので、「latest」タグがついたコンテナイメージがデプロイされる。

#### (4)自動デプロイ完了
ビルドが成功していることをCloud Buildの履歴から、新リビジョンがデプロイされていることをCloud Runの該当サービスのページから確認する。

## cloudbuild.yamlを利用したコンテナ自動ビルド/デプロイのキック方法
・コマンドを利用する方法
　→cloudbuild.yaml、Dockerファイル、ソースコードがあるディレクトリで以下コマンドを実行
```bash
gcloud builds submit --config cloudbuild.yaml
```

・トリガーを利用する方法
　→Cloud Buildの「トリガー」から設定する。GitHub等のソースコードリポジトリへのPushやPullリクエストを契機にビルドを実行することができる。

![Build_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3311265/5715b6d4-be8e-bfb7-316c-4a3e1c10c9a1.png)

この場合、cloudbuild.yamlはリポジトリに含めておく(ロケーションの「リポジトリ」設定)か、設定画面上で直接内容を記載する(ロケーションの「インライン」設定)ことができる。cloudbuild.yamlのバージョン管理をするなら前者であるが、セキュリティ上cloudbuild.yamlを色んな人に編集されないようにするならば後者になると思われる。
![Build_03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3311265/1388bada-236a-29c2-0eaa-abe351b6b31f.png)


なお、Cloud Buildはセキュリティ上専用のサービスアカウントを利用して実行する。このサービスアカウントはIAMのページを見ても見当たらず、Cloud Buildの「設定」から権限の設定をする必要があるので注意が必要。
![Build_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3311265/5969acb8-8e49-dfde-77c7-68ae3d72bdbe.png)
→必要な権限を有効化する。

## 終わりに
Cloud Buildを利用したCI/CDは検討することや注意することが多く、実際に躓いた内容は本記事では書ききれないほど発生している。(権限周りや、GitHubとの連携等。)
また、Cloud Deployを利用したデプロイ方法の実践や、cloudbuild.yamlのエラーを考慮した記載(timeoutの設定等)はまだ検討ができていない。

CI/CD自体が奥が深くまだまだ勉強しないといけないことが多いと考えるが、一気に全てのことを実現するのではなく簡単な設定をして実際に動くことを確認しながら進めるのが良いと思われるので、これからも少しずつ歩みを進めていきたい。