ローカルのWeb開発でTLSとドメインを得るやり方
結論
ngrokを使います。
この後はdocker composeを使ってフロントとバックエンドを統合する方法を書いていきます。
目的
ローカルで開発している時にインターネットに晒したいことがあります。
- OAuth認証のコールバックURLでTLSが要求される
- スマートフォンの実機で確認したい
クラウドやVPSにデプロイすればいいんですが、ちょっと面倒です。
ngrok
ngrokコマンドをインストールして実行すると、その場でドメインが発行されてTLSで動作するようになります。指定してホストとポートにプロキシーしてくれます。
アカウント登録して認証キーを発行などありますが、詳しいことはぐぐってください。
docker compose
ローカルにインストールしたくない主義なので、開発用のdocker composeに組み込みます。
WebはフロントをVue.js,バックエンドをRustのaxumで動かします。
フロントは「/」に、バックエンドは「/api」に流れるようにnginxで制御します。
バックエンドは起動後、コンテナに入って手動でサーバーを起動しています。
ディレクトリー構成は以下のようになります。
- apps
- api
- frontend
- development
.env
docker-compose.yaml
Dockerfile
nginx.conf
ngrok.conf
services:
nginx:
image: nginx:latest
ports:
- '9000:80'
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
depends_on:
- api
- frontend
ngrok:
image: ngrok/ngrok:latest
restart: unless-stopped
environment:
NGROK_AUTHTOKEN: ${NGROK_AUTHTOKEN}
command:
- "start"
- "--all"
- "--config"
- "/etc/ngrok.yml"
volumes:
- ./ngrok.yml:/etc/ngrok.yml
ports:
- 4040:4040
frontend:
image: node:20.11.0-bookworm
working_dir: /app
volumes:
- ../apps/frontend:/app
command: ["npm", "run", "dev", "--", "--host"]
ports:
- 5173:5173
api:
build:
context: .
environment:
CLIENT_KEY: ${CLIENT_KEY}
CLIENT_SECRET: ${CLIENT_SECRET}
CARGO_TARGET_DIR: /tmp/target
CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse
PG_URL: postgres://user:pass@db:5432/web
volumes:
- ../apps/api:/app
- sample_web_cargo_cache:/usr/local/cargo/registry
- sample_web_target_cache:/tmp/target
ports:
- 3000:3000
depends_on:
- db
tty: true
working_dir: /app
security_opt:
- seccomp:unconfined
db:
image: postgres:16
environment:
- POSTGRES_DB=web
- POSTGRES_USER=user
- POSTGRES_PASSWORD=pass
- TZ=Asia/Tokyo
- PGTZ=Asia/Tokyo
ports:
- 5432:5432
volumes:
- sample_web_postgresql_data:/var/lib/postgresql/data
volumes:
sample_web_postgresql_data:
sample_web_cargo_cache:
sample_web_target_cache:
FROM rust:1.75
RUN apt -y update && apt -y install musl-tools libssl-dev pkg-config build-essential
RUN rustup update && \
cargo install cargo-watch && \
rustup component add rustfmt clippy
worker_processes auto;
events {
worker_connections 1024;
}
http {
server {
listen 80;
location /api {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
proxy_pass http://api:3000;
}
location / {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
proxy_pass http://frontend:5173/;
}
}
}
version: "2"
tunnels:
website:
proto: http
addr: nginx:80
host_header: rewrite
NGROK_AUTHTOKEN=xxx
CLIENT_KEY=xxx
CLIENT_SECRET=xxx
まとめ
これでドメイン付きでTLSで外部からアクセスできるようになります。実は想定してなかったメリットとしてVue.jsのホットリロードが効きました。実機で直ぐに反映されるのはちょっと感動します。
またいくつかデメリットもありました。
- 初回だけ確認ページが出る
- ngrokが起動する度にドメインが変わってしまう。
最初のものはデモとか実機確認なのであまり影響が無いです。後のはOAuth認証のコールバックURLでは不便です。毎回修正するのもありなんですが、サービスによってはコールバックURLを変更しても承認レビューが必要になります。
今はなるべくngrokだけは再起動しないようにしてます。または自分で管理しているドメインがあるならCNAMEを使って調整しても良いと思います。 追記(2024/02/15) CNAMEでやるには有料プランに入る必要がありました。
Discussion