2020/05/29
nginxのproxy_cacheを設定して、Nuxt.jsのサイトを高速化しました
概要
本サイトのクライアント側のアプリ(htmlのレンダリングやインタラクティブな処理)にはNuxt.jsを利用しています。
リリース当初は(めんどくさくて)やっていなかったのですが、やろうやろうと思っていたNginxのproxy_cacheの導入を行いました。
まずは、ローカルのdocker-composeでテストをして、問題ないことを確認しつつ、本番のnginxの設定を修正して適用しました。
ただ、ローカルではうまくいったものの、本番ではどうしてもうまくいかなったので、そちらの調査と解決も行いました。
nginxの設定ファイルは基本的には nginx をリバースプロキシとして使う - NuxtJS こちらの記事を踏襲しました。
実施事項
ローカルでの動作確認
以下のような構成で試しました。
├── docker-compose.yml
└── nginx
├── Dockerfile
└── sites-available
└── portfolio-web.conf
nginx/Dockerfile
- nginxのバージョンは本番環境のものに合わせました “nginx -V” で確認できます。
- また、docker上では、site-availableの設定ファイルを conf.d/default.conf へ上書きします
- 通常、site-availableをシンボリックファイルをsites-enabledに作成して、読み込ませるのがbest practiceではありますが、Dockerは1プロセス1サイトが基本なので、こちらの構成がシンプルでみやすいです
FROM nginx:1.10.3-alpine
RUN apk update; \
apk add curl bash
COPY sites-available/portfolio-web.conf /etc/nginx/conf.d/default.conf
CMD ["/usr/sbin/nginx", "-g", "daemon off;"]
nginx/sites-available/portfolio-web.conf
proxy_cache_path /var/cache/nginx/portfolio-web levels=2:2 keys_zone=portfolio-web:1m max_size=1g inactive=5m use_temp_path=off;
proxy_temp_path /var/cache/nginx/portfolio-web/cache;
upstream portfolio_web {
server web:3000; # docker-composeで定義した service名 port番号と合わせる
}
server {
listen 0.0.0.0:80;
listen [::]:80;
server_name _;
access_log /dev/stdout;
error_log /dev/stderr;
location / {
proxy_pass http://portfolio_web;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_redirect off;
proxy_read_timeout 1m;
proxy_connect_timeout 1m;
# cache settings
proxy_ignore_headers Cache-Control; # nuxt appで付与された Cache-Controlを無視する
add_header X-Cache-Status $upstream_cache_status; # キャッシュが有効かどうかをレスポンスヘッダーに付与する
proxy_cache portfolio-web;
proxy_cache_key $uri$is_args$args;
proxy_cache_valid 200 201 300 301 302 5m;
proxy_cache_valid 404 1m;
proxy_cache_lock on;
}
}
docker-compose.yml
環境変数の定義など、説明の都合上省略してます
version: "3"
services:
nginx:
image: portfolio-nginx:latest
ports:
- "8080:80"
depends_on:
- web
web:
image: portfolio-web:latest
ports:
- "3000:3000"
environment:
- BASE_URL=http://web:3000
- API_URL=http://api:8000/api/v1
depends_on:
- api
api:
image: portfolio-api:latest
ports:
- "8000:8000"
environment:
- POSTGRES_USER=portfolio
- POSTGRES_PASSWORD=password
- POSTGRES_SERVER=db
- POSTGRES_DB=portfolio_dev
depends_on:
- db
db:
image: postgres:12.2-alpine
ports:
- "5432:5432"
environment:
- POSTGRES_USER=portfolio
- POSTGRES_PASSWORD=password
- POSTGRES_DB=portfolio_dev
- PGDATA=/var/lib/postgresql/data/pgdata
volumes:
- ./.docker/pgdata:/var/lib/postgresql/data
上記のような構成で、起動し、nginxのコンテナにログイン(docker exec -it
それで、 以下のコマンドで、アクセスし、“X-Cache-Status” headerの値をみます。
curl -v localhost
2回目のアクセスで、“X-Cache-Status"の値が、“MISS"から"HIT"に変われば成功です。
また、”/var/cache/nginx/portfolio-web” 配下に実際にcacheされたデータが作成されているのがわかります。
本番環境での適用
本番環境でもローカルでテストしたものと似たような構成に変更して、nginxを再起動してみました。
ただ、何度アクセスしても キャッシュ用のディレクトリ “/var/cache/nginx/portfolio-web” はできているのに
キャッシュファイル自体が作成されませんでした。
いろいろ原因を考え、
proxy_ignore_headers X-Accel-Redirect X-Accel-Expires Cache-Control Expires Set-Cookie;
を追加したり、
“proxy_cache_bypass” や、"proxy_no_cache"を追加・削除してみたりして試したのですが・・一向にうまくいきません。
何かエラーログに記載されているかもしれないと思い、エラーログをみてみました。
すると以下のようなログが出ていました。
# tail -n 50 /var/log/nginx/error.log
2020/05/29 03:47:05 [emerg] 9585#9585: bind() to [::]:80 failed (98: Address already in use)
2020/05/29 03:47:05 [emerg] 9585#9585: bind() to 0.0.0.0:443 failed (98: Address already in use)
2020/05/29 03:47:05 [emerg] 9585#9585: bind() to [::]:443 failed (98: Address already in use)
2020/05/29 03:47:05 [emerg] 9585#9585: still could not bind()
どうやら、nginxがうまく起動できていないのが原因でした。
systemctl経由とsupervisorctl経由の2つ同時で起動しており、古いプロセスがずっと生きていました。
なので、新しい設定ファイルを適用したnginxのプロセスが起動直後にエラーとなってしまい、以下のようなことが起きていました。
- cacheのディレクトリは作成されたけれど、cacheが適用された設定では起動できていなかった
- ブラウザからのアクセスでは、cacheが有効になっていない古いプロセスが応答していたため、普通にアクセスできてしまっていた
教訓
まあ当たり前の話なんですが・・「変なことが起きたら真っ先にエラーログを確認しましょう。」
これにつきますね。
ただ、解決するためにいろいろ調べたので、時間はかかりましたが、nginxのcache周りに少し詳しくなりました。
以上になります。
関連する記事
Nuxt2からNuxt3への移行とNextJSとNuxt3の比較について
弊社ホームページとブログサイトをNuxt2からNuxt3ベースに移行しました。
Nuxt.jsからNext.jsへのリニューアルを経て思うこと
Nuxt.jsからNext.jsへフルリニューアルしたことで見えてきた個人的なメリットとデメリットを整理します
NuxtJSにEditor.jsを導入
リッチでカスタマイズが自由なテキストエディタであるEditor.jsをNuxtJSのサイトに導入しました。
AOSをNuxtJSのサイトに導入する
スクロールアニメーションを簡単に実装できるAOSというライブラリをNuxtJSベースのサイトに導入しました