我想将 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_filter
和proxy_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
。这适用于在 发出的所有初始 GET 请求https://sub.example.com/wiki/
,也适用于上述链接。
但是,单击 后<a href="/mw-config/index.php">...
,index.php
会发出进一步的请求 - 再次指向https://sub.example.com/
。由于 URL 未重写且 referer 表示https://sub.example.com/mw-config/index.php
,因此这些请求返回 500。
我的问题是:如何修复此行为,使我的应用程序永久驻留在其各自的位置?不幸的是,我目前无法更改子域名。
任何帮助都将不胜感激!
编辑:
由于我想使用可能遇到类似问题的多个其他应用程序,因此我想提出一个更通用的解决方案。在某些情况下,我无法控制基本 URL。
答案1
这里有几件事我们需要达成共识才能使它发挥作用:
- NGINX配置:基于路径的路由,反向代理
- 我已经尝试过你的配置,并且我相信你的配置是正确的
- Apache2配置:正确将 URI 映射到文件路径和脚本
- 使用指令
AliasMatch "^/wiki(.*)" "/var/www/html/$1"
去除/wiki
并正确映射到内部文件路径
- 使用指令
- 维基百科设置:添加
/wiki
路径,以便Nginx
知道在哪里反向代理链接,然后Apache2
可以剥离/wiki
并使用正确的内部文件路径。- 在运行 MediaWiki 设置后创建的文件
$wgScriptPath = "/wiki";
中进行设置,并在您的LocalSettings.php
docker-compose.yml
- 在运行 MediaWiki 设置后创建的文件
- Docker 组成:通过将修改后的本地文件挂载到
mediawiki
docker容器中来保留这些更改
Apache2
我们将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/Topic:Ry90289pdqa86yrd其中第一个响应告诉如何在 MediaWiki 中设置根 URL:
必须在 LocalSettings.php 中设置您的 wiki 的 URL(例如 $wgLogo,也在该文件中设置),您可以通过将 $wgServer 设置为其他值来更改它。这样 MediaWiki 输出的 URL 就会以您想要的域名开头。