语境:
我对 nginx 还不太熟悉,正在想办法逐步实现这一点。到目前为止,我已经解决这个问题有一段时间了,但由于行为不当(每个主机之间没有传递标头、请求主体为空等),它实际上阻碍了我的某个应用程序的开发。
我在 php-fpm 容器中有三个应用程序,在自己的容器中有一个 nginx 服务器。nginx 容器充当基于请求的主机名(基本 vhost 配置)向 php-fpm 容器提供请求的单一访问点。使用 时一切正常try_files
,但切换到 时proxy_pass
问题就出现了。
每个 php-fpm 主机的 nginx 配置几乎相同,只是要server_name
更改为匹配要处理请求的容器。
我的研究资源链接在页面底部。
问题:
这就是我感到困惑的地方。根据我的设置,proxy_pass
我看到的 nginx 日志中的错误会发生变化。在任何情况下,使用时proxy_pass
请求都不会真正成功完成。以下是各种设置及其相关错误:
环境:
proxy_pass http://appX/; # upstream name
错误:
nginx | 2018/05/08 22:19:48 [error] 10224#10224: *8442 recv() failed (104: Connection reset by peer) while reading response header from upstream, client: 172.18.0.1, server: appX.local, request: "GET / HTTP/1.1", upstream: "http://172.18.0.3:9000/", host: "appX.local"
nginx | 172.18.0.1 - - [08/May/2018:22:19:48 +0000] "GET / HTTP/1.1" 502 568 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36" "-"
环境:
proxy_pass https://appX/; # upstream name
错误:
nginx | 172.18.0.1 - - [08/May/2018:22:20:50 +0000] "GET / HTTP/1.1" 502 568 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36" "-"
nginx | 2018/05/08 22:20:50 [error] 13589#13589: *8446 peer closed connection in SSL handshake (104: Connection reset by peer) while SSL handshaking to upstream, client: 172.18.0.1, server: appX.local, request: "GET / HTTP/1.1", upstream: "https://172.18.0.3:9000/", host: "appX.local"
环境:
proxy_pass http://appX.local/; # hostname
错误(循环多次(逻辑上,基于重定向到 https):
nginx | 172.18.0.6 - - [08/May/2018:22:21:49 +0000] "GET / HTTP/1.0" 301 185 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36" "172.18.0.1"
环境:
proxy_pass https://appX.local/; # hostname
错误(循环了很多次但我不知道为什么):
nginx | 172.18.0.1 - - [08/May/2018:22:23:35 +0000] "GET / HTTP/1.1" 500 588 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36" "-"
环境:
proxy_pass https://appX:9000/;
错误:
nginx | 2018/05/08 22:29:26 [error] 14426#14426: *9563 connect() failed (111: Connection refused) while connecting to upstream, client: 172.18.0.1, server: appX.local, request: "GET / HTTP/1.1", upstream: "https://172.18.0.6:9000/", host: "appX.local"
nginx | 172.18.0.1 - - [08/May/2018:22:29:26 +0000] "GET / HTTP/1.1" 502 568 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36" "-"
环境:
proxy_pass https://appX.local:9000/;
错误:
nginx | 2018/05/08 22:27:39 [error] 14426#14426: *9559 connect() failed (111: Connection refused) while connecting to upstream, client: 172.18.0.1, server: appX.local, request: "GET / HTTP/1.1", upstream: "https://172.18.0.6:9000/", host: "appX.local"
nginx | 172.18.0.1 - - [08/May/2018:22:27:39 +0000] "GET / HTTP/1.1" 502 568 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36" "-"
尝试的补救措施:
- 我尝试将服务器指令中的端口更改为非标准端口以及附加端口号(listen 指令中指定的端口号以及upstream 指令中指定的端口号)。
- 我尝试过不使用 SSL 而是通过标准 HTTP 连接来完成此工作。
- 我删除了所有其他代理设置,然后尝试
proxy_pass
- 这适用于
try_files $uri $uri/ /index.php?$args
,但绕过了代理。 - 我尝试匹配我的研究资源中的各种配置,但无论我做什么更改,都会遇到错误。
配置:
主机名位于我的主机/etc/hostname
文件中,并且所有响应均符合预期。
nginx.conf
worker_processes 1;
daemon off;
events {
worker_connections 1024;
}
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
http {
default_type application/octet-stream;
include /etc/nginx/conf/mime.types;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
include /etc/nginx/conf.d/*.conf;
}
/etc/nginx/conf.d/appX.conf:
upstream appX {
server appX:9000;
}
server {
listen 80;
listen [::]:80;
server_name appX.local appX;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl;
listen [::]:443 ssl;
server_tokens off;
ssl on;
ssl_certificate /etc/nginx/certs/appX.crt;
ssl_certificate_key /etc/nginx/certs/appX.key;
ssl_dhparam /etc/nginx/certs/dhparam.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
ssl_ecdh_curve secp384r1;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
server_name appX.local appX;
root /var/www/appX;
index index.php index.html;
location / {
proxy_read_timeout 90;
proxy_connect_timeout 90;
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Scheme $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $server_name;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Port 443;
proxy_set_header Authorization $http_authorization;
proxy_pass_header Authorization;
proxy_next_upstream error timeout invalid_header;
proxy_hide_header X-Powered-By;
proxy_hide_header X-Pingback;
proxy_hide_header Link;
proxy_cache_bypass $http_pragma $http_authorization;
proxy_ssl_session_reuse off;
proxy_ssl_server_name on;
proxy_pass https://appX;
}
}
docker-compose.yml
version: '3.3'
services:
nginx:
image: evild/alpine-nginx:1.9.15-openssl
container_name: apps_nginx
volumes:
- ./app-one:/var/www/app-one/:ro
- ./app-two:/var/www/app-two/:ro
- ./app-three:/var/www/app-three/:ro
- ./nginx/conf/nginx.conf:/etc/nginx/conf/default.conf:ro
- ./nginx/conf.d:/etc/nginx/conf.d:ro
- ./certs:/etc/nginx/certs
ports:
- 80:80
- 443:443
expose:
- "80"
- "443"
depends_on:
- php-app-one
- php-app-two
environment:
TZ: "America/Los_Angeles"
networks:
default:
aliases:
- app-one.local
- app-two.local
php-app-one:
environment:
TZ: "America/Los_Angeles"
image: joebubna/php
container_name: apps_php_app-one
restart: always
volumes:
- ./app-one:/var/www/app-one
ports:
- 9001:9000
networks:
- default
php-app-two:
environment:
TZ: "America/Los_Angeles"
image: joebubna/php
container_name: apps_php_app-two
restart: always
volumes:
- ./app-two:/var/www/app-two
ports:
- 9000:9000
networks:
- default
php-app-three:
image: joebubna/php
container_name: apps_php_app-three
restart: always
volumes:
- ./app-three:/var/www/app-three
- ./fastcgi_params:/var/www/fastcgi_params
ports:
- 9002:9000
depends_on:
- db
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: root
WORDPRESS_DB_PASSWORD: root
WORDPRESS_DB_NAME: app_three
TZ: "America/Los_Angeles"
networks:
- default
db:
image: mysql:5.6
container_name: apps_mysql
volumes:
- db-data:/var/lib/mysql
- ./mysql/my.cnf:/etc/mysql/conf.d/ZZ-apps.cnf:ro
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_USER: user
MYSQL_PASSWORD: password
MYSQL_DATABASE: cora
TZ: "America/Los_Angeles"
ports:
- 3306:3306
expose:
- "3306"
networks:
- default
volumes:
db-data:
networks:
default:
driver: bridge
任何帮助都将不胜感激。我今天花了好几个小时来做这件事,但我仍然很清楚自己在阅读和反复试验的过程中遗漏了什么。
研究资源:
https://docs.nginx.com/nginx/admin-guide/web-server/reverse-proxy/
https://www.liaohuqiu.net/posts/nginx-proxy-pass/
https://gist.github.com/soheilhy/8b94347ff8336d971ad0
https://groups.google.com/forum/#!topic/xnat_discussion/-S6eYsnwrXg
https://stackoverflow.com/questions/37346560/nginx-server-closes-ssl-connection-for-some-clients
https://stackoverflow.com/questions/38375588/nginx-reverse-proxy-to-heroku-fails-ssl-handshake
https://stackoverflow.com/questions/40580617/nginx-reverse-proxy-upstream-not-working
编辑:根据这里几位好心人的意见,我得出结论,这条路线与我原来的问题相差太大,不值得进一步研究。这可以归咎于困惑和花太多时间盯着同一个问题。如果版主想关闭这个问题,请随意关闭。
答案1
/etc/hostname 或 /etc/hosts 中未指定 docker 的主机名。Docker 有自己的容器间通信。因此,当您引用容器时,您可以使用在 docker-compose.yml 中指定的服务名称来引用该容器。因此,目前您有以下容器:
- nginx:您可以将其称为 nginx 作为主机名。您应该能够使用主机名 nginx ping 容器。
- php-app-one:主机名:php-app-one
- php-应用程序-two
- php-应用程序-three
- D b
顺便说一句,如果你想为容器指定不同的主机名,那么你可以在 docker-compose.yml 中使用它
container_name: 'some-container-name-different-to-the-name-of-service'
让 nginx+php-fpm 协同工作,但每个都在自己的容器中,这非常困难。这是一个 github repo,我手动设置了所有内容,没有使用 docker-compose.yml。Nginx 和 php-fpm 各自在自己的容器中:https://github.com/timogoosen/mediawiki-dockerized/blob/master/nginx/sites-enabled/site.conf 这就是 nginx 配置。您将看到 nginx 容器使用主机名和端口连接到 php-fpm 容器。
fastcgi_pass php-fpm-container:9000;
请参阅 README,它非常具有描述性:https://github.com/timogoosen/mediawiki-dockerized/tree/master/nginx
我建议像你一直做的那样将问题分解成小部分。首先让 nginx 和 php-fpm 分别在各自的容器中工作,然后提供一个只包含以下内容的随机页面:
<?php
phpinfo();
php>
一旦它开始工作,就可以从那里开始。
以下链接可为您提供帮助: https://stackoverflow.com/questions/39901311/docker-ubuntu-bash-ping-command-not-found https://stackoverflow.com/questions/30172605/how-to-get-into-a-docker-container https://stackoverflow.com/questions/30151436/how-to-run-nginx-docker-container-with-custom-config