Nginx 中同一個網域設定不同應用程式/目錄

技能點還沒有點太多的領域一點點成果就會獲得大大的成就感。

最近弄了一個可以在同一個網域中實作多的應用程式的設定,這邊紀錄一下。先講結論:

  1. 可以實現同一個網域前後端分離,讓版本控制的操作也分開來。
  2. 同理多個不同應用如果需要互相呼叫時,也可以使用 sub-path 不要 sub-domain 來處理。
  3. 強烈建議不要用套裝的應用程式,關於網域使用的設計需要特別處理。
  4. 個人認為,如果是不同功能的應用場景,還是應該用 sub-domain 處理,這應該是 UX 相關的設計,和技術較為無關。
  5. 系統層的設定較為複雜,包含 Nginx 的設定,如果沒有 full controll 的權限可能實現上較為困難。

前提列一下:

  1. 主網域是 a.com.tw
  2. 第二個網域是 b.com.tw 作為 nginx 的 proxy 使用,如果有需要也會在 dns 上設定。

目標有幾個:

  1. 用戶訪問 a.com.tw 時候,會跳轉至 /root-document/a.com.tw/ 路徑上的 web-app
  2. 用戶訪問 a.com.tw/admin 時候,會跳轉至 /root-document/b.com.tw/ 路徑上的 web-app
  3. 用戶訪問 a.com.tw/uploads 時候,會跳轉至 /root-document/b.com.tw/uploads 路徑上的靜態檔案

實作步驟:

設定 /etc/hosts 檔案,新增:

127.0.0.1 b.com.tw

如果有需要,可以在 DNS 上設定 CNAME 把 b.com.tw 設定為 a.com.tw 別名。

設定 a.com.tw 的網站,Nginx 中添加:

# 將 /admin/ 和 /admin/* 路徑指向後端應用程式
location ^~ /admin/ {
  proxy_pass http://b.com.tw;
}
# 將 /uploads/ 和 /uploads/* 路徑的靜態檔案指向其他資料夾
location ^~ /uploads/ {
  alias /root-document/b.com.tw/uploads/;
  try_files $uri $uri/ /index.html;
}


# Option 其他網站的配置,例如前端 
location ^~ / {
  root /root-document/a.com.tw;
  ...
}

設定 b.com.tw 的網站,Nginx 按照一般的設定即可,不過在動態程式中需要特別注意幾項:

  1. b.com.tw 的顯示網域是主網域 a.com.tw,在畫面上如果顯示非相對域名,要注意顯示的是 a.com.tw 而不是 b.com.tw
  2. 尤其後端上傳行為與 form action 會需要特別注意。
  3. http://b.com.tw 作為後端服務 proxy_pass,要注意 ssl 設定,包含顯示網域的 ssl 是否寫死?或是 proxy_set_header 判斷處理。
  4. uploads 的路徑在範例中也是導向 /root-document/b.com.tw/ 裡面的路徑,如果單純只是靜態檔案也可以自行設定。建議事先規劃整理好。
  5. 需要請注意根目錄設定 .user.ini 檔案中的設定,建議把不同路徑都補進去。

還有一些小細節:

  1. Nginx 中 alias 的路徑需要是 / 結尾。 alias 和 root 不同的地方,參考這裡
  2. Nginx 路徑匹配優先權問題,請參考這裡

關於 Nginx 設定的注意事項,附上問 ChatGPT 生成回覆:

配置意圖

  1. /admin//admin/* 路徑指向後端應用程式
    • location ^~ /admin/ { ... } 這個配置塊的意圖是將所有匹配 /admin/ 開頭的路徑(包括 /admin//admin/*)的請求,轉發到後端應用程式,其地址為 http://b.com.tw
    • proxy_pass http://b.com.tw; 這個指令表示將符合條件的請求轉發給 http://b.com.tw 這個後端服務處理。
  2. /uploads//uploads/* 路徑的靜態檔案指向其他資料夾
    • location ^~ /uploads/ { ... } 這個配置塊的意圖是處理匹配 /uploads/ 開頭的路徑(包括 /uploads//uploads/*)的請求,並將這些請求指向伺服器上的一個具體的資料夾來提供靜態檔案。
    • alias /root-document/b.com.tw/uploads/; 這個指令表示將 /uploads/ 路徑的請求映射到伺服器上 /root-document/b.com.tw/uploads/ 目錄中的對應檔案。例如,請求 /uploads/image.jpg 會映射到 /root-document/b.com.tw/uploads/image.jpg
    • try_files $uri $uri/ /index.html; 這個指令會嘗試按順序查找以下檔案:
      • $uri:請求的原始檔案或目錄(例如 /root-document/b.com.tw/uploads/image.jpg)。
      • $uri/:如果是目錄,則查找目錄下的檔案(例如 /root-document/b.com.tw/uploads/image.jpg/)。
      • 如果以上都未找到,則回退到 /index.html 這個檔案。

注意事項

  1. ^~ 前綴
    • ^~ 表示如果路徑匹配 /admin//uploads/,那麼該配置塊將優先於其他正則表達式匹配(例如 location ~location /)來處理請求。這確保了 /admin//uploads/ 的請求被這些特定的配置塊處理。
  2. Proxy Pass 的上下文
    • 當使用 proxy_pass 指令時,Nginx 將請求轉發給後端服務(如 http://b.com.tw)。確保 b.com.tw 這個服務能夠正確處理接收到的 /admin/ 路徑,並且能夠返回正確的響應。
  3. Alias 的使用
    • alias 指令用於將 URL 路徑映射到文件系統上的實際路徑,注意它不同於 root 指令。使用 alias 時需要確保映射的目錄結構和權限設置正確,以便 Nginx 能夠讀取和提供靜態檔案。
  4. 靜態檔案的優先級
    • /uploads/ 路徑的靜態檔案配置中,try_files 的指令順序很重要。你需要確保 /index.html 是你希望用來處理靜態資源請求失敗時的回退頁面。
  5. 安全性考量
    • 在提供靜態資源時,應確保 /root-document/b.com.tw/uploads/ 資料夾內的檔案不包含敏感信息,且檔案權限設置得當,防止未經授權的訪問。

這段配置主要是為了處理特定路徑的請求,將動態內容轉發給後端應用程式,並通過靜態資源提供功能來處理文件的提供。


已發佈

分類:

作者: