🐳
Cloud Deploy用のcloudbuildでskaffold buildを使わない場合のサンプル
対象
- manifest.yamlとかすでに動かせる
- skaffold build使わないとき
前提
- イメージ名
server
想定 - cacheFromを効かせる
- Dockerfileは/deploy/Dockerfileに存在する
- substitutionはCloudBuildTriggerの環境変数として渡される
- cloudbuildリージョンは台湾
- skaffold buildは使わず docker buildで代替したい
cloudbuild.yaml
steps:
# ------------------------------------------------------------------------------------
# STEP 1: Artifact Registryから"server"サービスの最新イメージのタグを取得する
# ------------------------------------------------------------------------------------
- name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
id: 'Get Latest Image Tag'
entrypoint: 'bash'
args:
- '-c'
- |
# Artifact Registryで"server"イメージの最新版(最終更新日時順)のタグを取得する
gcloud artifacts docker images list $_ARTIFACT_REPOSITORY_PATH/server \
--include-tags \
--sort-by=~UPDATE_TIME \
--limit=1 \
--format='get(tags)' \
| head -n 1 > /workspace/latest_image_tag.txt || echo "" > /workspace/latest_image_tag.txt
echo "Latest tag found in Artifact Registry: $(cat /workspace/latest_image_tag.txt)"
# ------------------------------------------------------------------------------------
# STEP 2: Dockerイメージをビルドし、Artifact Registryにプッシュする
# ------------------------------------------------------------------------------------
- name: 'gcr.io/cloud-builders/docker'
id: 'Docker Build and Push'
secretEnv: ['TURBO_TOKEN', 'TIPTAP_PRO_TOKEN']
entrypoint: 'bash'
args:
- '-c'
- |
# STEP 1で取得した最新タグを読み込む
LATEST_TAG_FROM_REPO=$(cat /workspace/latest_image_tag.txt)
# 安定したフォールバックとして':latest'をキャッシュ元に指定
CACHE_ARGS="--cache-from=$_ARTIFACT_REPOSITORY_PATH/server:latest"
# もしArtifact Registryから最新タグが取得できていれば、それもキャッシュ元に追加
if [[ -n "$$LATEST_TAG_FROM_REPO" ]]; then
echo "✅ Caching from latest image in registry: $$LATEST_TAG_FROM_REPO"
CACHE_ARGS="$$CACHE_ARGS --cache-from=$_ARTIFACT_REPOSITORY_PATH/server:$$LATEST_TAG_FROM_REPO"
else
echo "⚠️ No existing image found in registry. Caching from 'latest' only."
fi
# 動的に生成したキャッシュ引数を使ってビルドを実行
docker build \
--tag=$_ARTIFACT_REPOSITORY_PATH/server:$SHORT_SHA \
$$CACHE_ARGS \
--file=deploy/Dockerfile \
.
# ビルドしたイメージをプッシュ
docker push $_ARTIFACT_REPOSITORY_PATH/server:$SHORT_SHA
env:
- 'DOCKER_BUILDKIT=1'
# ------------------------------------------------------------------------------------
# STEP 3: Cloud Deploy用のビルド成果物ファイル (artifacts.json) を手動で作成する
# ------------------------------------------------------------------------------------
- name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
id: 'Generate Build Artifacts'
entrypoint: 'bash'
args:
- '-c'
- |
# skaffold.yamlで定義されているイメージ名。STEP 2でビルドしたものと一致させる。
IMAGE_NAME_IN_SKAFFOLD="${_ARTIFACT_REPOSITORY_PATH}/server"
# 実際にプッシュしたイメージのフルパス付きタグ
IMAGE_TAG_WITH_PATH="${_ARTIFACT_REPOSITORY_PATH}/server:$SHORT_SHA"
# プッシュしたイメージのダイジェスト(一意なID)を取得
# イメージ名はSTEP 2でビルド&プッシュした 'server' を使用
DIGEST=$$(gcloud container images describe "$${IMAGE_TAG_WITH_PATH}" --format='get(image_summary.digest)')
# ダイジェストを含む完全なイメージ参照を作成
IMAGE_WITH_DIGEST="$${IMAGE_NAME_IN_SKAFFOLD}@$${DIGEST}"
# Cloud Deployが要求する正しい形式でJSONファイルを作成
# imageNameはskaffold.yamlで定義されているイメージ名と一致させる
echo "{\"builds\":[{\"imageName\":\"server\",\"tag\":\"$${IMAGE_WITH_DIGEST}\"}]}" > /workspace/artifacts.json
echo "✅ Generated /workspace/artifacts.json:"
cat /workspace/artifacts.json
# ------------------------------------------------------------------------------------
# STEP 4: Cloud Deployを使って"Service"をデプロイする
# ------------------------------------------------------------------------------------
- name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
id: 'Deploy Service'
entrypoint: gcloud
args:
- 'deploy'
- 'releases'
- 'create'
- 'rel-${SHORT_SHA}'
- '--delivery-pipeline=${_CLOUD_DEPLOY_SERVICE_PIPELINE}'
- '--region=${_REGION}'
- '--annotations=commitSha=$SHORT_SHA'
- '--source=.'
- '--skaffold-file=apps/api/deploy/skaffold.yaml'
- '--build-artifacts=/workspace/artifacts.json' # STEP 3で作成したファイルを参照
- '--gcs-source-staging-dir=${_GCS_SOURCE_SERVICE_STAGING_DIR}'
- '--impersonate-service-account=${_CLOUD_DEPLOY_SERVICE_RELEASER_EMAIL}'
env:
- 'IMAGE_TAG=$SHORT_SHA'
substitutions:
_REGION: by-terraform
_ARTIFACT_REPOSITORY_PATH: by-terraform
_CLOUD_DEPLOY_JOB_PIPELINE: by-terraform
_CLOUD_DEPLOY_SERVICE_PIPELINE: by-terraform
_GCS_SOURCE_JOB_STAGING_DIR: by-terraform
_GCS_SOURCE_SERVICE_STAGING_DIR: by-terraform
_CLOUD_DEPLOY_JOB_RELEASER_EMAIL: by-terraform
_CLOUD_DEPLOY_SERVICE_RELEASER_EMAIL: by-terraform
# https://cloud.google.com/build/docs/securing-builds/configure-user-specified-service-accounts?hl=ja#set_up_build_logs
# 設定しないとログエラーが発生する↓
# generic::invalid_argument: if 'build.service_account' is specified, the build must either (a) specify 'build.logs_bucket', (b) use the REGIONAL_USER_OWNED_BUCKET build.options.default_logs_bucket_behavior option, or (c) use either CLOUD_LOGGING_ONLY / NONE logging options
options:
logging: CLOUD_LOGGING_ONLY
skaffold build
は使っていないのでbuildプロパティには不要なものもありそう
skaffold.yaml
apiVersion: skaffold/v3
kind: Config
metadata:
name: hogehoge-server
build:
tagPolicy:
envTemplate:
# テンプレートをサポートするフィールドは限られている
# https://skaffold.dev/docs/environment/templating/#list-of-fields-that-support-templating
template: '{{ .IMAGE_TAG }}' # 環境変数により置換される
artifacts:
- image: server
context: .
docker:
dockerfile: deploy/Dockerfile
local:
useBuildkit: true
push: true
deploy:
cloudrun: {}
# マニフェストファイルの指定
manifests:
rawYaml:
- manifest.yaml
manifest.yaml
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
name: hogehoge-server
annotations:
run.googleapis.com/ingress: all
spec:
template:
metadata:
annotations:
autoscaling.knative.dev/maxScale: '5' # from-param: ${max_scale}
autoscaling.knative.dev/minScale: '0' # from-param: ${min_scale}
run.googleapis.com/sessionAffinity: 'false'
spec:
containerConcurrency: 80
timeoutSeconds: 300
serviceAccountName: dummy # from-param: ${service_account_name}
containers:
- image: server # skaffold.yamlのnameにあわせる
ports:
- name: http1
containerPort: 3000
resources:
limits:
cpu: 1000m
memory: 512Mi
startupProbe:
timeoutSeconds: 240
periodSeconds: 240
failureThreshold: 1
tcpSocket:
port: 3000
Discussion