この記事は、シリーズ記事「「C#のライブラリプロジェクトをGitLabにpushしたら自動でDLLが書き出されてついでにDocFXで作成されたドキュメントがCloud Run上にデプロイされる」っていうやつをやる」の一部です。
はじめに
GitLabは.gitlab-ci.ymlというファイルを書く事で、データが push
されたタイミングでCIが走ります。
.gitlab-ci.ymlという名前ではありますが、もちろんCDを実現する事も可能です。
今回は、以前書いた記事の続きとしてビルドした成果物をデプロイするところまでやってみたいと思います。
関連記事
Cloud Run の設定
まずは、デプロイ先を準備する必要があります。
今回は Cloud Run にデプロイするので、ますは https://console.cloud.google.com/ にアクセスして、プロジェクトを作成します。
プロジェクトを作成
既に対象のプロジェクトがある場合は改めて作る必要はありません。任意の名前のプロジェクトを選択、あるいは作成し、プロジェクトIDを控えておいてください。後で使用します。
グローバルで一意なプロジェクト名を設定した場合はほぼ同じ名前のIDがふられますが、例えば「My Project」等のプロジェクト名だった場合はランダムなプロジェクトIDが付与されます。
プロジェクトのダッシュボードにアクセスした時に、
https://console.cloud.google.com/home/dashboard?project=(プロジェクトID)
となっているはずですので、分からなければここを確認してください。
Cloud Build を有効に
docker
のビルドに関してはクラウドでやらずにローカルでやってしまっても問題ないのですが、面dせっかくなので Cloud Build を使ってみようと思います。
まずは API を有効にしておく必要があるので、プロジェクトから有効化しておきます。
Cloud Run を有効に
同じく、Cloud Run に関しても API を有効にしておく必要があります。
サービスアカウントを作成
新しいサービスアカウントを作成し、Cloud Run と Cloud Build を実行するために必要な権限を与えます。
IAM と管理 > サービスアカウント > サービスアカウントを追加
と辿ると新しいサービスアカウントの作成画面になり、必要な項目を埋めていくと、次は権限の設定画面になります。
ここで、僕は試行錯誤の結果以下の項目を追加しました。
- Cloud Build サービス アカウント
- Cloud Run 管理者
- Cloud Run サービス エージェント
- ストレージ管理者
- 閲覧者
なんか権限与えすぎな感じがするのですが、すべてないと動きません…
もし不要な権限に気付いた方いましたら、コメントでご指摘頂けると嬉しいです。
最後に、アカウント情報が含まれた json
をダウンロードします。
この json
が認証情報になります。後で使用しますので、取っておいてください。
GitLab に CD で使う環境変数をセット
認証情報等の機密情報を、たとえ内部サーバーだったとしてもソースコードに含めるのは抵抗がありますよね。GitLabには、そういった情報を CI/CD 時の環境変数として格納しておける場所があります。
プロジェクト > Settings > CI/CD > Variables
ここに必要な情報を格納しておけば、ソースコードが流出したとしても認証情報は流出しません。
(ソースコードの流出だけでも大きな問題ですけど)
今回は、以下の変数をセットします。
PROJECT_ID
そのまま、プロジェクトのIDです。
控えておいたプロジェクトIDをそのまま入力してください。
SERVICE_ACCOUNT
前項で取得したサービスアカウント情報ですが、ファイルをアップロードする機能は無いので、 json
で取得した情報の中身を全てコピペします。
Dockerfile を追加
Cloud Run は ざっくり言うと Docker のコンテナをうまく動かしてくれるサービスなので、なにはともあれ Docker のイメージにする必要があります。
今回は、ClassLibrary/_site
にある HTML のファイル群を Nginx コンテナでサーブします。
FROM nginx:1.16-alpine
COPY ./_site /usr/share/nginx/html
COPY nginx/default.conf /etc/nginx/conf.d/default.conf
Nginx の設定を変更
ここで一つ注意なのが、Cloud Runは 環境変数 Port
で指定されるポートで動作する必要がある、という点です。 Nginx は当然 80 番ポートで待ち受けているので、これを変更する必要があります。
厳密には環境変数で渡されたポートを使用する必要があるのですが、基本的に渡される値は 8080 で固定されているようです。なので、とりあえず 8080 で待機するように変更します。
(手軽に環境変数からの値を使用できる方法を知っている方いましたら、コメントで教えて頂けると幸いです)
上記 Dockerfile でも参照していますが、 Dockerfileと同じディレクトリに nginx というディレクトリを作成し、その中に default.conf として以下の内容のテキストを配置して下さい。
server {
listen 8080;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
# redirect server error pages to the static page /50x.html
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
これで、Cloud Run で動作するようになります。
.gcloudignore を追加
今回使用する Cloud Run は、gitignoreの内容に従ってビルド用のサーバーにアップロードするファイルを決めます。
.gitignore の設定次第なのですが、ビルドされた成果物は基本的に ignore される傾向にあると思っていて、かくいう僕も ignore していました。今回はビルドで生成された _site というディレクトリを使用する事になるので、そのファイルは絶対にアップするように、.gcloudignore というファイルを置きます。
中身は .gitignore と同じような感じになります。
!_site
!nginx
!Dockerfile
ignore と言いながら今回は除外しない項目しかありませんが、これで必要なファイルがビルドサーバーにアップされるようになりました。
Runner の設定
以前の記事で設定したものに加えて、今回は gcloud
コマンドを使用するので、Runner 側に Google Cloud SDK をインストールしておく必要があります。
通常であればインストール後に認証設定を行う必要があるのですが、今回はサービスアカウントを使用して認証するので、インストールするだけでOKです。
.gitlab-ci.ymlを書く
こちらも、以前の記事で書いたものに CD の分を加筆します。
variables:
MSBuild: C:/Program Files (x86)/Microsoft Visual Studio/2019/BuildTools/MSBuild/Current/Bin/MSBuild.exe
NuGet: C:/Tools/nuget.exe
stages:
- build
- deploy
build:
stage: build
tags:
- C#
- powershell
script:
- chcp 65001
- Start-Process -FilePath $env:NuGet restore -Wait -NoNewWindow
- Start-Process -FilePath $env:MSBuild ClassLibrary/ClassLibrary.csproj -Wait -NoNewWindow
artifacts:
name: ClassLibrary
paths:
- ClassLibrary/bin/Debug
- ClassLibrary/_site
deploy:
stage: deploy
tags:
- gcloud
- powershell
script:
- chcp 65001
- cd ClassLibrary
- New-Item token.json -Value $env:SERVICE_ACCOUNT -Force
- gcloud auth activate-service-account --key-file token.json
- gcloud --project $env:PROJECT_ID builds submit --tag gcr.io/$env:PROJECT_ID/class-library
- gcloud --project $env:PROJECT_ID run deploy class-library --image gcr.io/$env:PROJECT_ID/class-library --platform managed --region asia-northeast1 --quiet
- Remove-Item token.json -Force
ポイント
今回加筆した CD 用のジョブ deploy
について、基本的には build
と変わらないのですが、自分的なポイントを挙げておきます。
ディレクトリを適宜移動
- cd ClassLibrary
ジョブ実行時、カレントディレクトリはプロジェクトのルートになっています。
今回、Dockerfile は ClassLibrary 以下にあるので、以降のコマンドを簡単にするために移動しておきます。
環境変数からの認証情報を使用する
- New-Item token.json -Value $env:SERVICE_ACCOUNT -Force
- gcloud auth activate-service-account --key-file token.json
- (中略)
- Remove-Item token.json -Force
環境変数に入っている文字列を一度ファイルにして、それを gcloud auth activate-service-account
に食わせています。認証が終わったら、安全のためにファイルを削除しています。
イメージを作成してデプロイ
- gcloud auth activate-service-account --key-file token.json
- gcloud --project $env:PROJECT_ID builds submit --tag gcr.io/$env:PROJECT_ID/class-library
- gcloud --project $env:PROJECT_ID run deploy class-library --image gcr.io/$env:PROJECT_ID/class-library --platform managed --region asia-northeast1 --quiet
上記の記述でビルドからデプロイまで可能ですが、 class-library
となっている部分は任意で変更できるので、必要に応じて分かりやすいものに変更してください。
デプロイテスト
ここまで出来たら、 push
する前に一度ローカルでデプロイを試してみます。
環境変数は、設定が面倒なのでコマンドに直接入れていきます。
認証については、先程ダウンロードした json
形式の認証情報を、ClassLibrary 以下に token.json という名前で配置して下さい。
テストのための措置なので、間違ってもこのまま push
しないようにご注意を。
まずはサービスアカウントの認証をして
> gcloud auth activate-service-account --key-file token.json
Activated service account credentials for: [xxxxxxxx@xxxxxxxx-262512.iam.gserviceaccount.com]
ビルドを実行し
> gcloud --project (プロジェクトID) builds submit --tag gcr.io/(プロジェクトID)/class-library
(省略)
xxxxxxxxxx.tgz gcr.io/xxxxxxxxxxxxxxx-262512/class-library (+1 more) SUCCESS
デプロイします
gcloud --project (プロジェクトID) run deploy class-library --image gcr.io/(プロジェクトID)/class-library --platform managed --region asia-northeast1 --quiet
Service [class-library] revision [class-library-00001-vak] has been deployed and is serving 100 percent of traffic at https://class-library-xxxxxxxxxxxx.a.run.app
全て問題なく完了したら、コマンドの設定は正しい事になります。
コマンドの最後に、公開URLが表示されていますね。
一点だけ注意があって、Cloud Run はデフォルト設定では認証済みの状態でないと表示ができないようになっており、テストでブラウザから見るのは少々骨が折れる状態になっています。
公開する事に問題が無ければ、画像にもありますが 「allUsers」 というユーザーを作成し、 「Cloud Run 起動元」 という役割を与えてあげればアドレスを知っていれば誰でもアクセスできる状態になります。
push!
もう何も言う事はありません。
きっと GitLab がよしなにやってくれるでしょう。
おわりに
クラウドにデプロイをしようと思うと、デプロイ先の設定があったり、認証情報が必要だったりと結構手間が増える印象です。ただ、それらの作業はクラウドを使用する以上は結局は必ず発生するので、一度やっておけば勝手にデプロイしてくれる CD はやはり便利だなと感じました。
引っかかりやすそうなところはあらかじめ僕が引っかかっておいたので、同じ事をやりたいと思っている人が、この記事を見てスムーズに CD を導入できれば幸いです。