はじめに
Go で書いた CLI ツールを定期実行させたかったので、普段よく使ってるGCPの環境で試してみた。Docker で CLI を実行するイメージを作って、CloudRun Job で実行させるようにする。定期実行のタイミングは Github Actions のスケジュールのイベントで指定する。といった感じ。
CLI はサイトのデータをスクレイピングして DB に保存するツールで、この CLI を毎週自動で実行するようにしたかったのがモチベーション。
📝 やること
- CLI ツールを Docker 化する(Dockerfile を用意する)
- Docker Image をリポジトリ(artifact registry)に登録する
- ここまでの操作をCI で自動化する(1 と 2 を CI で自動化する)
- Cloud Run Job を使って Docker 化した CLI を定期実行する
1️⃣ CLI ツールを Docker 化する
Dockerfile を用意する。
# Use an official Golang runtime as a parent image
FROM golang:alpine
# Set the working directory inside the container
WORKDIR /app
# Copy the local package files to the container's workspace
COPY . /app
# Build the Go application inside the container
RUN go build -o ageage-collector cmd/ageage-collector/main.go
# Define the command to run your application
ENTRYPOINT ["./ageage-collector"]
ビルドする。
# ビルドする
$ docker build -t shimabukuromeg/ageage-collector:latest .
$ docker images | grep ageage
shimabukuromeg/ageage-collector latest f47a90783376 About a minute ago 669MB
# 手元で実行してみる(envの指定はサンプルのCLIの都合)
$ docker run --env DSN="postgresql://<your user name>:<your password>@<your endpoint>:<your port>/<your db name>" shimabukuromeg/ageage-collector
2️⃣ Docker Image をリポジトリ(Artifact Registry)に登録する
なければ、Artifact Registry を作る。
$ gcloud artifacts repositories create myrepo --location=asia-northeast1 --repository-format=docker
ビルドする。
$ docker build ./ -t asia-northeast1-docker.pkg.dev/${PROJECT_ID}/myrepo/ageage-collector
プッシュする。
$ docker push asia-northeast1-docker.pkg.dev/${PROJECT_ID}/myrepo/ageage-collector
作られた。
3️⃣ ここまでの操作をCI で自動化する
手元のローカルの環境でビルドとプッシュを試したが、CI で自動でできるようにする。
-
.github/workflows/build-image.yml
を作成する。 -
secrets
の変数を github に登録する。
name: Docker Image Build
on:
push:
tags:
- "v*"
workflow_dispatch:
permissions:
contents: "read"
id-token: "write"
env:
# 例. projects/<プロジェクト番号>/locations/global/workloadIdentityPools/<プールID>/providers/github
# projects/999999999999/locations/global/workloadIdentityPools/my-pool-id/providers/github
WORKLOAD_IDENTITY_PROVIDER: ${{ secrets.WORKLOAD_IDENTITY_PROVIDER }}
SERVICE_ACCOUNT: ${{ secrets.SERVICE_ACCOUNT }}
IMAGE_HOST: "asia-northeast1-docker.pkg.dev"
IMAGE_TAG_BASE: ${{ secrets.IMAGE_TAG_BASE }} # 例. プロジェクトID/artifact_registry名/イメージ名
jobs:
build-push:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- id: "auth"
name: "Authenticate to Google Cloud"
uses: "google-github-actions/auth@v1"
with:
workload_identity_provider: ${{ env.WORKLOAD_IDENTITY_PROVIDER }}
service_account: ${{ env.SERVICE_ACCOUNT }}
- name: "Set up Cloud SDK"
uses: "google-github-actions/setup-gcloud@v1"
- name: Docker Setup
id: buildx
uses: docker/setup-buildx-action@v2
- name: Authorize Docker push
id: authorize-docker-push
shell: bash
run: gcloud auth configure-docker ${{ env.IMAGE_HOST }}
- name: Docker Image Build and Push
id: docker-build
uses: docker/build-push-action@v4
with:
push: true
provenance: false
tags: "${{ env.IMAGE_HOST }}/${{ env.IMAGE_TAG_BASE }}:latest"
build-args: |
APP_VERSION=${{ github.sha }}
cache-from: type=gha
cache-to: type=gha,mode=max
secrets
の秘匿情報を github 側に追加して、workflowの定義から読み込めるようにする。
CI を実行して成功したらOK
4️⃣ Cloud Run Job を使って CLI を定期実行する
.github/workflows/exec-ageage-collector.yml
を作成してワークフローを定義する。
name: Exec Ageage Collector
on:
push:
tags:
- "v*"
workflow_dispatch: # 手動実行用
schedule:
- cron: "0 23 * * SUN" # 日曜日の23時に実行
permissions:
contents: "read"
id-token: "write"
env:
# 例. projects/<プロジェクト番号>/locations/global/workloadIdentityPools/<プールID>/providers/github
# projects/999999999999/locations/global/workloadIdentityPools/my-pool-id/providers/github
WORKLOAD_IDENTITY_PROVIDER: ${{ secrets.WORKLOAD_IDENTITY_PROVIDER }}
SERVICE_ACCOUNT: ${{ secrets.SERVICE_ACCOUNT }}
RUN_SERVICE_ACCOUNT: ${{ secrets.RUN_SERVICE_ACCOUNT }}
IMAGE_HOST: "asia-northeast1-docker.pkg.dev"
IMAGE_TAG_BASE: ${{ secrets.IMAGE_TAG_BASE }} # 例. プロジェクトID/artifact_registry名/イメージ名
GCP_REGION: asia-northeast1
jobs:
exec-cli:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- id: "auth"
name: "Authenticate to Google Cloud"
uses: "google-github-actions/auth@v1"
with:
workload_identity_provider: ${{ env.WORKLOAD_IDENTITY_PROVIDER }}
service_account: ${{ env.SERVICE_ACCOUNT }}
- name: "Set up Cloud SDK"
uses: "google-github-actions/setup-gcloud@v1"
- name: Exec Ageage Collector
id: ageage-collector
run: |
gcloud config set run/region $GCP_REGION
set +e
gcloud run jobs describe ageagecli --quiet >/dev/null
job_exists_check=$?
set -e
if [ $job_exists_check -eq 0 ]; then
jobs_cmd="update"
else
jobs_cmd="create"
fi
echo ": $jobs_cmd a job"
gcloud run jobs $jobs_cmd ageagecli --image="${{ env.IMAGE_HOST }}/${{ env.IMAGE_TAG_BASE }}:latest" --max-retries=1 --service-account="${{ env.RUN_SERVICE_ACCOUNT }}" --set-secrets="DSN=DATABASE_URL:latest"
gcloud run jobs execute ageagecli --wait --format=json
成功
参考