使用nginx反向代理的Docker容器内的闪亮服务器将不会遵循301重定向

时间:2016-06-13 11:40:38

标签: r nginx amazon-ec2 docker shiny-server

这个问题有三个要素:

  1. Docker容器:我有一个部署在EC2实例上的Docker容器。更具体地说,我有rocker/shiny图像,我使用它运行:

    sudo docker run -d -v /home/ubuntu/projects/shiny_example:/srv/shiny-server -p 3838:3838 rocker/shiny
    
  2. 闪亮的服务器:标准的Shiny服务器配置文件不受影响,设置为提供端口3838上/srv/shiny-server文件夹中的所有内容以及本地内容~/projects/shiny_example映射到容器的/srv/shiny-server/

    在我当地的~/projects/shiny_example,我已经克隆了一个随机的Shiny app:

    git clone https://github.com/rstudio/shiny_example 
    
  3. nginx :我已将nginx设置为反向代理,而here则是/etc/nginx/nginx.conf的完整内容。

  4. 问题在于,通过这种设置,当我尝试检索http://<ip-address>/shiny/shiny_example时,我得到了404.关于可能出错的主要线索是,当我这样做时:

     wget http://localhost:3838/shiny_example
    

    从我的EC2实例的命令行,我得到:

      

    - 2016-06-13 11:05:08-- http://localhost:3838/shiny_example   解析localhost(localhost)... 127.0.0.1

         

    连接到localhost(localhost)| 127.0.0.1 |:3838 ...已连接。

         

    发送HTTP请求,等待响应... 301永久移动

         

    位置:/ shiny_example / [关注]

         

    - 2016-06-13 11:05:08-- http://localhost:3838/shiny_example/

         

    重用与localhost的现有连接:3838。

         

    发送HTTP请求,等待响应... 200 OK

         

    长度:3136(3.1K)[text / html]

         

    保存到:'shiny_example.3'

         

    100%[============================================ ================================================== ================================&gt;] 3,136 - .- K / s在0.04s

         

    2016-06-13 11:05:09(79.6 KB / s) - 'shiny_example.3'已保存[3136/3136]

    强调是我的

    我认为我的nginx配置没有考虑到在请求Docker映射端口时,存在301重定向。我认为该解决方案涉及proxy_next_upstream,但我希望在我的上下文中尝试设置它时会有所帮助。

    我也认为这个问题可以解决Docker上下文,但是理解如何在从Docker容器中的Shiny服务器请求资源时如何防止301重定向,以及是否预期这种行为会很好。

3 个答案:

答案 0 :(得分:1)

我无法确定没有更多输出,但怀疑您的错误在您的proxy_redirect行中:

    location /shiny/ {
      rewrite ^/shiny/(.*)$ /$1 break;
      proxy_pass http://localhost:3838;
      proxy_redirect http://localhost:3838/ $scheme://$host/shiny_example;
      proxy_http_version 1.1;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection $connection_upgrade;
      proxy_read_timeout 20d;
    }

尝试将其更改为:

    location /shiny/ {
      rewrite ^/shiny/(.*)$ /$1 break;
      proxy_pass http://localhost:3838;
      proxy_redirect http://localhost:3838/ $scheme://$host/shiny/;
      proxy_http_version 1.1;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection $connection_upgrade;
      proxy_read_timeout 20d;
    }

原因是301标题从&#34; http://localhost:3838&#34;要添加尾部斜杠,它会被重写为&#34; http://localhost/shiny_example&#34;在你的nginx配置中不存在,加上它也可能从路径中删除斜杠。这意味着来自&#34; http://localhost:3838/shiny_example&#34;到&#34; http://localhost:3838/shiny_example/&#34;会被重写为&#34; http://localhost/shiny_exampleshiny_example/&#34;,此时你会获得404.

答案 1 :(得分:0)

任何事情都没有错。基本上,/etc/nginx/nginx.conf中的一行是include /etc/nginx/sites-enabled/*,其中包含已启用网站的默认文件,其中包含以下行:

 server {
        listen 80 default_server;
        listen [::]:80 default_server ipv6only=on;

        root /usr/share/nginx/html;
        index index.html index.htm;

        # Make site accessible from http://localhost/
        server_name localhost;

        location / {
                # First attempt to serve request as file, then
                # as directory, then fall back to displaying a 404.
                try_files $uri $uri/ =404;
                # Uncomment to enable naxsi on this location
                # include /etc/nginx/naxsi.rules
        }

覆盖了端口80和位置/的监听指令。在/etc/nginx/nginx.conf文件中为已启用站点的默认conf文件注释掉include指令解决了所有问题。

答案 2 :(得分:0)

不确定这是否仍然相关,但我在这里有一个最小的例子:https://github.com/mRcSchwering/butterbirne

服务shinyserver(基于rocker/shiny)以服务webserver(基于nginx:latest)启动:

version: '2'

services:

  shinyserver:
    build: shinyserver/

  webserver:
    build: webserver/
    ports:
      - 80:80

我配置了ngin,因此它会直接重定向到闪亮的服务器根目录。在我的情况下,我添加了应用程序(此处称为myapp)作为shinyserver的根(因此不需要/myapp)。这是整个nginx.conf

user  nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       /etc/nginx/mime.types;

    default_type  application/octet-stream;
    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;


    # apparently this is needed for shiny server
    map $http_upgrade $connection_upgrade {
        default upgrade;
        ''      close;
      }

    # proxy shinyserver
    server {
        listen 80;

        location / {
          proxy_pass http://shinyserver:3838;
          proxy_redirect http://shinyserver:3838/ $scheme://$host/;
          proxy_http_version 1.1;
          proxy_set_header Upgrade $http_upgrade;
          proxy_set_header Connection $connection_upgrade;
          proxy_read_timeout 20d;
          proxy_buffering off;
        }
    }
}