はじめに
Streamlit のサービスをCloudRunにデプロイするCI/CDを作ろう、と思ったら大変でした。
最初はGithub Actions で頑張ったのですがハマってしまい、結局、CloudBuild で実現しました。
Gemini先生がたくさん教えてくれたのですが、それでも肝心なところはうまくいきませんでした。主に権限の設定あたりです。メモを残しておきます。
内容
何をするか
まず最初にできたこと
- ターミナルから docker build, docker push で Google Cloud のArtifact Registry に push すること。
- ターミナルから cloudbuild.yaml を gcloud submit で指定して build/push する
- gcloud deploy run で Cloud run にdeploy する。
- github repository にpush すると cloudbuild で docker build/push し CloudRun に deploy する。
必要だったことは、Artifact Registryと service account の両方に権限の設定です。
- Artifact Registgry の作成
- そのArtifact Registryにサービスアカウントへアクセス権を与えること。
- サービスアカウントに Artifact への書き込み権限を与えること
ファイル構成
同じディレクトリに全てを置いてあります。
tree .
.
├── Dockerfile
├── app.py
├── cloudbuild.yaml
├── compose.yaml
├── pages
│ ├── 1_something.py
│ └── 2_foo.py
└── requirements.txt
Docker関係
pip のときroot だと警告が出たので、仮想環境で実行するようにしています。
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN bash -c "python3 -m venv .venv && source .venv/bin/activate && \
pip install --upgrade pip && \
pip install -r requirements.txt"
COPY app.py .
COPY pages/*.py /app/pages/
EXPOSE 8501
CMD [".venv/bin/streamlit", "run", "app.py", "--server.port=8501"]
ここでdocker build/ run は下記のコマンドで実行できます。
docker build --no-cache -t streamlit-app .
docker run -rm -p 8501:8501 --name my-streamlit-app streamlit-app:latest
これをまとめて管理するために、compose.yaml を書くこともできます。
version: "3.9"
services:
streamlit-app: # service name
build:
context: . # Dockerfile directory
dockerfile: Dockerfile
no_cache: true # (docker build --no-cache)
ports:
- "8501:8501" # port(host):port(container)
container_name: my-streamlit-app # container name (docker run --name)
image: streamlit-app:latest # image name:tag (docker build -t)
ターミナルで書きコマンドでdocker build/run できます。もちろん、build, up
docker compose up -d --build
Google Cloudでのアカウント
ターミナルで認証を通します。
gcloud auth login
今のconfiguration について調べます。
$ gcloud config configurations list
NAME IS_ACTIVE ACCOUNT PROJECT COMPUTE_DEFAULT_ZONE COMPUTE_DEFAULT_REGION
default True myname012@gmail.com my-project
$ gcloud config list
[core]
account = myname012@gmail.com
disable_usage_reporting = True
project = my-project
Your active configuration is: [default]
サービスアカウントの設定
登録しているサービスアカウントの調べてみます。デフォルトのサービスアカウントは下記のようです。
$ gcloud builds get-default-service-account
name: projects/my-cloud-run01/locations/global/defaultServiceAccount
serviceAccountEmail: projects/639188470809/serviceAccounts/012345678901-compute@developer.gserviceaccount.com
このアカウントをCI/CDに使っても良いのですが、別のものを用意することにします。
サービスアカウントの作成は、CUIでもブラウザ(console)からでも実行可能です。
Cloud Build のデフォルトのサービスアカウントの確認
$ gcloud projects describe my-project --format="value(serviceAccounts.email)"
プロジェクトに登録されているサービスアカウントは下記で確認できます。
gcloud iam service-accounts list --project=my-project
Cloud Buildのアカウントを作る。
$ gcloud iam service-accounts create cloudbuild --display-name="Cloud Build service account" --project=my-project
Created service account [cloudbuild].
Artifact Registry の作成
名前が app01
であるArtifact Registry が存在するか確認します。Region は東京にしています。
hogeが今回pushする予定のregistry です。
$ gcloud artifacts repositories list --location=asia-northeast1
Listing items under project my-project, location asia-northeast1.
ARTIFACT_REGISTRY
REPOSITORY FORMAT MODE DESCRIPTION LOCATION LABELS ENCRYPTION CREATE_TIME UPDATE_TIME SIZE (MB)
cloud-run-source-deploy DOCKER STANDARD_REPOSITORY Cloud Run Source Deployments asia-northeast1 Google-managed key 2025-02-07T13:56:33 2025-02-07T13:58:13 210.468
hoge DOCKER STANDARD_REPOSITORY test asia-northeast1 Google-managed key 2025-02-07T14:59:03 2025-02-17T23:40:48 3941.308
もしリポジトリが存在しない場合は、作成する必要があります。作成はconsoleからもできます。
gcloud artifacts repositories create hoge \
--repository-format=docker \
--location=asia-northeast1
--description="foo bar" \
--immutable-tags \
--async
imutable-tags のオプションがあると、push されているイメージのタグと同じになるイメージはpush できなくなります。
例えばlatest やv1.0 のように同じtag のモノをpush しようとするとエラーになりました。
あと、大事なのはこのレジストリへの書き込み権限を使用するサービスアカウントに与えることです。
Artifact Registryへのpush (docker コマンド)
DockerのGoogle Cloudとの間でのcredential で意味は理解できていません。が設定が必要です。
docker-credential-gcr
ヘルパーがインストールされていなければインストールします。
gcloud components install docker-credential-gcr
良く分かりませんが、下記を実行します。
docker-credential-gcr configure-docker
/home/xt/.docker/config.json configured to use this credential helper for GCR registries
そしてdocker registry に push します。
docker push asia-northeast1-docker.pkg.dev/my-project/hoge/app:tagtag
Artifact Registryへのpush (CloudBuildを利用)
Google Cloud のサービスであるCloud Buildを用いて同じことを行います。
内容をcloudbuild.yaml に書きます。
steps:
- name: 'gcr.io/cloud-builders/docker'
args: ['build', '-t', 'asia-northeast1-docker.pkg.dev/${PROJECT_ID}/foo1/my-python-app:${COMMIT_SHA}', '.']
- name: 'gcr.io/cloud-builders/docker'
args: ['push', 'asia-northeast1-docker.pkg.dev/${PROJECT_ID}/foo1/my-python-app:${COMMIT_SHA}']
- name: 'gcr.io/cloud-builders/gcloud'
entrypoint: 'gcloud'
args: ['run', 'deploy', 'myapp',
'--image', 'asia-northeast1-docker.pkg.dev/${PROJECT_ID}/foo1/my-python-app:${COMMIT_SHA}',
'--region', 'asia-northeast1',
'--platform', 'managed',
'--port', '8501',
'--memory', '1G',
'--max-instances', '3']
options:
defaultLogsBucketBehavior: REGIONAL_USER_OWNED_BUCKET
serviceAccount: my_cicd@my-cloud-run01.iam.gserviceaccount.com
環境変数PROJECT_IDはGoogle Cloud 1での project IDであり、COMMIT_SHA は git repository でのcommit の番号で、実行時に代入されます。
option で指定しているのはCloud Build を実行するサービスアカウントで、ターミナルで実行するときはサービスアカウントを指定する必要があります。ただし、指定が無ければdefault のサービスアカウントが使われるそうです。
下記でbuild + push ができました。
gcloud builds submit --config cloudbuild.yaml \
--service-account projects/my-project/serviceAccounts/github-delivery@my-project.iam.gserviceaccount.com \
--substitutions COMMIT_SHA=$(git rev-parse HEAD) .
Artifact Registry にあるdocker image の管理
ブラウザ(google cloud console)からいろいろできます。
ターミナルからも操作可能で、Registryにあるimage は下記コマンドで見れました。
$ gcloud artifacts docker images list asia-northeast1-docker.pkg.dev/PROJECT_ID/REPOSITORY_NAME/ --project=my-project
Artifact Registry に利用できる地域を表示します。
gcloud artifacts locations list
例えば今のcommit に対応するimage をregistry から削除するには下記でできました。
gcloud artifacts docker images delete asia-northeast1-docker.pkg.dev/PROJECT_ID/REPOSITORY_NAME/APP:$(git rev-parse HEAD) --quiet
Github 経由のCICD
ブラウザ画面の設定でできます。
まとめ
とりあえずGithub から Docker container を CloudRunにCI/CDの環境は作れました。Cloud側のIAMの設定でかなりはまりましたが、Artifact へのアクセス権さえうまく管理できれば、あとはgeminiさんの言う通りにすれば大丈夫だと思います。
折をみて文章を修正しようと思いますが、とりあえず今はこのあたりで。。
(2025/2/20)