はじめに
コミットごとにDokerのイメージを作るようにしました。
それぞれのコミットごとに完全動作するコンテナが出来上がります。コミットごとに別々の環境がデプロイされると開発が良くなると考えています。
これには
- CIの一つとしてイメージのビルドが通る、イメージを使ってテストを実行できる、といったことが可能になる
- それぞれのイメージでデプロイができ、実行(テスト)ができる
- 検証をする場合にイメージのビルドを行わず、プルすることができる
といったメリットがあります。
コミットごとデプロイについての関連記事です。
PWAアプリがブランチごとに自動デプロイされる開発フローを取り入れたらすごく捗った話
https://qiita.com/yousan/items/b2741110ca2c0dae6330
Dockerfileの準備
テスト用に Dockerfile
を作成しておきます。
FROM golang:latest
テスト用なのでどういったDockerfileでも構いません。
設定
CircleCIの設定
CircleCIでGCPを使う場合の参考ページです
https://circleci.com/docs/2.0/google-auth/
基本的にこのページに沿っていけば実現できるのですが、うまく動かないポイントも多いため注意が必要です。
まずCircleCIでAdd Project
し、GitHub(やGitLab, Bitbucket)と連携しておきます。
(GitHubとCircleCIの連携は済ませているとします)
GCPでのサービスアカウントの登録
GCP上でサービスアカウントを登録します。
作成したサービスアカウントからキーをJSONでダウンロードしておきます。
次に「IAM」から作成したサービスアカウントに対して権限を付与します。
権限 |
---|
Cloud Build サービス アカウント |
Storage オブジェクト管理者 |
Storage オブジェクト作成者 |
Storage オブジェクト閲覧者 |
閲覧者 |
Cloud Buildを実行するための権限、CGRにイメージをアップロードするためのCloud Storage関連の権限、プロジェクトを参照するための閲覧権限が必要でした。
思った以上に権限が必要で、足りないと途中でエラーが出るためその対処は大変です。
CircleCIによるGCPの参考ページにもGCRの場合には追加の権限が必要になる、との記載があります。
If you are having issues pushing container images to GCR you may need more granular permissions than the default service account provides. You can grant permission changes in the Cloud Storage IAM Console
https://circleci.com/docs/2.0/google-auth/
「プロジェクトの編集者」といった権限を与えるとなんでもできてしまうため権限が足りなエラーは解消しますが、自動化する場合には万が一の漏洩を考えて最小限の権限とすることが必要です。
ローカルでの試験
CircleCIでの手順に進む前にローカル環境から正しく動くか、権限が足りているか、ということを確認しておきます。
こうすることでCircleCI、GCPといった複数のサービスをまたがって行う作業に対してトラブルを早めに見つけられるようにしておきます。
まずプロジェクトIDとリージョン(ゾーン)を設定しておきます。(プロジェクト名をexampleとしていますが適宜読み替えてください)
$ export GOOGLE_PROJECT_ID=example
$ export GOOGLE_COMPUTE_ZONE=ap-northeast1
先ほどダウンロードしたCircleCI用のキーでgcloud
コマンドで認証を掛けます。
$ echo <ダウンロードしたキーの場所> | gcloud auth activate-service-account --key-file=-
Activated service account credentials for: [circleci@example.iam.gserviceaccount.com]
プロジェクトとリージョンの設定を行います。
$ gcloud --quiet config set project ${GOOGLE_PROJECT_ID}
$ gcloud --quiet config set compute/zone ${GOOGLE_COMPUTE_ZONE}
アカウントが切り替わっていることを確認しておきます。
$ gcloud config list
[compute]
zone = ap-northeast1
[core]
account = circleci@example.iam.gserviceaccount.com
disable_usage_reporting = False
project = example
Your active configuration is: [default]
先ほど作成したDockerfileをビルドしてみます。
$ gcloud builds submit --tag gcr.io/${GOOGLE_PROJECT_ID}/test .
Creating temporary tarball archive of 10 file(s) totalling 5.4 KiB before compression.
Uploading tarball of [.] to [gs://example_cloudbuild/source/1594367971.xxxxxxxxxxxxxxxx.tgz]
Created [https://cloudbuild.googleapis.com/v1/projects/xxxxxxxxxxxxxxxxxxxxxx].
.....
latest: digest: sha256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx size: 1795
DONE
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ID CREATE_TIME DURATION SOURCE IMAGES STATUS
xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx 2020-07-10T07:59:32+00:00 18S gs://example_cloudbuild/source/1594367971.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.tgz gcr.io/example/test (+1 more) SUCCESS
成功しました。
確認しておきます。
$ gcloud container images list-tags gcr.io/example/test
DIGEST TAGS TIMESTAMP
b413792axxxx latest 2020-07-07T18:20:07
正しく作成されていますね。
CircleCIへの組み込み
CircleCIでビルドが通るように設定を行います。
環境変数を設定します。
CircleCIのプロジェクトを開いた画面中にある Project Settings
から Environment Variables
を選択します。
それぞれの変数を設定しています。
鍵のJSONについては pbcopy
などを利用すると便利です。
$ cat ~/Download/example.json | pbcopy
環境変数名 | |
---|---|
GCLOUD_SERVICE_KEY | 先の手順で作成したサービスアカウントの鍵 |
GOOGLE_PROJECT_ID | プロジェクトID |
GOOGLE_COMPUTE_ZONE | コンピュートゾーン (ap-northeast1 ap-northeast2 など) |
下記のように3つの変数を設定します。
セットアップ
次にCircleCIの config.yml
を設定します。
CircleCIではgoogle/cloud-sdk
というイメージを使うとgcloud
が一通り揃っています。
version: 2.1
jobs:
build:
docker:
- image: google/cloud-sdk
steps:
- checkout
- run: |
echo $GCLOUD_SERVICE_KEY | gcloud auth activate-service-account --key-file=-
gcloud --quiet config set project ${GOOGLE_PROJECT_ID}
gcloud --quiet config set compute/zone ${GOOGLE_COMPUTE_ZONE}
gcloud builds submit --tag gcr.io/${GOOGLE_PROJECT_ID}/test .
コミット、プッシュをして動作させます。
circleci
コマンドが入っている場合、下記のように validate
を掛けておくと構文エラーをへらすことができます。
$ circleci config validate && git add .circleci/config.yml && git commit -m 'Add CircleCI config' && git push origin HEAD
CircleCIでのビルドを確認します。
問題がなければ正しくビルドされ、GCRにイメージが作成されているはずです。
Cloud Runでの実行
冒頭に述べた「それぞれのDockerイメージに対してテストを行う」を行いたいと思います。
GKEではクラスタ上にPodを作りますが、すべてのDockerイメージに対してPodを作成することは難しいです。というのもPodごとに動作メモリが必要で、クラスタで最大利用可能メモリが決まっており、それを超えてPodを作成することができません。
そのためビルド済みDockerイメージのテストをCloud Runを使って実行します。
参考: Google Cloud Run を使うまで
https://qiita.com/massie_g/items/5a9ce514eaa7c460b5e3
費用など
GCRでは Cloud Storage としてイメージが保管されるため、月々の費用がかかります。
2020年7月現在、概算で下記の通りです。
Standard のバケット料金は、1 GB あたり月額約 $0.026 です。
https://cloud.google.com/container-registry/pricing?hl=ja
巨大なイメージを管理する場合には注意が必要です。