3 votes

Configuration de nginx dans un environnement de conteneur docker unique (AWS ElasticBeanstalk)

Je déploie actuellement une application Django + uWSGI à l'aide d'un fichier de type environnement docker à conteneur unique dans AWS ElasticBeanstalk. Cet environnement est déjà livré avec nginx, que j'essaie actuellement de configurer.

J'essaie d'obtenir ce qui suit :

  1. Terminer HTTPS au niveau de l'équilibreur de charge de l'environnement
  2. Rediriger les demandes HTTP vers HTTPS en utilisant nginx (qui est livré avec l'environnement)
  3. Passer les requêtes de nginx à uwsgi

Informations sur l'environnement :

  • Configuration et nom de la pile de solutions : Conteneur unique Docker 1.11 version 2.3.0
  • AMI : 64bit Amazon Linux 2016.09 v2.3.0 exécutant Docker 1.11.2 2016.09.0
  • Version de Docker : 1.11.2
  • Serveur Proxy : nginx 1.10.1

Voici ma configuration actuelle :

.ebxtensions/00-loadbalancer-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 (configuration uwsgi)

[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

Maintenant, en testant la configuration :

Vérification de http://test.domain.com/status/ fonctionne bien

$ 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

Vérification de http://test.domain.com/hello/ ne fonctionne pas comme prévu. Il redirige bien, mais il se bloque ensuite jusqu'à ce que la requête soit terminée.

$ 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.

4voto

blaze Points 1213

Suivant la suggestion de @deviavir, j'avais besoin d'autoriser le trafic de l'équilibreur de charge vers l'instance EC2.

C'est ma configuration finale :

   .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'

1voto

deviavir Points 105

éditer :

Le problème de l'OP a été résolu ici Configuration de nginx dans un environnement de conteneur docker unique (AWS ElasticBeanstalk) Je laisse les informations ci-dessous pour être complet.


Supprimez le bloc "server" pour le port 443 de votre configuration nginx, et dans la section .ebxtensions/00-loadbalancer-terminatehttps.config ensemble aws:elb:listener:443: 's InstancePort en 80, et vérifiez le HTTPS en utilisant '$http_x_forwarded_proto' de nginx.

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

Pourquoi ? Actuellement, il semble que votre nginx+elb essaient de terminer HTTPS ensemble, mais votre nginx ne répond pas avec aucun. Si vous ne prévoyez pas d'avoir un HTTPS interne, il est plus logique de s'en tenir à un seul bloc de serveurs nginx et d'y faire toute votre logique.

Je propose les fichiers de configuration suivants :

.ebxtensions/00-loadbalancer-terminatehttps.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

.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;

        if ($http_x_forwarded_proto != "https") {
          set $test  http;
        }

        if ($request_uri = /status/) {
          set $test  "${test}+status";
        }

        if ($test = "http") {
          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;
          client_max_body_size 100m;
        }

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

        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;
        }

      }

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'

Notez que je ne prétends en aucun cas que c'est la meilleure solution à votre problème (ou même une solution tout court), la 408 semble indiquer un problème quelque peu étrange - cependant, cela devrait vous permettre d'obtenir une configuration un peu plus simple à déboguer et, espérons-le, vous permettre de démarrer immédiatement.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X