rm /blog

IT系技術職のおっさんがIT技術とかライブとか日常とか雑多に語るブログです。* 本ブログに書かれている内容は個人の意見・感想であり、特定の組織に属するものではありません。/All opinions are my own.*

Google CloudのCloud RunにAWS Route 53上で管理しているドメインのサブドメインをCustom Domainとして設定して動かしてみた

タイトルの通り。
まあAWSGCPの各所で表示される内容にしたがってやっていけば問題なくできるのだが、実施記録と今後の自分への備忘録のために。

事前準備・前提条件

  1. AWSGCPに有効なアカウントが存在すること。
    AWSではRoute 53、GCPではCloud Run、Container Registryを使うので、それらを使える権限を持ったユーザーがAWSGCP両方に必要である。
  2. AWS Route 53上に自分で管理しているドメインが存在すること。
    これのサブドメインをCloud Runのカスタムドメインとして利用するので、その親になるドメインAWS Route53上で管理している必要がある。
  3. 開発するローカル環境にDocker、Node.jsがインストールされていること。

個人的には開発はいつもDockerコンテナ上で(VS CodeのRemote Containerで)やることが多く、Node.js、Docker CLIGCP 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とかも皆無の雑なアプリケーションにしたが、実際にProdctionとして動かす場合は当然もうちょっと凝ったものを作る必要があるだろう。

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にイメージがプッシュされている。
f:id:rmrmrmarmrmrm:20210307181856p:plain

GCPのCloud Runにdeploy

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

f:id:rmrmrmarmrmrm:20210307181912p:plain

リージョンを選んでサービス名を適当に入れて「次へ」
f:id:rmrmrmarmrmrm:20210307181932p:plain

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

f:id:rmrmrmarmrmrm:20210307181946p:plain

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

f:id:rmrmrmarmrmrm:20210307181958p:plain

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

f:id:rmrmrmarmrmrm:20210307182010p:plain

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

f:id:rmrmrmarmrmrm:20210307182030p:plain

URL部分をコピーしてパス末尾に「/test」を加えたものに対してcurlしてみる。
今まで↑でやってきたのとの同様のレスポンスが返ってくれば成功。

この段階では「https://[サービス名]-xxxxxxxxxx...run.app」というURLになっているはずである。
カスタムドメインなしでも、このURLでとりあえずパブリックアセスはできるようになっている。(さっきつくった超簡素なExpressアプリケーションが動く)
とりあえずCloud Runにデプロイされていることが確認できた。

gcloud cliでまとめてやる方法

こんな面倒なことしなくてもGCPCLIを使えばもっと簡単に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で「ホストゾーンの作成」

f:id:rmrmrmarmrmrm:20210307182142p:plain

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

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

f:id:rmrmrmarmrmrm:20210307182207p:plain

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

しばらく待つ。
5分後くらいにdigとかnslookupとかで今回作成したサブドメインの名前が引けるか試してみる。

Cloud Runにカスタムドメイン設定

再びGCP Consoleに戻る。
さっきつくったCloud Runの詳細画面に行く。
URLの隣にある「!」マークをクリックして右側に表示されたメニューから「MANAGE CUSTOM DOMAINS」をクリックする。
f:id:rmrmrmarmrmrm:20210307182231p:plain

ドメインマッピングの画面に遷移。
マッピングを追加」を選択
f:id:rmrmrmarmrmrm:20210307182244p:plain

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

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

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

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

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

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

最終的にOKになるとドメインマッピング画面で緑マークがつく。
f:id:rmrmrmarmrmrm:20210307182356p:plain

これでカスタムドメイン経由でCloud Runにアクセスすることが可能になった。
たとえば「cloudrun.hogehoge.com」を設定した場合は
curl https://cloudrun.hogehoge.com/testでアクセスすれば今までと同様のレスポンスが得られる。

おわりに

振り返ってみれば、要するに、指示されたTXTレコードを追加→(検証OK→)指示されたAレコードとAAAAレコードを追加すればOKらしい。
Googleの検証作業に時間がかかるが、まあこれで済むなら簡単だよなと思った。
また、カスタムドメインマッピングはCloud Functionsにもあったので、(試してないけど)恐らく同じ手順で設定できるはずだ。
そっちはそっちでまた別の使い道ができそうなので、今後試してみたい。

今回のこれ、自分が持っているドメインなら(DNSを設定できるなら)、別に親ドメインの管理場所はAWSでなくても基本的にはやり方は同じなんだと思われる。
(自分の場合はたまたまAWSでとったドメインがあるのでそれをテスト用に使わせてもらったが)
そういう意味では、AWSGCPでマルチクラウドだぜ!って感じの色がそこまで強くない案件ではあるが、まあ、個人的に面白かったので良しとする。