帶有 docker 容器和特定嵌套位置的 nginx 反向代理

帶有 docker 容器和特定嵌套位置的 nginx 反向代理

我想將 nginx 設為反向代理,並在永久駐留在特定位置的 docker 容器上使用多個應用程序,例如:

https://sub.example.com/wiki
https://sub.example.com/app1
https://sub.example.com/app2

特別是,我想使用mediawiki docker 映像位於其他應用程式旁。這是我的 docker-compose.yml:

version: '3.5'
services:

  mediawiki:
    image: mediawiki
    restart: unless-stopped
    hostname: mediawiki
    ports:
      - "8080:80"
    links:
      - database
    volumes:
      - images:/var/www/html/images
      # - ./wiki/LocalSettings.php:/var/www/html/LocalSettings.php
    networks:
      - wiki
  
  database:
    image: mariadb
    restart: unless-stopped
    hostname: database
    environment:
      MYSQL_DATABASE: my_wiki
      MYSQL_USER: wikiuser
      MYSQL_PASSWORD: example
      MYSQL_RANDOM_ROOT_PASSWORD: 'yes'
    volumes:
      - db:/var/lib/mysql
    networks:
      - wiki

  app1:
    # ...
    expose:
      - "4000"
    networks:
      - apps

  nginx:
    image: nginx:1.23-alpine
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/conf.d:/etc/nginx/conf.d
      - ./certbot/conf:/etc/nginx/ssl
      - ./certbot/data:/usr/share/nginx/html/letsencrypt
    depends_on:
      - app1
      - mediawiki
    networks:
      - apps
      - wiki

  certbot:
    image: certbot/certbot:latest
    # ...
    volumes:
      - ./certbot/conf:/etc/letsencrypt
      - ./certbot/logs:/var/log/letsencrypt
      - ./certbot/data:/usr/share/nginx/html/letsencrypt
    networks:
      - apps
      - wiki

networks:
  apps:
  wiki:

我面臨的問題是,透過以下內容default.conf,我能夠代理 mediawiki 容器以及其他應用程序,但某些連結和資源返回 404。

upstream testwiki {
    server mediawiki:80;
}

server {
    listen 80;
    listen [::]:80;

    server_name sub.example.com;

    location / {
        return 301 https://$server_name$request_uri;
    }
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    
    server_name sub.example.com;

    ssl_certificate /etc/nginx/ssl/live/sub.example.com/fullchain.pem;
    ssl_certificate_key /etc/nginx/ssl/live/sub.example.com/privkey.pem;

    location /wiki/ {
        proxy_pass http://testwiki/;
        proxy_set_header   Host $host;
        proxy_set_header   X-Real-IP $remote_addr;
        proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header   X-Forwarded-Host $server_name;
    }
}

我懷疑這種行為的原因是由於關係 URL,例如<a href="/mw-config/index.php">complete the installation</a>將請求定向到根位置而不是嵌套位置。我嘗試了很多東西,例如rewrite(包括正規表示式)、sub_filterproxy_redirect方法proxy_set_header,但我想出的最好的方法是:

location /wiki/ {
    proxy_pass http://mediawiki:80/;
    proxy_set_header   Host $host;
    proxy_set_header   X-Real-IP $remote_addr;
    proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header   X-Forwarded-Host $server_name;
}

location /app1/ {
    proxy_pass http://app1:4000/;
    proxy_set_header   Host $host;
    proxy_set_header   X-Real-IP $remote_addr;
    proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header   X-Forwarded-Host $server_name;
}


if ($http_referer = "https://sub.example.com/wiki/") {
    set $proxypass http://mediawiki:80;
}
if ($http_referer = "https://sub.example.com/app1/") {
    set $proxypass http://app1:4000;
}
    
location / {
    proxy_pass $proxypass;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
}

由於我還無法為 mediawiki 配置 baseurl,因此我嘗試根據http_referer.這適用於在https://sub.example.com/wiki/上述連結上發出的所有初始 GET 請求。

但是,點擊後<a href="/mw-config/index.php">...index.php會提出進一步的請求 - 再次定向至https://sub.example.com/。由於 URL 未被重寫且引用者表示https://sub.example.com/mw-config/index.php,因此這些請求傳回 500。

我的問題是:如何修復此行為以使我的應用程式永久駐留在各自的位置?不幸的是,我現在無法更改子網域。

任何幫助表示讚賞!

編輯:


由於我想使用可能遇到類似問題的多個其他應用程序,因此我想提出一個更通用的解決方案。在某些情況下,我無法控制基本 URL。

答案1

這裡發生了一些事情,我們需要在同一頁上達成一致才能使其發揮作用:

  1. NGINX配置:基於路徑的路由、反向代理
    • 我已經嘗試過你的配置,並且我相信你的配置是正確的
  2. 阿帕契2配置:正確地將 URI 對應到檔案路徑和腳本
    • 使用指令AliasMatch "^/wiki(.*)" "/var/www/html/$1"剝離/wiki並正確地映射到內部檔案路徑
  3. 媒體維基設定:新增/wiki路徑,以便Nginx知道在哪裡反向代理鏈接,然後Apache2可以刪除/wiki並使用正確的內部文件路徑。
    • 在執行 MediaWiki 安裝程式後建立的檔案$wgScriptPath = "/wiki";中進行設置,並在您的LocalSettings.phpdocker-compose.yml
  4. Docker 組合:透過將修改後的本機檔案掛載到mediawikidocker 容器中來保留這些更改

阿帕契2

我們將新增AliasMatch "^/wiki(.*)" "/var/www/html/$1"到配置/etc/apache2/sites-enabled/000-default.conf。您還需要在您的應用程式中覆蓋該文件的內容docker-compose.yml

#/etc/apache2/sites-enabled/000-default.conf 
<VirtualHost *:80>
        # The ServerName directive sets the request scheme, hostname and port that
        # the server uses to identify itself. This is used when creating
        # redirection URLs. In the context of virtual hosts, the ServerName
        # specifies what hostname must appear in the request's Host: header to
        # match this virtual host. For the default virtual host (this file) this
        # value is not decisive as it is used as a last resort host regardless.
        # However, you must set it for any further virtual host explicitly.
        #ServerName www.example.com

        ServerAdmin webmaster@localhost
        DocumentRoot /var/www/html
        AliasMatch "^/wiki(.*)" "/var/www/html/$1"

        # Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
        # error, crit, alert, emerg.
        # It is also possible to configure the loglevel for particular
        # modules, e.g.
        #LogLevel info ssl:warn

        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined

        # For most configuration files from conf-available/, which are
        # enabled or disabled at a global level, it is possible to
        # include a line for only one particular virtual host. For example the
        # following line enables the CGI configuration for this host only
        # after it has been globally disabled with "a2disconf".
        #Include conf-available/serve-cgi-bin.conf
        AllowEncodedSlashes NoDecode
</VirtualHost>

MediaWiki 設定:

這只是LocalSettings.php需要更改的文件的一個片段。在這裡包含整個預設值有點大。看起來您已經擁有了LocalSettings.php使用 docker-compose 掛載到 docker 容器中的本機副本,因此只需修改$wgScriptPath那裡的變數並重新啟動容器即可。

## The URL base path to the directory containing the wiki;
## defaults for all runtime URL paths are based off of this.
## For more information on customizing the URLs
## (like /w/index.php/Page_title to /wiki/Page_title) please see:
## https://www.mediawiki.org/wiki/Manual:Short_URL
$wgScriptPath = "/wiki";

Docker 組合

現在我們將修改卷部分docker-compose.yml 的 MediaWiki 部分的覆蓋 apache2 配置MediaWiki 網站的檔案。

  mediawiki:
    image: mediawiki
    restart: unless-stopped
    hostname: mediawiki
    ports:
      - "8080:80"
    links:
      - database
    volumes:
      - ./images:/var/www/html/images
      - ./wiki/LocalSettings.php:/var/www/html/LocalSettings.php
      - ./apache2/000-default.conf:/etc/apache2/sites-enabled/000-default.conf
    networks:
      - wiki

答案2

設定根 URL 是解決此問題的唯一穩定的解決方案。

我搜尋“mediawiki root URL”,第二個搜尋指向https://www.mediawiki.org/wiki/主題:Ry90289pdqa86yrd,其中第一個回應告訴我們如何在 MediaWiki 中設定根 URL:

您的 wiki 的 URL 必須在 LocalSettings.php 中設定(就像 $wgLogo,它也在該檔案中設定),您可以透過將 $wgServer 設定為另一個值來變更它。然後,這將使 MediaWiki 輸出以您想要的網域開頭的 URL。

相關內容