web-dev-qa-db-ja.com

NGINXはHTMLページ以外のすべてで404エラーを出します

Dockerコンテナーでnginxをリバースプロキシとして設定し、コンテナー外のサイトにリンクします。私は次のようにvhost構成を設定しています(ホームアシスタントの場所の前に^〜を追加してみました):

server { # simple reverse-proxy
    listen       80;

    location / {
        proxy_pass http://192.168.1.99:6789;
    }

    location ^~ /home-assistant {
        proxy_pass http://192.168.1.99:8123/;
    }

    location /calibre-web/ {
        proxy_pass http://192.168.1.99:8181/;
    }

  }

ホームアシスタントとcalibre-webサイトの両方でページが読み込まれますが、他のすべてのアイテム(画像、CSSなど)で404エラーが発生します。 アプリケーションのリンクをクリックしようとすると、192.168.1.99/site-folder/fileではなく、192.168.1.99/fileにリンクされます。以下は、ログのいくつかのレコードです(1つの200応答と他の404応答に注意してください)。ここで何が悪いのですか?助けてくれてありがとう。

192.168.1.6 - randy [15/Aug/2016:03:15:42 +0000] "GET /frontend/panels/dev-template-0a099d4589636ed3038a3e9f020468a7.html HTTP/1.1" 404 199 "http://192.168.1.99/home-assistant/" "Mozilla/5.0 (X11; CrOS x86_64 8350.60.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.85 Safari/537.36"

192.168.1.6 - randy [15/Aug/2016:03:15:42 +0000] "GET /frontend/panels/logbook-66108d82763359a218c9695f0553de40.html HTTP/1.1" 404 199 "http://192.168.1.99/home-assistant/" "Mozilla/5.0 (X11; CrOS x86_64 8350.60.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.85 Safari/537.36"

192.168.1.6 - randy [15/Aug/2016:03:17:54 +0000] "GET /home-assistant/ HTTP/1.1" 200 1654 "-" "Mozilla/5.0 (X11; CrOS x86_64 8350.60.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.85 Safari/537.36"

192.168.1.6 - randy [15/Aug/2016:03:17:55 +0000] "GET /static/icons/favicon-192x192.png HTTP/1.1" 404 91 "http://192.168.1.99/home-assistant/" "Mozilla/5.0 (X11; CrOS x86_64 8350.60.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.85 Safari/537.36"

192.168.1.6 - randy [15/Aug/2016:03:17:55 +0000] "GET /static/core-457d5acd123e7dc38947c07984b3a5e8.js HTTP/1.1" 404 91 "http://192.168.1.99/home-assistant/" "Mozilla/5.0 (X11; CrOS x86_64 8350.60.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.85 Safari/537.36"

これは私のルートnginx.confのコピーです 。エラーはここのどこかにあると思いますが、どこにあるのかわかりません。

5
Randy

元のアプリケーションにとって不明な場所からのリクエストをproxy_passしようとしています。 Dockerコンテナアプリケーションでは、Webサイトのルート(http://192.168.1.99:8123/)からアクセスされていると見なしているため、/または/home-assistant/ではなく、/calibre-web/に関連するすべてのURLを生成します。

この問題を解決する方法はたくさんあります。自分に最適な方法を選択してください。

1.プロキシされたhtmlのリンクを置き換える

まず第一に、結果をクライアントに送信する前に、プロキシされたアプリケーションから受信したすべてのリンクを ngx_http_sub_module で置き換えることができます。デフォルトでは有効になっていないため、ディストリビューションにない場合は ソースからnginxをコンパイル する必要があります(このモジュールの可用性を確認するには、nginx -Vを実行します。これにより、--with-http_sub_module構成パラメータに沿ったどこか)。

この方法を選択する場合は、次のディレクティブを構成に追加します。

location ^~ /home-assistant {
    rewrite ^/home-assistant(/.*)$ $1 break;
    proxy_pass http://192.168.1.99:8123/;
    sub_filter "<head>" "<head><base href=\"${scheme}://${Host}/home-assistant\">";
}

2.コンテナー内のアプリケーションパスの変更

Dockerコンテナー内のアプリケーションをルートではなく/home-assistantに移動すると、ルート/ではなく、そのパスに関連する提供コンテンツにすべてのURLが生成されます。これは明白な(そしておそらく最も簡単な)ソリューションであり、nginxの構成をまったく変更する必要がありません(Docker内で構成を編集する必要はありません)。

3.リファラーヘッダーに基づいてアップストリームを選択する

Refererヘッダーに基づいて、使用するアップストリームを決定します。 ここから取得 。自分では本番では使用しませんが、かなりスマートに見えます(css/jsファイルでのみ機能することに注意してください)。

location ~* ^/(css|js)/.+\.(css|js)$ {
    #checking if referer is from home-assistant
    if ($http_referer ~ "^.*/home-assistant"){
        return 417;
    }

    #checking if referer is from calibre-web
    if ($http_referer ~ "^.*/calibre-web"){
        return 418;
    }
}

error_page   417  /home-assistant$request_uri;
error_page   418  /calibre-web$request_uri;

location ^~ /home-assistant {
    proxy_pass http://192.168.1.99:8123/;
}

location /calibre-web {
    proxy_pass http://192.168.1.99:8181/;
}

私があなただったら、#2を使用します。必要なものを取得するための最も簡単でエラーが発生しにくい方法として、コンテナー内でアプリを移動します。

追伸バックエンドがnginxと同じサーバー上にあるため、静的ファイルをハードドライブから直接提供できることを完全に忘れていました。アプリケーションに依存した構成が必要になりますが、結果として最も効率的なソリューションが得られます。

3
Anubioz

1つの解決策は、proxy_passディレクティブでURIを渡さないことです。

location ^~ /home-assistant {
    proxy_pass http://192.168.1.99:8123;
}

location ^~ /calibre-web/ {
    proxy_pass http://192.168.1.99:8181;
}

/ステートメントのポート番号の後にproxy_pass文字がないことに注意してください。つまり、nginxはサーバーに送信されたURIをアプリサーバーに渡します。

/文字(URI)を使用すると、要求URIがそれで置き換えられます。

この動作は http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass に記載されています

2
Tero Kilkanen