@saw99ala

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

nginxでリバースプロキシを設定した際にリダイレクト先の相対パスが機能しなくなってしまう

ググろうにも状況をうまく言語化することができなかったため、こちらに質問を投稿させていただきました。個人開発をしており、業界で活躍されている方からすると伝わらない部分もあるかと思いますが、ご容赦ください。

現在、DockerComposeを用いてwebアプリケーション用のサーバーを立てようとしております。
まずは勉強用として、viteとreact、そしてリバースプロキシ用のnginxで構成されるプロジェクトを作成しました。nginxとreactそれぞれをdocker composeコマンドにて起動させることには成功したのですが、いざnginxを用いてreactにリダイレクトすると、html内に記述されている相対パスの参照先が

http://<サーバーのIP>:5173でアクセス時(直接)
http://<サーバーのIP>:5173/src/main.tsx
http://<サーバーのIP>/react/でアクセス時(リダイレクト)
http://<サーバーのIP>/src/main.tsx

となってしまい、404エラーが発生してしまいます。こちらについて、404エラーを発生させないようにするには、どうすればよいでしょうか?ゆくゆくはhttp://<サーバーのIP>:5173へのアクセスを制限し、すべてnginxを介するようにしたいと思っています。

ソースコード

※すでに動いているwebサーバーがあり、ネットワークカードを追加して動かしているので、localhostが使えません。

/
├─ docker
│ ├─ nginx
│ │ └─ nginx.conf
│ └─ nodejs
│ └─ Dockerfile
├─ react
│ ├─ .gitignore
│ ├─ eslint.config.js
│ ├─ index.html
│ ├─ package-lock.json
│ ├─ package.json
│ ├─ README.md
│ ├─ tsconfig.app.json
│ ├─ tsconfig.json
│ ├─ tsconfig.node.json
│ ├─ vite.config.ts
│ ├─ node_modules
│ │ └─ ...
│ ├─ public
│ │ └─ vite.svg
│ └─ src
│ ├─ App.css
│ ├─ App.tsx
│ ├─ index.css
│ ├─ main.tsx
│ ├─ vite-env.d.ts
│ └─ assets
│ └─ react.svg
└─ docker-compose.yml

index.html(reactプロジェクトに最初から入っているものです。)
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/vite.svg" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vite + React + TS</title>
  </head>
  <body>
    <div id="root"></div>
    <script type="module" src="/src/main.tsx"></script>
  </body>
</html>
main.tsx(reactプロジェクトに最初から入っているものです。)
<html lang="en"><head>
    <script type="module">import { injectIntoGlobalHook } from "/@react-refresh";
injectIntoGlobalHook(window);
window.$RefreshReg$ = () => {};
window.$RefreshSig$ = () => (type) => type;</script>

    <script type="module" src="/@vite/client"></script>

    <meta charset="UTF-8">
    <link rel="icon" type="image/svg+xml" href="/vite.svg">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Vite + React + TS</title>
  </head>
  <body>
    <div id="root"></div>
    <script type="module" src="/src/main.tsx"></script>
  

</body></html>
エラーメッセージ(edgeで確認)
Failed to load resource: the server responded with a status of 404 (Not Found) client:1
Failed to load resource: the server responded with a status of 404 (Not Found) main.tsx:1
Failed to load resource: the server responded with a status of 404 (Not Found) @react-refresh:1
Failed to load resource: the server responded with a status of 404 (Not Found) vite.svg:1
nginx.conf
http {
    server {
        listen 0.0.0.0:80;
        server_name <サーバーのIP>;
        
        location /react/ {
            proxy_pass http://host.docker.internal:5173/;
            proxy_redirect off;
        }
    }
}
docker-compose.yml
services:
  react:
    container_name: 'React'
    build:
      context: .
      dockerfile: ./docker/nodejs/Dockerfile
    ports:
      - 5173:5173
    volumes:
      - ./react/:/var/www/html/node
    environment:
      - WATCHPACK_POLLING=true
    tty: true

  proxy:
    image: nginx:1.29.0
    container_name: 'Proxy'
    volumes:
      - ./docker/nginx/nginx.conf:/etc/nginx/nginx.conf
      - ./src:/var/www/html
    ports:
      - 80:80
    extra_hosts:
      - "host.docker.internal:host-gateway"
0 likes

2Answer

こちらについて,解決いたしましたので記録として残しておきます./react/が実際にはディレクトリとして存在しないので,理解に時間がかかりました.
設定:http://<サーバーのIP>/react/を全てhttp://<サーバーのIP>:5173/に振り分けたい.
問題:http://<サーバーのIP>/react/index.htmlにはアクセスできるものの,index.html内において相対パスで記載されているファイルが404エラーになる.
原因:相対パスには/react/が記載されていないため,index.html内において相対パスを/src/main.tsxと記載した場合,http://<サーバーのIP>/src/main.tsxを参照してしまった.
対策:
① vite.config.tsのdefineConfigに以下を追記

vite.config.ts
export default defineConfig({
+ base: '/react/',
  plugins: [react()],
  server: {
  ...

② nginx.confのproxy_pathを以下のように変更

nginx.conf
location /react/ {
  proxy_pass http://<サーバーのIP>:5173/react/;
  ...

考察:baseの追加することでviteでビルドされる相対パスに/react/が付加され,振り分け対象のリクエストとなる.同時に,http://<サーバーのIP>/react/index.htmlはhttp://<サーバーのIP>:5173/react/index.htmlとなるので,あわせてリダイレクト先もhttp://<サーバーのIP>:5173/react/とする必要がある.

1Like

nginxのデフォルトのドキュメントルートは/usr/share/nginx/html ですから、 /var/www/html にマウントしてもダメなんでは?
あるいは、下記のようにドキュメントルートを指定する必要があるかと。

location /src/ {
    root /var/www/html;
}
0Like

Comments

  1. @saw99ala

    Questioner

    パスやディレクトリについてソースや設定を読み進めたところ、いただいた回答の内容が直接の原因ではありませんでしたが、「相対パスには/react/が含まれていないため振り分け条件に合致せず、"http://<サーバーのIP>/相対パス"として解釈されてしまう」という状況であることがわかりました。(実際、相対パスの前に/react/を追記すると404エラーは消えました。)
    システム構成を見直そうと思いますが、当初の質問内容は解決いたしましたので、質問をクローズさせていただきます。ご回答いただきありがとうございました。

Your answer might help someone💌