我读了很多书,也尝试了很多方法,但最终还是没有奏效。希望你能帮助我。
以下是我的设置:
我有一个包含 phpmyadmin 容器的 Docker-compose 文件。我的问题不仅限于 phpmyadmin,这只是一个很好的例子。在 docker-file 下方(重要部分)。如您所见,我希望 phpmyadmin 在https://www.example.com/phpmyadmin/。我认为我的设置会容易得多,如果我使用https://phpmyadmin.example.com/(子域而不是子路径,但这不是我想要的。)phpmyadmin 容器本身运行良好。
phpmyadmin:
image: phpmyadmin/phpmyadmin:latest
container_name: k3633970_phpmyadmin
restart: always
environment:
MYSQL_ROOT_PASSWORD: xxx
PMA_HOST: xxx
PMA_ABSOLUTE_URI: https://www.example.com/phpmyadmin/
networks:
- frontproxy_default
- backend
然后,我有第二个 docker-compose 文件来启动 Nginx。这里没什么特别的:
nginx:
image: nginx:alpine
restart: unless-stopped
volumes:
- ./data/nginx:/etc/nginx/conf.d
ports:
- "80:80"
- "443:443"
networks:
- frontproxy_default
第三,我的 vHost 有一个 Nginx 配置文件。我尝试将所有对 /phpmyadmin/ 的请求代理到 phpmyadmin 容器,将其他所有“/”请求代理到运行 apache+php 的另一个容器。如下所示,我对 phpmyadmin 容器进行了代理传递。当我使用 docker 容器名称时,一切都正常proxy_pass http://k3633970_phpmyadmin/;
(参见注释部分)。
但是当我使用类似这样的变量时,proxy_pass $target;
它就不再起作用了。(我描述相关问题是为了供我和其他人将来参考,所以这篇文章有点长)。发生的事情是,phpmyadmin 的起始页被加载,其中包括一些 JS/CSS 文件,如“js/phpmyadmin.js”或“css/phpmyadmin.css”。Web 浏览器加载了这些文件,但 Nginx 反向代理并没有提供 CSS/JS 文件,而是再次提供了起始页。浏览器显示警告,由于错误的 mime 类型,它无法包含 CSS/JS 文件,因为起始页是以“text/html”的形式提供的。这首先让我找到了错误的踪迹,即 mime 类型是错误的,而实际上 mime 类型是正确的,但传递了错误的文件。
你明白我的意思吗?我试着再解释一遍:
我正在加载 www.example.com/phpmyadmin --> 返回带有 mime 类型 text/html 的 phpmyadmin html 起始页(这是正确的)。此起始页包括 www.example.com/phpmyadmin/js/phpmyadmin.js 和 www.example.com/phpmyadmin/css/phpmyadmin.css,但返回的内容如下:www.example.com/phpmyadmin/js/phpmyadmin.js --> phpmyadmin html首页返回 mime 类型为 text/html。www.example.com/phpmyadmin/css/phpmyadmin.css --> phpmyadmin html首页返回 mime 类型 text/html。
这是我的 nginx 配置文件。
server {
listen 443 ssl;
server_name www.example.com;
server_tokens off;
ssl_certificate /etc/letsencrypt/live/www.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/www.example.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
location /phpmyadmin/ {
resolver 127.0.0.11 valid=30s;
set $target http://k3633970_phpmyadmin/; #Notice the trailing slash!
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass $target;
}
# This works, without variables, but this is not what I want
# location /phpmyadmin/ {
# resolver 127.0.0.11 valid=30s;
# set $upstreamx k3633970_phpmyadmin;
# proxy_set_header Host $host;
# proxy_set_header X-Real-IP $remote_addr;
# proxy_pass http://k3633970_phpmyadmin/;
# gzip on;
# }
location / {
resolver 127.0.0.11 valid=30s;
set $upstream k3633970_vhost_1000303;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://$upstream:80;
}
}
原因如下,根据 Nginx 文档所述:
如果 proxy_pass 指令指定了 URI,那么当请求传递给服务器时,规范化请求 URI 中与位置匹配的部分将被指令中指定的 URI 替换。
好的,明白了。但是我现在该如何解决这个问题呢?
我尝试了能想到的所有组合set $target http://k3633970_phpmyadmin$uri;
set $target http://k3633970_phpmyadmin$request_uri;
set $target http://k3633970_phpmyadmin/$uri;
等等。但没有找到可行的组合。
请帮帮我,我被困住了——谢谢!
最后说明:为什么我需要代理传递中的变量?全部原因是:我有 10 个 docker-compose 文件,其中包含 10 个 wordpress 堆栈,每个堆栈有 3 个容器(apache+php / mariabdb / phpmyadmin)和一个 nginx 反向代理。如果我使用 docker 主机名,则所有 10 个 docker-compose 堆栈必须启动并运行在我启动 nginx 之前。这是不可能的,有时一两个堆栈会因为测试/维护而关闭。使用变量的方法允许在 10 个 docker 堆栈中只有 8 个启动并运行时启动 nginx。
谢谢你!
答案1
您的 nginx 服务必须使用“服务名称”而不是“容器名称”来解析 phpmyadmin 容器 ip。
此外,当您将请求代理到 phpmyadmin 容器时,您必须在 URL 中保留 /phpmyadmin 路径,如果您在末尾添加斜杠,它会删除该部分,因此您不能在末尾添加斜杠。或者您也可以使用正则表达式解析重建完整 URL。
因此这样的事情应该可行:
location ~* ^/phpmyadmin/(.*)$ {
set $query $1;
set $phpmyadmin phpmyadmin; # Service name in docker-compose file
proxy_pass http://$phpmyadmin/phpmyadmin/$query$is_args$args; # Rebuild the URL
}
答案2
在@jonathan-rioux 的帮助下,这是现在的工作配置:
location ~* ^/phpmyadmin/(.*)$ {
resolver 127.0.0.11 valid=30s;
set $query $1;
set $target http://k3633970_phpmyadmin/$query$is_args$args;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass $target;
}
谢谢你!