1

Context:

I'm fairly new to nginx, and figuring out how to incrementally make this work. I've worked around this problem for a while till now, where it's actually hindering development on one of my apps as a result of improper behavior (headers not being passed between each host, request bodies being empty, etc).

I have three apps in php-fpm containers, and an nginx server in its own container. The nginx container acts as a single access point for serving requests to the php-fpm containers based on the requested hostname (basic vhost configuration). Everything works fine when using try_files, but when switching to proxy_pass the problem presents itself.

The nginx configurations are nearly identical for each of the php-fpm hosts, with the exception of the server_name being changed to match whichever container the request is supposed to be processed by.

My research resources are linked at the bottom of the page.

Problem:

This is where I'm confused. Depending on what I set proxy_pass to will change the error I see in the nginx logs. Under no circumstance when using proxy_pass will requests actually complete successfully. Here are the various settings with their associated error:

Setting:

proxy_pass http://appX/; # upstream name 

Error:

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" "-" 

Setting:

proxy_pass https://appX/; # upstream name 

Error:

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" 

Setting:

proxy_pass http://appX.local/; # hostname 

Error (Loops a bunch of times (logically, based on the redirect to 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" 

Setting:

proxy_pass https://appX.local/; # hostname 

Error (Loops a bunch of times and I don't know why):

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" "-" 

Setting:

proxy_pass https://appX:9000/; 

Error:

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" "-" 

Setting:

proxy_pass https://appX.local:9000/; 

Error:

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" "-" 

Attempted Remedies:

  • I've tried changing the ports in the server directives to non-standard ports as well as appending a port number (both the one specified in the listen directive, as well as the one specified in the upstream directive).
  • I've tried not using SSL and making this work over a standard HTTP connection.
  • I've removed all of the other proxy settings and tried with just proxy_pass
  • This works with try_files $uri $uri/ /index.php?$args, but that bypasses the proxying.
  • I've tried to match the various configurations in my research resources and am experiencing the errors regardless of the changes I make.

Configurations:

Hostname are in my host's /etc/hostname file and all respond as to be expected.

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 

Any help would be greatly appreciated. I've spent quite a few hours on this today and I'm pretty well stuck as to what I've missed in all the reading and trial and error.

Research resources:

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://stackoverflow.com/questions/43500469/nginx-proxy-jwilder-nginx-proxy-connection-reset-by-peer-502-bad-gateway

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

https://umbrella.cisco.com/blog/2015/11/03/lets-talk-about-proxies-pt-2-nginx-as-a-forward-http-proxy/

Use Nginx as Reverse Proxy for multiple servers

EDIT: Based on input from a couple kind individuals here, I have concluded this route has deviated too far from my original problem to warrant further pursuit. This can be chalked up to confusion and too many hours staring at the same problem. If a moderator wants to close this question, please feel free to do so.

2
  • 1
    There's quite a lot going on here. It might be useful to try and reduce your question a bit, to help clarify the issue. For example, you mention switching to proxy_pass, but not why. Was this because nginx is not passing certain headers, as you mention earlier in your question? That's a rather common problem and may not be related to fastcgi at all. Also, I may be mistaken, but I don't think you can even proxy_pass fastcgi because it's a binary protocol and not http. Perhaps you will find this answer helpful (provides a minimal working config): stackoverflow.com/a/38231584/780220 Commented May 9, 2018 at 11:39
  • @Marty you might have pointed me in the right direction here. I started looking to proxy_pass instead of try_files specifically due to response codes being overwritten. So, for instance, php-app-one would response with a 401, then nginx would return a 200 to the client. Very frustrating. But I think you're right -- this is an issue in fastcgi and not proxy_pass. Commented May 9, 2018 at 18:13

1 Answer 1

1

The hostnames for docker are not specified in /etc/hostname or /etc/hosts. Docker has its own inter container communication. So when you refer to a container then you can use the service name that you specified in your docker-compose.yml to refer to the container. So at the moment you have the following containers:

  1. nginx: you can refer to it as nginx as the hostname. You should be able to ping the container using the hostname nginx.
  2. php-app-one: hostname: php-app-one
  3. php-app-two
  4. php-app-three
  5. db

Btw if you want to specify a different hostname for the container then you can use this in your docker-compose.yml

container_name: 'some-container-name-different-to-the-name-of-service' 

Getting nginx+php-fpm to work together, but each in their own container is pretty tough. Here is a github repo where I setup everything manually without docker-compose.yml. Nginx and php-fpm are each in their own container: https://github.com/timogoosen/mediawiki-dockerized/blob/master/nginx/sites-enabled/site.conf That is the nginx config. You will see the nginx container connects to php-fpm container using a hostname and port.

fastcgi_pass php-fpm-container:9000; 

See the README, it is pretty descriptive: https://github.com/timogoosen/mediawiki-dockerized/tree/master/nginx

I suggest break the problem up into small parts as you have been doing. First get nginx and php-fpm each in their own container working then serve a random page that just contains:

<?php phpinfo(); php> 

Once you get that working then go from there.

Here are some links to help you: 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

2
  • thanks for your answer. I've had nginx+php-fpm working with try_files, which as this point I feel is the correct method of doing what I need. The initial problem I was experiencing spawned the problems in this question, and I think that returning to the original problem is a better route to take than trying to force a square peg into a round hole, as this question's approach is doing. Having FastCGI in the mix complicates the proxying factor further, so I need to retreat, regroup, and formulate a better question regarding my base issue. Thanks again! Commented May 9, 2018 at 18:19
  • Cool your welcome. Maybe only have one php-fpm container and mount different volumes in it or something like that. Feel free to hop onto irc.freenode.net on the #docker channel, the people are very helpful and informative. Commented May 10, 2018 at 8:28

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.