やりたいこと
好きなWebサーバーをHTTP/3に対応させたいです。
HTTP/3はGoogleやCloudflareなどで使われ徐々に普及しています。HTTP/3では
UDPで通信が行われ、HTTP/1.xやHTTP/2やより高速に通信することができるようになります。詳しくは「HTTP/3が出るらしいという話を雑に書く - Qiita」などが参考になります。
今回はNginx + HTTP/3をDockerイメージにしてすぐに手軽にHTTP/3対応が出来るようにしました。Docker Composeで手軽にHTTP/3対応できるサンプルも載せたいと思います。
Cloudflare Quiche
CDNや1.1.1.1やWarpなどで活躍しているCloudflareからQuicheというQUICやHTTP/3のためのOSSがリリースされています。Cloudflare公式がNginxをHTTP/3対応する記事があり、それを元にDockerイメージを作成しました。
Nginx + HTTP/3のDockerイメージ
docker pull nwtgck/nginx-http3
でDockerイメージが手に入ります。
Dockerfileの内容はhttps://github.com/nwtgck/docker-nginx-http3/blob/master/Dockerfileです。
Dockerfileは公式のGitHubにあるNginx + HTTP/3をする説明を(quiche/extras/nginx at master · cloudflare/quiche)を元に作成しました。
Docker Hub上でのサイズは47MBでnginx:latest
と同じくらいのサイズです。
例: docker run
docker run
で起動させる例についてです。
以下のnginx.conf
を今いるディレクトリに作成します。
worker_processes 1;
events {
worker_connections 1024;
}
http {
server {
# Enable QUIC and HTTP/3.
listen 443 quic reuseport;
# Enable HTTP/2 (optional).
listen 443 ssl http2;
ssl_certificate /etc/ssl/certs/server.crt;
ssl_certificate_key /etc/ssl/private/server.key;
# Enable all TLS versions (TLSv1.3 is required for QUIC).
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
# Add Alt-Svc header to negotiate HTTP/3.
add_header alt-svc 'h3-23=":443"; ma=86400';
}
}
以下のようにHTTP/3ではUDPも使うため-p 443:443/udp
でUDPも解放します。
docker run -it -p 443:443 -p 443:443/udp \
-v $PWD/nginx.conf:/usr/local/nginx/conf/nginx.conf \
-v /etc/letsencrypt/live/nwtgck-nginx-http3.tk/fullchain.pem:/etc/ssl/certs/server.crt \
-v /etc/letsencrypt/live/nwtgck-nginx-http3.tk/privkey.pem:/etc/ssl/private/server.key \
nwtgck/nginx-http3
上記はLet's Encryptの証明書を指定してます。.../fullchain.pem
や.../privkey.pem
は適切に存在しているものを指定してください。最初はローカル環境で自己証明書を使いたかったのですが、後述のChromeでHTTP/3対応の確認が出来なかったのでLet's Encryptを使いました。
好きなWebサーバーをリバースプロキシしてHTTP/3対応するには
上記のように好きにnginx.conf
が書けるためlocation / {proxy_pass ...}
などを使ってリバースプロキシの設定すれば良いと思います。
docker run --net=host ...
を使って起動すればホスト環境で起動している他のWebサーバーのリバースプロキシを作れると思います。
Docker Composeでリバースプロキシする例は後述します。
HTTP/3対応できているか確認する
このCloudflareの公式ブログ「HTTP/3: the past, the present, and the future」で触れられている方法を使ってHTTP/3の対応を確認します。Chrome Canaryに--enable-quic --quic-version=h3-23
フラグを付けて起動します。
Macユーザーは以下のコマンドで起動できます。
/Applications/Google\ Chrome\ Canary.app/Contents/MacOS/Google\ Chrome\ Canary --enable-quic --quic-version=h3-23
以下のように開発者ツールのネットワークタブでhttp/2+quic/99
となっていてHTTP/3で通信できていることが確認できました。
Chrome CanaryはVersion 80.0.3959.0 (Official Build) canary (64-bit)
を使いました。GUIのChrome CanaryではなくCLIで確認したいときは以下の方法が使えるかも知れません。
http3-client - HTTP/3 Docs
Docker Composeを使った例
HTTP/3の対応するのはGhostというOSSのブログのプラットフォームです。https://hub.docker.com/_/ghost/でDockerイメージが配布されています。
このGitHubリポジトリhttps://github.com/nwtgck/ghost-nginx-http3-docker-composeに例を作りました。
docker-compose.yml
とnginx.conf
があるだけのシンプルな構成で内容は以下のとおりです。
version: '3.1'
services:
nginx:
image: nwtgck/nginx-http3
ports:
- '80:80'
- '443:443'
- '443:443/udp'
depends_on:
- ghost
restart: always
volumes:
- ./nginx.conf:/usr/local/nginx/conf/nginx.conf
# 適切に証明書のパスを指定してください。
- /etc/letsencrypt/live/nwtgck-nginx-http3.tk/fullchain.pem:/etc/ssl/certs/server.crt
- /etc/letsencrypt/live/nwtgck-nginx-http3.tk/privkey.pem:/etc/ssl/private/server.key
ghost:
image: ghost
restart: always
expose:
- "2368"
worker_processes 1;
events {
worker_connections 1024;
}
http {
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://ghost:2368;
}
}
server {
# Enable QUIC and HTTP/3.
listen 443 quic reuseport;
# Enable HTTP/2 (optional).
listen 443 ssl http2;
ssl_certificate /etc/ssl/certs/server.crt;
ssl_certificate_key /etc/ssl/private/server.key;
# Enable all TLS versions (TLSv1.3 is required for QUIC).
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
location / {
proxy_pass http://ghost:2368;
}
# Add Alt-Svc header to negotiate HTTP/3.
add_header alt-svc 'h3-23=":443"; ma=86400';
}
}
自分の環境で試す方法
# リポジトリをクローンする
git clone https://github.com/nwtgck/ghost-nginx-http3-docker-compose.git
cd ghost-nginx-http3-docker-compose
<docker-compose.ymlの...fullchain.pemと...privkey.pemのパスを適切に書き換える>
# サーバーを起動する
docker-compose up
Chrome Canaryの開発者ツールのネットワークタブで確認するとhttps://nwtgck-nginx-http3.tk/...
のリクエストがhttp/2+quic/99
となっていてHTTP/3で通信されていることが分かります。
おまけ
以下にNginx + HTTP/3でビルドしたり、Dockerイメージにするために少し苦労したことなどを書きました。
Nginx + HTTP/3 (Quiche)のDockerイメージを生成するためにしたこと - nwtgck / Ryo Ota