30歳からのプログラミング

30歳無職から独学でプログラミングを開始した人間の記録。

Route 53 + Cloudflare + Heroku で Deno アプリを公開する

先日、砂場として使うために以下の構成のウェブアプリを作った。

  • Deno で作ったアプリケーションサーバを Heroku で公開し、それを Cloudflare 経由で配信する
  • ドメインは Route 53 で取得したものを使う
  • Heroku も Cloudflare も無料プランを利用する

忘れないうちにその手順を記録しておく。

ちなみにこの構成だと、ドメイン代以外の費用はかからない。
HTTPS で配信される独自ドメインのサイトを、無料で公開できる。また、クライアントとエッジサーバ間は HTTP/3 で配信できる。

Deno のバージョンはv1.10.3を使っている。

必要なファイルの用意

まずは Deno でアプリケーションサーバを作る。

以下の内容のserver.tsを作る。

import {
  listenAndServe,
  ServerRequest,
} from "https://deno.land/std@0.97.0/http/mod.ts";
import { parse } from "https://deno.land/std@0.97.0/flags/mod.ts";

const argPort = parse(Deno.args).port;
const port = argPort ? Number(argPort) : 8080;

listenAndServe({ port }, (req: ServerRequest) => {
  const body = `<html>
<head>
  <title>Deno App</title>
</head>
<body>
  <p>foo</p>
</body>
</html>`;

  switch (req.url) {
    case "/": {
      req.respond({
        status: 200,
        headers: new Headers({
          "Content-Type": "text/html",
        }),
        body,
      });
      break;
    }
    default:
      req.respond({
        status: 404,
        headers: new Headers({
          "Content-Type": "text/plain",
        }),
        body: "Not found\n",
      });
      break;
  }
});

$ deno run --allow-net server.tsを実行して、ローカルで動作確認する。
http://localhost:8080/にアクセスしたときにfooと表示され、他のパスにアクセスするとNot foundが表示されれば、成功。

次に、デプロイのために必要なファイルを 2 つ作成する。

まずはProcfile

web: deno run --allow-net=:${PORT} --cached-only server.ts --port=${PORT}

そしてruntime.txt。これは、使用する Deno のバージョンを指定するために使う。

v1.10.3

ここまでで、以下のディレクトリ構成になっている。

.
├── Procfile
├── runtime.txt
└── server.ts

これで準備は整ったので、次は Heroku へのデプロイを行う。

Heroku へのデプロイ

Heroku へのデプロイには Git を用いるため、上記 3 つのファイルをコミットする。
コミットメッセージは何でもよい。

$ git init
$ git add .
$ git commit -m "initial commit"

次は Heroku CLI を使うので、インストールしておく。
そしてログイン後、heroku createでアプリケーションを作る。

$ heroku login
$ heroku create --buildpack https://github.com/chibat/heroku-buildpack-deno.git

あとは$ git push heroku masterでプッシュすればデプロイされるので、$ heroku openで確認する。
ドメインは、foo-bar-1234.herokuapp.comのように、Heroku から自動的に付与されたものになっている。
fooと表示されていれば成功。
デプロイが失敗した場合は$ heroku logs --tailでログを確認できる。

Route 53 でドメインを取得

Route 53 でドメインを取得する。UI は変わる可能性が高いため、細かい手順は紹介しない。
この記事の文脈においては Route 53 である必要はなく、他の業者を使っても問題ない。

Cloudflare への登録

これ以降、Heroku アプリのドメインはfoo-bar-1234.herokuapp.com、Route 53 で取得したドメインはexample.comとして、説明していく。
そのため実現したいのは、クライアントがexample.comにアクセスしたときにfoo-bar-1234.herokuapp.comにデプロイした内容が表示されること、そしてそれが Cloudflare のエッジサーバ経由で配信されること、である。

Cloudflare に登録後、「サイトを追加」を選びexample.comを入力する。
次にこのドメインに対して、DNS レコードを設定する。
「タイプ」はCNAME、「名前」はexample.com、コンテンツはfoo-bar-1234.herokuapp.com
「続行」を押下すると次の画面に移るので、その画面に従ってドメインのネームサーバを変更する。
そうすることで、エンドユーザーがドメインにアクセスしたときに、Cloudflare のネームサーバに対して IP を問い合わせるようになる。 

今回は Route 53 でドメインを取得したので、Route 53 の設定を変更する必要がある。
下記画像の右端の「ドメインの登録」から「ネームサーバー」を設定しなければならないので、注意する。

f:id:numb_86:20210605231858p:plain

「ホストゾーン」から「NS レコード」を編集しても、いつまでも反映されない。

$ whois example.comName Serverが変わっていれば成功。

設定が上手くいくと、Cloudflare のダッシュボードにその旨が表示される。また、メールでも通知が来る。

ネームサーバに関する画面のあとに以下のページが表示されるが、基本的には全て有効でよいはず。

f:id:numb_86:20210605231840p:plain

Heroku でカスタムドメインを追加する

最後に、Heroku でexample.comを利用できるようにする。この設定を行わずにexample.comにアクセスしても、エラーになってしまう。

まず、カスタムドメインを追加するためには Heroku アカウントの認証が必要になる。そしてそのためにはクレジットカードかデビットカードを登録する必要がある。
前述のように無料プランを使っているので支払いは行われないが、認証のために登録が必要になる。
アカウントの確認 | Heroku Dev Center

登録後、以下のコマンドを実行する。

$ heroku domains:add example.com -a foo-bar-1234

これで、必要な作業は全て終えた。

動作確認

設定したドメインのページ(この記事の例で言えばhttps://example.com)にアクセスして、正しく表示されているか確認する。
画面にはfooが表示されており、レスポンスヘッダのserverフィールドの値がcloudflareになっているはずである。

参考資料