代码之家  ›  专栏  ›  技术社区  ›  Mihai

如何正确使用Nginx作为多个带SSL的Apache Docker容器的反向代理?

  •  0
  • Mihai  · 技术社区  · 4 年前

    给定以下docker容器:

    • nginx 运行未经修改的官员的服务 nginx:latest 形象
      • 容器名称: proxy
    • 基于改进的official在单独容器中运行的两个应用程序 php:7.4.1-apache 图像
      • 容器名称: app1 app2
    • 所有集装箱 代理 , app1 ,以及 app2 位于Docker创建的同一网络中,具有自动DNS解析功能

    以下是域名示例:

    • local.web.test
    • local1.web.test
    • local2.web.test

    我想实现以下行为:

    • 服务 local.web.test nginx 作为默认服务器块
    • 配置 nginx 代理来自的请求 local1.web.test local2.web.test app1 app2 ,分别在端口上侦听 80
    • 配置 nginx 使用 wildcard SSL certificate

    我遇到了两个问题:

    1. 我注意到以下错误 nginx 日志:
      • 2020/06/28 20:00:59 [crit] 27#27: *36 SSL_read() failed (SSL: error:14191044:SSL routines:tls1_enc:internal error) while waiting for request, client: 172.19.0.1, server: 0.0.0.0:443
    2. 这个 mod_rpaf 似乎无法正常工作(即 ip 地址在 apache 访问日志属于 nginx 服务器[例如。, 172.19.0.2 ]而不是 ip 发出请求的客户端
      • 172.19.0.2 - - [28/Jun/2020:20:05:05 +0000] "GET /favicon.ico HTTP/1.0" 404 457 "http://local1.web.test/" "Mozilla/5.0 (Windows NTndows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36
      • 输出 phpinfo() 对于 Apache环境 表明:
        • HTTP_X_REAL_IP 列出客户端 ip
        • SERVER_ADDR 列出 app1 容器 ip (例如。, 172.19.0.4 )
        • REMOTE_ADDR 显示 代理 容器 ip (例如。, 172.19.0.2 )而不是客户 ip

    为了使其可重复,这就是设置一切的方式。我在Windows计算机上尝试了这个,所以有两个初步步骤。

    1. 初步步骤

      a.在我的 C:\Windows\System32\drivers\etc\hosts 我添加了以下文件:

      127.0.0.1 local.web.test
      127.0.0.1 local1.web.test
      127.0.0.1 local2.web.test
      

      b.我生成了一个自签名的SSL证书 通用名称 设置为 *.local.test 通过

      openssl req -x509 -sha256 -nodes -newkey rsa:2048 -days 365 -keyout localhost.key -out localhost.crt
      
    2. 这个 代理 服务设置

      a nginx.yml 对于 docker-compose :

      version: "3.8"
      
      services:
          nginx:
              image: nginx:latest
              container_name: proxy
              ports:
                  - "80:80"
                  - "443:443"
              volumes:
                  - ./nginx:/etc/nginx/conf.d
                  - ./certs:/etc/ssl/nginx
                  - ./static/local.web.test:/usr/share/nginx/html
              networks:
                  - proxy
      networks:
          proxy:
              driver: bridge
      

      b.内 ./nginx 该装置安装在 /etc/nginx/conf.d 有一个文件 default.conf 其中包括:

      server {
          listen 80 default_server;
          server_name local.web.test;
      
          location / {
              return 301 https://$host$request_uri;
          }
      }
      
      server {
          listen 443 ssl;
          server_name local.web.test;
      
          location / {
              root   /usr/share/nginx/html;
              index  index.html index.htm;
          }
      
          ssl_certificate /etc/ssl/nginx/localhost.crt;
          ssl_certificate_key /etc/ssl/nginx/localhost.key;
      }
      

      c ./certs:/etc/ssl/nginx bind挂载包含自签名证书和密钥的文件夹

      d ./static/local.web.test:/usr/share/nginx/html 使文件可用 index.html 包含

      <h1>local.web.test</h1>
      
    3. 这个 app1 app2 服务设置

      a apache.yml 对于 docker编写 :

      version: "3.8"
      
      services:
          app1:
              build:
                  context: .
                  dockerfile: apache.dockerfile
              image: app1
              container_name: app1
              volumes:
                  - ./static/local1.web.test:/var/www/html
              networks:
                  - exp_proxy
      
          app2:
              build:
                  context: .
                  dockerfile: apache.dockerfile
              image: app2
              container_name: app2
              volumes:
                  - ./static/local2.web.test:/var/www/html
              networks:
                  - exp_proxy
      
      networks:
          # Note: the network is named `exp_proxy` because the root directory is `exp`.
          exp_proxy:
              external: true
      

      b apache.dockerfile 图片看起来像这样:

      # Base image.
      FROM php:7.4.1-apache
      
      # Install dependencies.
      RUN apt-get update && apt-get install -y curl nano wget unzip build-essential apache2-dev
      
      # Clear cache.
      RUN apt-get clean && rm -rf /var/lib/apt/lists/*
      
      # Change working directory,
      WORKDIR /root
      
      # Fetch mod_rpaf.
      RUN wget https://github.com/gnif/mod_rpaf/archive/stable.zip
      
      # Unzip.
      RUN unzip stable.zip
      
      # Change working directory,
      WORKDIR /root/mod_rpaf-stable
      
      # Compile and install.
      RUN make && make install
      
      # Register the module for load.
      RUN echo "LoadModule rpaf_module /usr/lib/apache2/modules/mod_rpaf.so" > /etc/apache2/mods-available/rpaf.load
      
      # Copy the configuration for mod_rpaf.
      COPY ./apache/mods/rpaf.conf /etc/apache2/mods-available/rpaf.conf
      
      # Enable the module.
      RUN a2enmod rpaf
      
      # Set working directory.
      WORKDIR /var/www/html
      

      c.档案 ./apache/mods/rpaf.conf 复制的内容包括:

      <IfModule mod_rpaf.c>
          RPAF_Enable             On
          RPAF_Header             X-Real-Ip
          RPAF_ProxyIPs           127.0.0.1
          RPAF_SetHostName        On
          RPAF_SetHTTPS           On
          RPAF_SetPort            On
      </IfModule>
      

      d ./static/local1.web.test:/var/www/html 绑定挂载 index.php 文件包含:

      <h1>local1.web.test</h1>
      <?php phpinfo(); ?>
      

      这同样适用于 ./static/local2.web.test:/var/www/html

      e 000-default.conf 虚拟主机 app1 app2 未修改:

      <VirtualHost *:80>
          ServerAdmin webmaster@localhost
          DocumentRoot /var/www/html
          ErrorLog ${APACHE_LOG_DIR}/error.log
          CustomLog ${APACHE_LOG_DIR}/access.log combined
      </VirtualHost>
      
    4. 正在启动安装程序

      a.启动 代理 服务器

      docker-compose -f nginx.yml up -d --build
      

      b.启动 app1 app2 服务

      docker-compose -f apache.yml up -d --build
      

      c.检查容器是否 mod_rpaf 已启用

      docker-compose -f apache.yml exec app1 apachectl -t -D DUMP_MODULES 
      

      d.添加两个文件 ./nix 这将在 代理 集装箱在 /etc/nix/conf.d

      • local1.web.test.conf 包含
      upstream app-1 {
          server app1;
      }
      
      server {
          listen 80;
          server_name local1.web.test;
      
          location / {
              return 301 https://$host$request_uri;
          }
      }
      
      server {
          listen 443 ssl;
          server_name local1.web.test;
      
          location / {
              proxy_pass http://app-1;
              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;
          }
      
          ssl_certificate /etc/ssl/nginx/localhost.crt;
          ssl_certificate_key /etc/ssl/nginx/localhost.key;
      }
      
      • 第二个文件是 local2.web.test.conf 具有类似的设置(即编号 1 被替换为 2 )

      e.检查配置并重新启动 代理 集装箱(或重新装载 nginx 服务器)

      docker-compose -f nginx.yml exec proxy nginx -t 
      docker-compose -f nginx.yml exec proxy service nginx reload
      

    问题:

    1. 当我奔跑时 docker logs proxy -f 我注意到上面提到的SSL内部错误: SSL_read() failed
    2. 如果我跑 docker logs app1 -f 并参观 https://local1.web.test ,the ip GET 请求与 ip 代理 容器(即。, 172.19.0.2 )而不是远程客户端
      • 我怀疑铜是这个 RPAF_ProxyIPs 127.0.0.1 ,但我无法手动修复 ip 因为我不知道是什么 ip 集装箱将进入 exp_proxy 网络
      • 我也不能使用主机名,因为 RPAF_ProxyIPs 期待A ip
      • docker inspect proxy 显示 "IPAddress": "172.19.0.2"
      • docker inspect app1 显示 "IPAddress": "172.19.0.4"

    我似乎不明白出了什么问题,我很感激你的帮助。

    0 回复  |  直到 4 年前