5
2

More than 3 years have passed since last update.

nginxのリバースプロキシとNuxt.jsのリダイレクトでハマった話

Last updated at Posted at 2021-09-06

状況

Dockerでnginxとnode環境(Nuxt.js)を構築して、リバースプロキシを介してNuxtアプリにアクセスすることを試みた。

dokcer-compose.yml
version: '3.9'
services:
  proxy:
    image: nginx:1.21.0
    volumes:
      - ./proxy/nginx.conf:/etc/nginx/nginx.conf
    ports:
      - '80:80'

  web:
    build:
      context: ./web
      dockerfile: Dockerfile
    command: yarn dev
    volumes:
      - ./web:/app
    tty: true
    environment:
      PORT: 3000
      HOST: 0.0.0.0
    ports:
      - '3000:3000'

nginx.conf
events {}
http {
  server {
    listen 80;
    server_name localhost;

    location / {
      proxy_pass http://host.docker.internal:3000/;
    }
  }
}

この設定で、http://localhost/ へアクセスすると、リバースプロキシを介してNuxtアプリにアクセスできる。
しかし、途中でlocation/から/app/に変更して、http://localhost/app/ の形でアクセスできるようにしたくなった。

nginx.conf
events {}
http {
  server {
    listen 80;
    server_name localhost;

    location /app/ { # ここを変更
      proxy_pass http://host.docker.internal:3000/;
    }
  }
}

nginx.confを書き換えて、http://localhost/app/ にアクセスしたところ、こんなエラーが発生した。

[error] 25#25: *1 open() "/etc/nginx/html/_nuxt/runtime.js" failed (2: No such file or directory)

ブラウザにはLoading Circleが表示されているので、Nuxtアプリ自体にはアクセスできているようだが、読み込めていないファイルがあるらしい。

エラー表記から_nuxt/runtime.jsの参照先がおかしいことがわかる。
本来であれば、localhost:3000にホストされている_nuxt/runtime.jsを参照したいところが、localhostにホストされている_nuxt/runtime.jsを見に行ってしまっている。

解決までの道のり

まず、NuxtのbaseURLを/から/app/に変更した。

nuxt.config.js
export default {
  // これを追記
  router: {
    base: '/app/'
  }
}

こうすることで、localhostではなく、localhost/appにホストされている_nuxt/runtime.jsを参照することになり、リバースプロキシによってlocalhost/appからlocalhost:3000へ飛ばされるので、結果的にlocalhost:3000にホストされている_nuxt/runtime.jsを見に行くことになる。

よし、解決!

と思ったが、別の問題が発生した。
リダイレクトが無限に繰り返されるようになってしまった。
メカニズムとしてはこんな感じ。

  1. localhost/appにアクセス
  2. リバースプロキシがlocalhost:3000に読み替え
  3. NuxtのbaseURLは/app/なので、localhost:3000からlocalhost:3000/appにリダイレクト
  4. 結果的にURLはlocalhost/appになる
  5. 1へ戻る

baseURLを書き換えたときにリバースプロキシの設定も書き換える必要があった。

nginx.conf
events {}
http {
  server {
    listen 80;
    server_name localhost;

    location /app/ {
      proxy_pass http://host.docker.internal:3000/app/; # ここを変更
    }
  }
}

http://localhost/app にアクセスすると、ちゃんとサイトが表示されました。
今度こそ解決!! ٩(ˊωˋ*)و

別解

proxy_passを設定するときには、trailing slash(後ろに付けるスラッシュ)に気をつける必要がある。
詳しくはこちら↓の解説記事を参照。
https://www.xmisao.com/2014/05/09/nginx-proxy-pass.html

trailing slashを付けずにproxy_passを設定すると、飛び先のURLには、locationの文字列も付与されるようになる。
これを利用して、最後のnginx.confの書き換えを以下のようにしてもOK

nginx.conf
events {}
http {
  server {
    listen 80;
    server_name localhost;

    location /app/ {
      # proxy_pass http://host.docker.internal:3000/app/;
      proxy_pass http://host.docker.internal:3000; # これでもOK
    }
  }
}
5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2