Docker Nginx 反向代理配置

Docker Nginx 反向代理配置

语境:

我对 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://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/

使用 Nginx 作为多台服务器的反向代理

编辑:根据这里几位好心人的意见,我得出结论,这条路线与我原来的问题相差太大,不值得进一步研究。这可以归咎于困惑和花太多时间盯着同一个问题。如果版主想关闭这个问题,请随意关闭。

答案1

/etc/hostname 或 /etc/hosts 中未指定 docker 的主机名。Docker 有自己的容器间通信。因此,当您引用容器时,您可以使用在 docker-compose.yml 中指定的服务名称来引用该容器。因此,目前您有以下容器:

  1. nginx:您可以将其称为 nginx 作为主机名。您应该能够使用主机名 nginx ping 容器。
  2. php-app-one:主机名:php-app-one
  3. php-应用程序-two
  4. php-应用程序-three
  5. 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

相关内容