Cloud Run へのデプロイに GitLab Runner を使う
はじめに
昨今ソースコードの管理には git
を使っている人が大多数かと思うのですが、リモートには GitHub
を使用するケースが多いのではないでしょうか。
GitHub
はとても良いサービスなのですが、業務で使用したいと思うとほぼ有料サービス加入必須であり、維持費がかかってきます。(必要経費ではありますが)
GitLab
は自分でサーバーを立ち上げる事が出来、CE版であれば基本的に無料で使用する事が出来ます。設定次第では完全プライベートな状態で運用でき、さらに維持費もサーバー運用コストのみです。
今回は、GitLab
をセットアップして、CIからクラウド (今回はGCP) にデプロイするまでの一連の流れを紹介したいと思います。
GitLab CE を docker-compose で立ち上げる
まずは GitLab
サーバーを立ち上げるのですが、docker-compose
を使うと拍子抜けするほど簡単に立ち上げる事が出来ます。
以前にQiitaで記事にしましたので、参照してみてください。
GitLab に Runner を追加する
GitLab
にも CI/CD
があり、GitHub
の GitHub Actions
と基本的には同じ役割を持つものですが、少し毛色が違います。
GitHub Actions
は GitHub
が用意した実行環境の中でコマンドを実行していきますが、GitLab
の CI/CD
は Runner
と呼ばれる実行環境を用意するところからスタートします。
自分で用意しないといけないとなると面倒な気がしてきますが、実はこのおかげでとても柔軟性の高い CI/CD
の環境が用意できます。
Runner
は Linux
・ Mac
・ Windows
用の各バイナリ、さらには Docker
のイメージや k8s
上で動かす Helm
チャートまであります。
これを利用して、例えば Mac
の Runner
を用意したら Windows
で開発していても Mac
や iOS
向けのアプリ書き出しが出来るし、複数の環境を用意したらそれぞれの環境用のアプリの書き出しが出来ます。
以前プロジェクトで RaspberryPI
向けのアプリを Electron
で作成する事になった際、 RaspberryPI
に Runner
をインストールして使用する事で簡単に CI
と連動した書き出し環境を作る事が出来、とても便利でした。
Runner の追加場所
GitLab
では、Runner
をどのレベルで共有するか選ぶ事が出来ます。
Shared Runner
GitLab
インスタンス全体で共有される Runner
です。
Adminエリアの「CI/CD」->「Runners」から登録でします。
Group Runner
グループの中でのみ使用できる Runner
です。
グループの「Settings」->「CI/CD」->「Runners」から登録します。
Project Runner
そのプロジェクトでのみ使用できる Runner
です。
プロジェクトの「Settings」->「CI/CD」->「Runners」から登録します。
Docker Runner を追加する
GitLab
本体と同じように、Ubuntu
上に docker-compose
で Docker Runner
を追加してみます。
docker-compose
が使用できる環境で設定ファイルを作成し、
version: '3'
services:
runner:
image: gitlab/gitlab-runner:v15.10.0
restart: always
volumes:
- ./gitlab-runner/config:/etc/gitlab-runner
- /var/run/docker.sock:/var/run/docker.sock
コマンドを実行します。
docker compose up -d
# もしくは docker-compose up -d
これで Runner
自体は立ち上がるのですが、 GitLab
本体に Runner
として登録する必要があります。
docker compose exec runner gitlab-runner register
対話式でコマンドが進行していくので、適宜入力していきます。
トークンは、登録する場所に合わせて前項を参照して取得して下さい。
Enter the GitLab instance URL (for example, https://gitlab.com/):
<URL>
Enter the registration token:
<TOKEN>
Enter a description for the runner:
[31c0105f5395]: test docker runner
Enter tags for the runner (comma-separated):
docker-runner
Enter optional maintenance note for the runner:
Registering runner... succeeded runner=TxvRhK_X
Enter an executor: parallels, docker+machine, instance, custom, docker-ssh, shell, ssh, virtualbox, docker-ssh+machine, kubernetes, docker:
docker
Enter the default Docker image (for example, ruby:2.7):
docker:dind
Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded!
Configuration (with the authentication token) was saved in "/etc/gitlab-runner/config.toml"
ここで大事になるのが、以下3点だと思っています。
executor
インストールした環境に合わせて設定しますが、今回は docker
を選択します。
tags
後述しますが、このタグを使用して CI
に使用する Runner
を選択します。
複数の Runner
があった場合、指定された全てのタグを持つ Runner
の中から実際に使用される Runner
が選択されます。
今回は Docker Runner
なので docker-runner
位しか設定しようがないですが、例えば複数の Windows Runner
を追加した時、ある端末には Unity
の開発環境が入っていて、また別の端末には Unreal
は入っていたとしたら、それぞれをタグにしておく事で CI
実行時に適切な Runner
を選択する事が出来ます。
default docker image
Docker Runner
なので、デフォルトで何のイメージで実行するか聞かれます。環境に合わせて適宜設定ですが、僕は dind
(Docker in Docker、Dockerが使えるDockerイメージ)にしました。
初期化が終わったら config.toml を編集
初期化が終わったらホストの ./gitlab-runner/config
の中に config.toml
ができます。
Docker Runner
を使用するためには config.toml
の中にある privileged
の項目を true
にする必要がある ので、変更しておいてください。
(おまけ) Windows Runner を追加する
以前 Qiita で書いた記事がありますので、こちらも参考になれば。
実行ユーザーの関係で躓きポイントがありましたので、ご注意ください。
リポジトリを作る
GitLab
上で適当なリポジトリを作成します。既に CI
を使ってみたいプロジェクトがあれば、そのプロジェクトでもいいと思います。
CI の設定をする
Project Runner
を追加した場合は不要なのですが、あるプロジェクトで Shared Runner
あるいは Group Runner
を使用したい場合はプロジェクトの設定 -> CI/CD
-> Runners
から Enable shared runners for this project を ON
にする必要があります。
GCP のプロジェクトを用意する
テスト用の新しい GCP のプロジェクトを作ります。使えるものがあれば、既存のプロジェクトでも大丈夫です。
Artifact Registry でリポジトリを作成
Cloud Run
はコンテナをデプロイするサービスなので、コンテナイメージをホストするためのリポジトリを用意する必要があります。
GCP
には Artifact Registry
というレジストリサービスがあるので、そちらを利用します。
Artifact Registry
から、「リポジトリを作成」と進み、必要事項を入力してリポジトリを作成します。形式は docker
としておいてください。
ここで作ったリポジトリ名と、選択したリージョン名は後で使用します。
API を有効にする
今回は Cloud Run
へのデプロイなのですが、以下の API
が必要です。
「APIとサービス」から「ライブラリ」を選択し、以下の API
を有効にします。
- Artifact Registry API
- Cloud Run API
サービスアカウントを用意
Cloud Run
へ実際にサービスをデプロイするサービスアカウントを作成します。
「IAM」から「サービスアカウント」を選択し、新規サービスアカウントを作成します。
ロールは、今回の場合は以下の物が必要です。
- Artifact Registry 書き込み
- Cloud Run 管理者
- サービスアカウントユーザー
作成したサービスアカウントのメニューから「鍵を管理」->「鍵を追加」->「新しい鍵を作成」と進み、json
ファイルをDLします。これがデプロイのための認証鍵になります。
コードを用意する
今回はサンプルとして、素の nginx
コンテナをデプロイする事にします。
Clour Run
へデプロイするアプリはポート8080で待ち受けている必要があるのですが、nginx
デフォルトでは80番になっているので、これを8080にします。
参考
FROM nginx:alpine
COPY nginx.conf /etc/nginx/conf.d/configfile.template
ENV PORT 8080
ENV HOST 0.0.0.0
EXPOSE 8080
CMD sh -c "envsubst '\$PORT' < /etc/nginx/conf.d/configfile.template > /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'"
server {
listen $PORT;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri /index.html;
}
gzip on;
gzip_vary on;
gzip_min_length 10240;
gzip_proxied expired no-cache no-store private auth;
gzip_types text/plain text/css text/xml text/javascript application/x-javascript application/xml;
gzip_disable "MSIE [1-6]\.";
}
CI ファイルを書く
GitLab
では、.gitlab-ci.yml
というファイルが CI
設定用のファイルになります。
# 指定しなければデフォルトの docker:dind になる
# image: docker:19.03.12-dind
services:
- docker:19.03.12-dind
stages:
- deploy
variables:
OPS: production
DOCKER_DRIVER: overlay2
DOCKER_TLS_CERTDIR: ""
DOCKER_HOST: tcp://docker:2375
RUN_REGION: asia-northeast2 # Cloud Runでサービスを実行するリージョン
REGISTRY_REGION: asia-northeast2 # Artifact Registry のリージョン
SERVICE: test-service # Cloud Run にデプロイする際のサービス名
IMAGE_TAG: ${REGISTRY_REGION}-docker.pkg.dev/${PROJECT_ID}/test/${SERVICE}
deploy:
stage: deploy
tags:
- docker-runner
script:
# install
- apk add --update --no-cache curl git bash python3
# gcloud
- curl -sSL https://sdk.cloud.google.com | bash
- echo ${GCP_SA_KEY} > ./gcp-key.json
- export PATH="$PATH:/root/google-cloud-sdk/bin"
- gcloud auth activate-service-account --key-file=./gcp-key.json
- gcloud config set project ${PROJECT_ID}
# registry
- gcloud auth configure-docker asia-northeast2-docker.pkg.dev
# build
- docker build -t ${IMAGE_TAG} .
- docker push ${IMAGE_TAG}
# deploy
- gcloud run deploy ${SERVICE} --image ${IMAGE_TAG} --region ${RUN_REGION} --platform managed --allow-unauthenticated
only:
refs:
- main
設定ファイル内にある変数のいくつかはファイル内の variables
内に定義してありますが、 GCP_SA_KEY
等の機密性の高い変数は別で定義します。
変数(シークレット)を設定する
前項であった「機密性の高い変数」ですが、グループやプロジェクトの「Settings」->「CI/CD」-> 「Variables」で設定する事が可能です。
この変数もプロジェクトやグループといった単位で設定でき、上位階層で設定されている変数は下位階層でも使用できます。
例えばAというグループにBというプロジェクトがあった場合、Aで設定した変数はBでも参照できます。
ここでは、以下の変数を設定します。
名称 | 値 |
---|---|
PROJECT_ID | プロジェクトのID |
GCP_SA_KEY | 事前にDLしておいたサービスアカウントの鍵となるjson |
※GCP_SA_KEYは、ファイルの中身をコピペして設定します。
注意点
GitHub
の場合は入力したシークレットは暗号化され、たとえ入力した本人でも復元する事は出来ませんが、GitLab
の場合はそれが出来てしまいます。
グループやプロジェクトに共同作業メンバーを招待する場合は、よりロールに気を付ける必要があります。
push して CI を実行する
ここまでの作業を終えたら、ファイルを commit
してリモートの GitLab
に push
します。
設定ファイル内で main
ブランチに push
されたら CI
が実行されるように書いてあるので、push
と同時に CI
プロセスが走り出します。
進行状況はプロジェクトの「CI/CD」->「Pipelines」、あるいは「Jobs」から確認できます。
デプロイの完了を確認する
デプロイが完了したら、実際にサービスにアクセスしてみましょう。
アドレスは前項のログ最後の方にも表示されていますし、GCP
のコンソールでも確認する事が出来ます。
nginx
の初期画面が表示されていれば成功です。
おわりに
GitLab
の構築からスタートしたので全体的に長くなってしまいましたが、一つ一つの手順はそんなに難しくなかったのではないかと思います。
GitLab
に限りませんが、CI/CDは一度設定してしまえば後はリモートに push
するだけで自動的に処理が走るので、自分の端末をデプロイで専有する時間をゼロに出来ます。
また、インフラの知識がない人でもデプロイプロセスを走らせる事が出来るので、そういう人が「試しに開発環境にデプロイしたい!」というケースでもインフラ担当者の手を止めずに済みます。
僕自身最初に構築した時は少し手間取ったのですが、この記事が同じような事をしたい方の助けになれば幸いです。
Discussion