Herokuで動かしているStrapiをRaspberry Piに移行するプロジェクト。
前回 → 【Strapi on Raspberry Pi】Strapi本体をデプロイする (6)
ローカル環境でStrapiを動かすことができたので、いよいよこれをインターネット経由でアクセスできるようにする。
最終的に目指す構成は以下の通り。
Cloudflare Zero Trust
Cloudflare Tunnelで外部からの接続を有効化し、Cloudflare Accessを使って自分以外の人がアクセスできないよう、アクセス制限を行う。これらの機能を使うためにはCloudflare Zero Trustを有効化する必要がある。
Zero Trust & SASE Plans & Pricing
Explore our Zero Trust offerings and find the plan that's right for your business to secure users, devices, and networks.
Cloudflareのアカウントは持っているが、別途プランへの加入が必要そうだ。ただ、個人利用だとフリープランで問題ない。
このチーム名は他とかぶらなければ何でもよい。後で変更することもできる。
一応決済画面に遷移するので、$0で決済。
まずはCloudflare Tunnelの設定を行う。
Create a tunnel (dashboard)
Create a tunnel (dashboard) in Zero Trust networking.
ドキュメントの手順に従いTunnelを作成する。
作成したTunnelでローカルネットワークとインターネットを繋ぐためには、ローカルネットワーク内でcloudflaredを導入する必要がある。
Tunnel作成後、どの環境にcloudflaredを導入するかをUIで選択できるので、Dockerを選択。token付きのコマンドが表示されるので、tokenだけをコピーして保持しておく。
cloudflared
Raspberry Pi(ホスト)の構成は以下の通り。
cloudflaredとStrapiのdocker compose設定を分けて定義する。一つのファイルにまとめてもよかったが、今後別のアプリも別のドメインでデプロイするかもしれないなと思い、cloudflaredの設定は独立させることにした。
composeはデフォルトでcomposeごとに独立したネットワークを作成するので、そのままではcloudflaredコンテナからStrapiコンテナへ疎通できない。そこで、cloudflared側でネットワークを作成し、Strapi 側で参照できるようにする。
# cloudflared docker-compose
services:
cloudflared:
networks:
- proxy
networks:
proxy:
name: proxy
# Strapi docker-compose
services:
app:
expose:
- "1337"
networks:
default: {}
proxy:
aliases:
- noura-release-note-strapi-app
networks:
proxy:
external: true
cloudflared側でname: proxyとして定義したネットワークに、Strapi側でexternal: trueと設定し接続。したがって、コンテナの起動順には注意が必要。cloudflaredを先にdocker compose upしないと、Strapiが接続すべきnetworkを見つけられずエラーとなる。
さらに、proxyネットワークにおけるStrapiアプリケーションの名前をnetworks.proxy.aliasesで定義(固定)する。ここで定義した名前をCloudflareのトンネルの接続先として設定することができる。Strapiコンテナは内部ネットワークのみポートを公開する。ports: "1337:1337"とするとホストOS経由でコンテナに直接アクセスできるようになるが、exposeでDockerネットワーク内のみの公開に限定できる。
cloudflaredコンテナは公式のイメージcloudflare/cloudflaredを使う。
services:
cloudflared:
image: cloudflare/cloudflared:latest
platform: linux/arm64
container_name: cloudflared
restart: unless-stopped
command: tunnel --no-autoupdate run
env_file:
- cloudflare.env
tunnel runコマンドでトンネルを作成する。この時、--no-autoupdateオプションで自動アップデートを無効化する。コンテナ環境なので更新はイメージの再ビルドで実行する。
トンネルの認証情報(トークン)は環境変数で渡す。ダッシュボードで取得したトークンをcloudflare.envファイルでTUNNEL_TOKEN環境変数に定義し、env_fileで環境変数をコンテナに渡す。
Published application routes
CloudflareのダッシュボードでPublic hostname(インターネットからアクセスするときのURL)とService URL(cloudflaredがリクエストを転送する先のアドレス)を設定する。トンネル詳細画面から「Published application routes」タブを選択し「Add a published application route」をクリック。
Hostnameに設定したドメインがCloudflareのDNSに登録される。Hostname宛のリクエストをCloudflare Edgeサーバがcloudflaredにプロキシする。cloudflaredはService URLの宛先にHTTPリクエストを送る際に、所属しているDockerネットワーク内からService URL(noura-release-note-strapi-app)を名前解決し、転送する。Docker内の通信なのでhttpで問題ない。
これでインターネット経由でStrapiにアクセスすることができるようになった。個人用とはいえインターネットに公開すること自体はリスクではあるが、出先でも記事を書けるし、Cloudflare Pagesのビルドも実行できるようになる。ただ、いくらStrapi自体の認証があるとはいえ丸裸で外の世界に公開するのは怖いので、別途アクセス制限をかけることにする。(というか実際はトンネル設定とアクセス制限は同時に実施している)。