タイトルの通り。 まあAWSとGCPの各所で表示される内容にしたがってやっていけば問題なくできるのだが、実施記録と今後の自分への備忘録のために。
事前準備・前提条件
- AWS、GCPに有効なアカウントが存在すること。 AWSではRoute 53、GCPではCloud Run、Container Registryを使うので、それらを使える権限を持ったユーザーがAWS、GCP両方に必要である。
- AWS Route 53上に自分で管理しているドメインが存在すること。 これのサブドメインをCloud Runのカスタムドメインとして利用するので、その親になるドメインをAWS Route 53上で管理している必要がある。
- 開発するローカル環境にDocker、Node.jsがインストールされていること。
個人的には開発はいつもDockerコンテナ上で(VS CodeのRemote Containerで)やることが多く、Node.js、Docker CLI、GCP CLIの入ったイメージを自作して、そのコンテナ上で作業していたので、必ずしもNode.jsのローカルへのインストールは必須ではない。 この辺は開発環境の事情に合わせて好きにかえてよいと思う。 極論Dockerさえ入ってればあとはローカルには何も入れなくてもよい。
なお、2021年3月現在、Cloud Runのカスタムドメイン設定はベータ版らしいので、そういうの気にする方はご注意を。
Cloud Runアプリケーションの用意
プロジェクト用意
適当なディレクトリを掘って npm init -y して package.json をつくっておく。
また、expressを使うので npm install express を実行する。
Expressアプリケーション作成
const express = require('express');
const app = express();
const port = process.env.PORT || 3002;
app.get('/test', (req, res) => {
res.send('hello express');
});
app.listen(port, (err) => {
if (err) {
console.error('error happened');
throw err;
}
console.log(`http://localhost:${port}/test`);
});
なんのことはない、/test でリクエスト受けたら固定で hello express 返すだけの単純なWebアプリである。
ポイントは3行目の const port = process.env.PORT || 3002; である。
Cloud Runは「PORT」という名前の環境変数でアプリケーションが起動されることを前提としているので、そのために起動するポートをPORT変数から取得して設定するよう記述する。
後ろの 3002 はローカル用。(まあローカルの実行環境でPORT変数指定すればそのPORT環境変数値で動くことになるけど)
これを app.js とでも名付けて保存する。
とりあえず node app.js で起動してみて、curl http://localhost:3002/test とか打ってみて、結果が返ってくることだけ確認する。
なお、これが今回Cloud Runで動くアプリケーションの実態になる。 今回は説明のため(?)にこんな非常に簡素でHelmetとかも皆無の雑なアプリケーションにしたが、実際にProductionとして動かす場合は当然もうちょっと凝ったものを作る必要があるだろう。
Dockerイメージ作成
これをDockerイメージにする。 以下のようなDockerfileをつくる。
FROM node:12-alpine
COPY . .
RUN npm install
CMD ["node", "app.js"]
作成後、docker build -t hogehoge:latest . とか打ってDockerイメージを作成する。
hogehogeは自身の好みに合わせて適当に変更する。
イメージ作成後、一応、docker run -d -p 3002:3002 --rm -it hogehoge:latest とか打ってコンテナ起動し、curl http://localhost:3002/test とか打ってレスポンスが返ってくるか確認してみる。
GCPのContainer RegistryにPush
上でつくったイメージをGCPのContainer RegistryにPUSHする。 使うContainer RegistryはAsia→asia.gcr.ioにする。
まずはタグ付け。
docker tag hogehoge asia.gcr.io/[プロジェクト名]/hogehoge:latest
次にdocker login。
いくつかやり方あるみたいだが、私はService AccountのJSONファイルを発行後に docker login した。
cat keyfile.json | docker login -u _json_key --password-stdin https://asia.gcr.io
参考:https://cloud.google.com/container-registry/docs/advanced-authentication?hl=ja#json-key
これによれば一番簡単なのは gcloud auth を使う方法のようだ。
なんでか自分のときには上手く動作しなかったので古典的(?)なdocker loginでやらせてもらった。
次にpush。
docker push asia.gcr.io/[プロジェクト名]/hogehoge:latest
うまくいってればこれでContainer Registryにイメージがプッシュされている。

GCPのCloud Runにdeploy
GCPのConsoleからCloud Runのメニューを選んで「サービスの作成」

リージョンを選んでサービス名を適当に入れて「次へ」

「コンテナイメージのURL」からさっきPUSHしたイメージを選択して「次へ」

「未認証の呼び出しを許可」を選択して「作成」

ちょっと待つ。 しばらくするとデプロイが終わり、Cloud Runメニュー最初の画面の一覧にこんな↓かんじで作成されたサービスが表示される。

サービス名の部分をクリックする。

URL部分をコピーしてパス末尾に「/test」を加えたものに対してcurlしてみる。 今まで↑でやってきたのとの同様のレスポンスが返ってくれば成功。
この段階では「https://[サービス名]-xxxxxxxxxx…run.app」というURLになっているはずである。 カスタムドメインなしでも、このURLでとりあえずパブリックアクセスはできるようになっている。(さっきつくった超簡素なExpressアプリケーションが動く) とりあえずCloud Runにデプロイされていることが確認できた。
gcloud cliでまとめてやる方法
こんな面倒なことしなくてもGCPのCLIを使えばもっと簡単にDockerビルド+レジストリへのPUSHとCloud Runデプロイまでやってくれる。。。
これがdockerビルド+PUSH。
gcloud builds submit --tag asia.gcr.io/[プロジェクト名]/hogehoge:latest
参考:https://cloud.google.com/run/docs/building/containers?hl=ja
これがCloud Runデプロイ。
gcloud run deploy [サービス名] --image=asia.gcr.io/[プロジェクト名]/hogehoge:latest --allow-unauthenticated
参考:https://cloud.google.com/sdk/gcloud/reference/run/deploy
dockerビルド+PUSHは実行環境下にdockerが入ってないと動かなそうな気はする。dockerが入っていない環境下では試してないが。
AWS Route 53でドメイン作成
AWSのほうに移動する。
Route 53で「ホストゾーンの作成」

ドメイン名に自分が管理しているドメインのサブドメインを入力して「作成」。 たとえば「hogehoge.com」を持っているなら「cloudrun.hogehoge.com」とか。 これがCloud Runに設定するカスタムドメインになる。

作成後、NSレコードとSOAレコードが表示される。 NSレコードのほう(多分4行分ある)をコピーする。

親ドメインのホストゾーンを選択して「レコードの作成」 レコード名の入力欄には最下部レベルのドメイン名だけ入力する。 たとえば親ドメインが「hogehoge.com」で「cloudrun.hogehoge.com」にするなら「cloudrun」だけ。 レコードタイプは「NS」、値に↑でコピーしたNSレコードの値を貼り付ける。 で、「レコードの作成」。

しばらく待つ。
5分後くらいに dig とか nslookup とかで今回作成したサブドメインの名前が引けるか試してみる。
Cloud Runにカスタムドメイン設定
再びGCP Consoleに戻る。 さっきつくったCloud Runの詳細画面に行く。 URLの隣にある「!」マークをクリックして右側に表示されたメニューから「MANAGE CUSTOM DOMAINS」をクリックする。

ドメインマッピングの画面に遷移。 「マッピングを追加」を選択

ドメインマッピングの設定を行う。 「マッピングするサービスを選択」では先ほど作成したCloud Runサービスを 「確認済ドメインを選択」は「Verify a new domain…」を 「検証するベースドメイン」は先ほどAWS Route 53で発行したサブドメインを それぞれ選択&入力する。

「続行」を押すと所有権の検証に入る。 「ウェブマスターセントラルで確認」をクリックする。(別画面が別タブで開く)

「ドメインまたはレジストラを選択」で「その他」を選ぶ。 すると設定すべきTXTレコードが表示されるので、コピー。

ここで再びAWS Route 53に戻る。 先ほど作成したサブドメインのホストゾーンに移動し、「レコードの追加」→コピーした値をTXTレコードとして追加する

TXTレコード追加後、しばらくすると、Googleのウェブマスターセントラルで検証が通る(所有権が認められる)。 検証が通ると、最後に追加でAレコードとAAAAレコードを追加するように指示があるので、指示通りにAWS Route 53からレコード追加する。 最終的にこんな感じ↓になるはずである。

このあとカスタムドメインのマッピングが有効化されるまでしばらく待つ。 これが結構時間がかかる。 自分の時は体感的に大体20~30分前後かかった。
最終的にOKになるとドメインマッピング画面で緑マークがつく。

これでカスタムドメイン経由でCloud Runにアクセスすることが可能になった。
たとえば「cloudrun.hogehoge.com」を設定した場合は
curl https://cloudrun.hogehoge.com/test でアクセスすれば今までと同様のレスポンスが得られる。
おわりに
振り返ってみれば、要するに、指示されたTXTレコードを追加→(検証OK→)指示されたAレコードとAAAAレコードを追加すればOKらしい。 Googleの検証作業に時間がかかるが、まあこれで済むなら簡単だよなと思った。 また、カスタムドメインのマッピングはCloud Functionsにもあったので、(試してないけど)恐らく同じ手順で設定できるはずだ。 そっちはそっちでまた別の使い道ができそうなので、今後試してみたい。
今回のこれ、自分が持っているドメインなら(DNSを設定できるなら)、別に親ドメインの管理場所はAWSでなくても基本的にはやり方は同じなんだと思われる。 (自分の場合はたまたまAWSでとったドメインがあるのでそれをテスト用に使わせてもらったが) そういう意味では、AWSとGCPでマルチクラウドだぜ!って感じの色がそこまで強くない案件ではあるが、まあ、個人的に面白かったので良しとする。