在单个docker容器环境中配置nginx(AWS ElasticBeanstalk)

时间:2017-01-15 05:25:35

标签: amazon-web-services nginx docker elastic-beanstalk uwsgi

我目前正在AWS ElasticBeanstalk中使用single container docker environment部署Django + uWSGI应用。这个环境已经附带了nginx,我目前正在尝试配置它。

我正在努力实现以下目标:

  1. 在环境的负载均衡器
  2. 中终止HTTPS
  3. 使用nginx(随环境提供)将HTTP请求重定向到HTTPS
  4. 将请求从nginx传递给uwsgi
  5. 环境信息:

    • 配置和解决方案堆栈名称:单个容器Docker 1.11 版本2.3.0
    • AMI :运行Docker的64位Amazon Linux 2016.09 v2.3.0 1.11.2 2016.09.0
    • Docker版本:1.11.2
    • 代理服务器:nginx 1.10.1

    这是我目前的配置:

    .ebxtensions / 00-负载均衡器-terminatehttps.config

    option_settings:
      aws:elb:listener:443:
        ListenerEnabled: true
        ListenerProtocol: HTTPS
        SSLCertificateId: <resource-id-here>
        InstancePort: 443
        InstanceProtocol: HTTP
      aws:elb:listener:80:
        ListenerEnabled: true
        ListenerProtocol: HTTP
        InstancePort: 80
        InstanceProtocol: HTTP
    

    .ebextensions / 01-nginx的-proxy.config

    files:
      "/etc/nginx/sites-available/test.domain.com.conf":
        mode: "000644"
        owner: root
        group: root
        content: |
          server {
            listen 80;
            server_name test.domain.com;
            access_log /var/log/nginx/$server_name.access.log;
    
            location / {
              return 301 https://$server_name$request_uri;
            }
    
            location = /status/ {
              access_log /var/log/nginx/$server_name.healthd.log healthd;
              include uwsgi_params;
              uwsgi_pass docker;
              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-Host $host;
              proxy_set_header X-Forwarded-Server $host;
            }
    
          }
    
          server {
            listen 443;
            server_name test.domain.com;
            access_log /var/log/nginx/$server_name.access.log;
    
            location / {
              include uwsgi_params;
              uwsgi_pass docker;
              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-Host $host;
              proxy_set_header X-Forwarded-Server $host;
              client_max_body_size 100m;
            }
    
            location /static {
                alias /var/www/static;
            }
          }
    
    commands:
       00_enable_site:
        command: 'rm -f /etc/nginx/sites-enabled/* && ln -s /etc/nginx/sites-available/test.domain.com.conf /etc/nginx/sites-enabled/test.domain.com.conf'
    

    .ebextensions / 02-healthcheckurl.config

    option_settings:
      - namespace:  aws:elasticbeanstalk:application
        option_name:  Application Healthcheck URL
        value:  /status/
    

    application.ini(uwsgi config)

    [uwsgi]
    master = true
    socket = :3031
    processes = 4
    enable-threads = true
    threads = 2
    chdir = /opt/app/
    wsgi-file = test/wsgi.py
    logto2 = /var/log/uwsgi.log
    callable = application
    py-autoreload = 3
    

    现在,在测试配置时:

    检查http://test.domain.com/status/正常

    $ wget http://test.domain.com/status/
    --2017-01-14 23:00:18--  http://test.domain.com/status/
    Resolving test.domain.com... 52.xx.xx.xx, 52.xx.xx.xy
    Connecting to test.domain.com|52.xx.xx.xx|:80... connected.
    HTTP request sent, awaiting response... 200 OK
    

    检查http://test.domain.com/hello/没有按预期工作。它重定向很好,但它会挂起,直到请求超时。

    $ wget http://test.domain.com/hello/
    --2017-01-14 22:59:13--  http://test.domain.com/hello/
    Resolving test.domain.com... 52.xx.xx.xx, 52.xx.xx.xy
    Connecting to test.domain.com|52.xx.xx.xx|:80... connected.
    HTTP request sent, awaiting response... 301 Moved Permanently
    Location: https://test.domain.com/hello/ [following]
    --2017-01-14 22:59:15--  https://test.domain.com/hello/
    Connecting to test.domain.com|52.xx.xx.xx|:443... connected.
    HTTP request sent, awaiting response... 408 REQUEST_TIMEOUT
    2017-01-14 23:00:17 ERROR 408: REQUEST_TIMEOUT.
    

2 个答案:

答案 0 :(得分:4)

按照@ deviavir的建议,我需要允许来自负载均衡器的流量进入EC2实例。

这是我的最终配置:

   .ebextensions
   |-- 00-resources.config
   |-- 01-nginx-proxy.config

<强> .ebextensions / 00-resources.config

Resources:
  AWSEBSecurityGroup:
    Type: "AWS::EC2::SecurityGroup"
    Properties:
      GroupDescription: "Allow traffic to ports 80 and 443 from the load balancer. Restrict SSH access."
  AWSEBLoadBalancer:
    Type: "AWS::ElasticLoadBalancing::LoadBalancer"
    Properties:
      Listeners:
        - {LoadBalancerPort: 80,
          Protocol: 'HTTP',
          InstancePort: 80,
          InstanceProtocol: 'HTTP'}
        - {LoadBalancerPort: 443,
          Protocol: 'HTTPS',
          InstancePort: 443,
          InstanceProtocol: 'HTTP',
          SSLCertificateId: 'arn:aws:acm:us-east-1:xxxx:certificate/yyyy'}
      HealthCheck:
        Target: HTTP:80/status/
        HealthyThreshold: '3'
        UnhealthyThreshold: '5'
        Interval: '30'
        Timeout: '5'
  Port80SecurityGroupIngress:
    Type: "AWS::EC2::SecurityGroupIngress"
    Properties:
      GroupId: {"Fn::GetAtt" : ["AWSEBSecurityGroup", "GroupId"]}
      IpProtocol: tcp
      ToPort: 80
      FromPort: 80
      SourceSecurityGroupName: {"Fn::GetAtt" : ["AWSEBLoadBalancer" , "SourceSecurityGroup.GroupName"]}
  Port443SecurityGroupIngress:
    Type: "AWS::EC2::SecurityGroupIngress"
    Properties:
      GroupId: {"Fn::GetAtt" : ["AWSEBSecurityGroup", "GroupId"]}
      IpProtocol: tcp
      ToPort: 443
      FromPort: 443
      SourceSecurityGroupName: {"Fn::GetAtt" : ["AWSEBLoadBalancer" , "SourceSecurityGroup.GroupName"]}
  SSHSecurityGroupIngress:
    Type: "AWS::EC2::SecurityGroupIngress"
    Properties:
      GroupId: {"Fn::GetAtt" : ["AWSEBSecurityGroup", "GroupId"]}
      IpProtocol: tcp
      ToPort: 22
      FromPort: 22
      CidrIp: xx.xx.xx.xx/yy

<强> .ebextensions / 01-nginx的-proxy.config

files:
  "/etc/nginx/sites-available/test.domain.com.conf":
    mode: "000644"
    owner: root
    group: root
    content: |
      server {
        listen 80;
        server_name test.domain.com;
        access_log /var/log/nginx/$server_name.access.log;

        location / {
          return 301 https://$server_name$request_uri;
        }

        location = /status/ {
          access_log /var/log/nginx/$server_name.status.log;
          uwsgi_pass docker;
          include uwsgi_params;
        }

      }

      server {
        listen 443;
        server_name test.domain.com;
        access_log /var/log/nginx/$server_name.access.log;

        location / {
          uwsgi_pass docker;
          include uwsgi_params;
          client_max_body_size 100m;
        }

        location /static/ {
            root /var/www;
        }
      }

commands:
   00_enable_site:
    command: 'rm -f /etc/nginx/sites-enabled/* && ln -s /etc/nginx/sites-available/test.domain.com.conf /etc/nginx/sites-enabled/test.domain.com.conf'

答案 1 :(得分:1)

修改

OP的问题已经解决Configuring nginx in a single docker container environment (AWS ElasticBeanstalk),我将留下以下信息以保证完整性。

从nginx配置中删除端口443的“server”块,并在.ebxtensions/00-loadbalancer-terminatehttps.config中将aws:elb:listener:443:的{​​{1}}设置为80,并使用nginx'$ http_x_forwarded_proto检查HTTPS ”。

InstancePort

为什么呢?目前看来你的nginx + elb试图一起终止HTTPS,但你的nginx没有回复任何。如果您不打算使用内部HTTPS,那么只需坚持一个nginx服务器块并在那里完成所有逻辑就更有意义了。

我建议使用以下配置文件:

<强> .ebxtensions / 00-负载均衡器-terminatehttps.config

if ($http_x_forwarded_proto != "https") {
  rewrite ^(.*)$ https://$server_name$1 permanent;
}

<强> .ebextensions / 01-nginx的-proxy.config

option_settings:
  aws:elb:listener:443:
    ListenerEnabled: true
    ListenerProtocol: HTTPS
    SSLCertificateId: <resource-id-here>
    InstancePort: 80
    InstanceProtocol: HTTP
  aws:elb:listener:80:
    ListenerEnabled: true
    ListenerProtocol: HTTP
    InstancePort: 80
    InstanceProtocol: HTTP

请注意,我绝不会声称这是解决您问题的最佳解决方案(甚至根本就没有解决方案),408似乎表明了一个有点奇怪的问题 - 但是,这应该会让您更简单的配置调试,希望能让你马上上去。