簡體   English   中英

無法從 Nginx 反向代理后面的 docker 容器提供靜態資產

[英]Can't serve static assets from docker containers behind Nginx reverse proxy

我正在嘗試使用 Nginx 作為反向代理來為兩個容器提供服務。 這是我的 Nginx conf 文件的一部分:

upstream dashboard {
    server dashboard:80;
}

upstream editor {
    server editor:80;
}

server {
    listen 80;
    server_name example.com;

    location / {
        proxy_pass         http://dashboard;
    }

    location /editor/ {
        rewrite ^/editor(.*)$ $1 break;
        proxy_pass         http://editor;
    } 

當我導航到瀏覽器中的/editor url 時,我收到 404 錯誤,因為該頁面正在提交對駐留在上游容器“editor”中的靜態資源的請求。

在此處輸入圖片說明

我對 Nginx 很陌生,但我認為當它收到帶有 url 的請求時: http://example.com/static/css/2.3d394414.chunk.css : http://example.com/static/css/2.3d394414.chunk.css

Nginx 無法知道相應的 css 位於editor容器內。 如何修改配置以解決此問題? 我已經看到一些配置為任何靜態資產提供了通用路徑,但我需要一個可以處理 docker 容器內資產的解決方案。

如果其他人遇到同樣的問題,這里有一個額外的答案以及@b0gusb 發布的答案。 當您將 docker 容器作為上游應用程序時,這是一個解決方案。 例如, dashboardeditor是由create-react-app應用程序和 nginx 服務器組成的容器。

首先,更改create-react-app生成的index.html文件所在的目錄,通過在 package.json 中設置homepage字段來搜索靜態資產:

{
  "name": "dashboard",
  "homepage": "https://example.com/dashboard",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "react": "^16.9.0",
    "react-dom": "^16.9.0",
    "react-scripts": "3.1.1"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": "react-app"
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}

使用當前最新版本的react-scripts (3.1.1) 這將生成一個 index.html 文件,其中包含指向您的靜態資產的鏈接,這些資產預計位於dashboard目錄中(或您在homepage字段中的斜杠后選擇的任何名稱) )。

現在在您的 docker 文件中,您需要對構建資產進行一些移動,以便index.html中的鏈接不會中斷。 以下是我的Dockerfile

FROM node:12.2.0-alpine as builder

WORKDIR /usr/src/app

ENV PATH /usr/src/app/node_modules/.bin:$PATH

COPY package.json .

RUN npm install react-scripts@3.1.1 -g
RUN npm install

COPY . .

RUN npm run build

FROM nginx:1.17.2

COPY --from=builder /usr/src/app/build/ /usr/share/nginx/html/dashboard
COPY --from=builder /usr/src/app/build/*.html /usr/share/nginx/html

EXPOSE 80

CMD [ "nginx", "-g", "daemon off;" ] 

請注意, create-react-app構建生成的靜態資產位於dashboard目錄中, index.html位於/usr/share/nginx/html目錄中。 現在,您的 nginx 反向代理可以區分對各種容器的不同靜態資產的請求:

    # location to handle calls by the editor app for assets
    location /editor/ {
        proxy_pass http://editor/editor/;
    }

    # location to handle calls by the dashboard app for assets
    location /dashboard/ {
        proxy_pass http://dashboard/dashboard/;
    }

    # location to handle navigation to the editor app
    location /editor-path/ {
        access_log /var/logs/nginx/access.log;
        rewrite ^/editor-path(.*)$ $1 break;
        proxy_pass         http://editor/;
    }        

    # location to handle calls to the rest/graphql api
    location /api/ {
        access_log /var/logs/nginx/access.log;
        rewrite ^/api(.*)$ $1 break;
        proxy_pass         http://restserver/;
    }

    # location to handle navigation to the dashboard app
    location / {
        access_log /var/logs/nginx/access.log;
        proxy_pass         http://dashboard/;
    }

如果我理解正確,您在editordashboard上游都有靜態資源,並且在這兩種情況下,URL 都是相同的/static/some.resource因為您無法根據 URL 進行區分,所以您可以配置nginx以嘗試該文件是否首先存在於dashboard然后如果未找到,則將請求代理給editor

 upstream editor {
    server editor:80;
   }

   upstream dashboard {
     server dashboard:80;
   }

   server {
     location /static {
     # Send 404s to editor
     error_page 404 = @editor;
     proxy_intercept_errors on;

     proxy_pass http://dashboard

     }

     location @editor {
       # If dashboard does not have the file try with editor
       proxy_pass http://editor
     }
   }

另請參閱nginx – 在多個命名位置或服務器上嘗試文件

希望能幫助到你。

/上方,配置/編輯器配置。

Nginx 從上到下執行檢查,因此有可能將根配置 ( / ) 放在頂部會將所有內容路由到錯誤的服務器。

切換塊位置並重新啟動/重新加載 nginx 配置。

實際上,為了便於配置,您可以按照以下步驟操作:

upstream dashboard {
    server dashboard:80;
}

upstream editor {
    server editor:80;
}

server {
    listen 80;
    server_name example.com;

    location / {
        proxy_pass         http://dashboard;
    }

    location /editor/ {
        proxy_pass         http://editor;
        proxy_set_header Accept-Encoding "";
        sub_filter "/static" "/editor/static;
        sub_filter_once off;
    }

sub_filter函數會將 example.com/static/ 更改為 example.com/editor/static,但為了獲得最佳配置,您必須為所有靜態文件創建一個路徑。 喜歡:

/var/data/build/dashboard/..(可以是css、js)

/var/data/build/editor/..(可以是css、js)

我認為使用sub_filter很好,而應用程序沒有很多要重寫的 URL,我希望這會有所幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM