Bienvenue sur IndexError.

Ici vous pouvez poser des questions sur Python et le Framework Django.

Consultez la FAQ pour améliorer vos chances d'avoir des réponses à vos questions.

Pourquoi ai-je une erreur 502 lorsque je requête mon application Django ?

+2 votes

J'ai récupéré une application django et je veux la faire tourner dans docker avec nginx et gunicorn.
J'ai déjà réussi à la faire fonctionner avec nginx et gunicorn dans le même conteneur Docker.
Je souhaite maintenant la faire fonctionner avec un conteneur pour nginx et un autre pour gunicorn.
Voici mon fichier de config nginx:

server {
    listen      80;
    charset     utf-8;
    server_name localhost;

    access_log /var/log/nginx/nginx.access.log;
    error_log /var/log/nginx/nginx.error.log;

    location / {
        proxy_set_header X-Forwarded-Host $server_name;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_pass http://myapp:8000;
    }
}

Voici mon script de lancement gunicorn:

set -e
LOGFILE=/var/log/gunicorn/myapp.log
LOGDIR=$(dirname $LOGFILE)
LOGLEVEL=debug
NUM_WORKERS=3

USER=root
GROUP=root

cd /srv/myapp
test -d $LOGDIR || mkdir -p $LOGDIR
exec gunicorn_django -w $NUM_WORKERS \
  --user=$USER --group=$GROUP --log-level=$LOGLEVEL \
  --log-file=$LOGFILE 2>>$LOGFILE -b 127.0.0.1:8000

et enfin les scripts avec lesquels je crée les conteneurs:

pour gunicorn:

docker run -ti --rm -p 8000:8000 --name myapp prod_myapp:latest bash

et pour nginx:

docker run -ti -p 80:80 --rm --name nginx --link myapp:myapp prod_nginx:latest bash

Quand j'essaye de requêter depuis firefox j'ai une erreur 502 (bad gateway), et dans les logs d'erreur nginx j'ai l'erreur suivante:

    [error] 17#0: *1 connect() failed (111: Connection refused) while connecting to upstream, client: 172.17.42.1, server: localhost, 
request: "GET / HTTP/1.1", upstream: "http://172.17.0.4:8000/", host: "localhost"

Dans les logs gunicorn je ne vois même pas de requête entrante. Quelqu'un verrait-il l'origine du problème et aurait-il une solution ?

demandé 13-Mar-2015 par NicoS (144 points)

C'est pas le host localhost le soucis ?

perso, j'ai plutot haussé un sourcil sur la conf nginx a la ligne
proxy_pass http://myapp:8000;
myapp a pas l'air tres resolvable, la.
mais bon, matin, pas de café, toussa...

@ashgan myapp est parfaitement résolvable, j'arrive à pinger le container myapp à partir du container nginx.

@foxmask: effectivement cela m'intrigue aussi mais je ne sais pas à quoi cela correspond. lorsque je lance tcptrack dans le conteneur gunicorn, je vois bien la connexion qui vient du conteneur nginx s'établir pendant quelques secondes, malgré le fait que le log d'erreur nginx comporte host: "localhost".

3 Réponses

+2 votes
 
Meilleure réponse

En fait dans le script de lancement gunicorn il fallait mettre 0.0.0.0 en adresse de bind:

set -e
LOGFILE=/var/log/gunicorn/myapp.log
LOGDIR=$(dirname $LOGFILE)
LOGLEVEL=debug
NUM_WORKERS=3

USER=root
GROUP=root

cd /srv/myapp
test -d $LOGDIR || mkdir -p $LOGDIR
exec gunicorn_django -w $NUM_WORKERS \
  --user=$USER --group=$GROUP --log-level=$LOGLEVEL \
  --log-file=$LOGFILE 2>>$LOGFILE -b 0.0.0.0:8000
répondu 14-Mar-2015 par NicoS (144 points)
sélectionné 14-Mar-2015 par NicoS
0 votes

regarde ici pour un un nginx sous docker:
http://jasonwilder.com/blog/2014/03/25/automated-nginx-reverse-proxy-for-docker/
et ici:
https://github.com/jwilder/nginx-proxy

il te manque surtout une partie (pas testé) qui devrait pas etre tres loin de ca:
upstream myapp { server xxx.xxxx.xxx.xxx:8000; }
apres, va falloir eplucher la tambouille docker, mais la, je passe la main :)

répondu 13-Mar-2015 par ashgan (698 points)

Nope, l'upstream n'est qu'un raccourci, qui permet aussi de faire du load balancing. Mais spécifier directement le host et le port dans la directive proxy_pass marche très bien aussi.

+2 votes

A priori, la ligne

 proxy_pass http://myapp:8000;

est correcte car les containers sont linkés entre eux et devraient se trouver par leur name.

La solution est plutôt du coté de l'option proxy-allow-ips de gunicorn. Il faut qu'il accepte les requêtes depuis l'ip du container nginx.

Avec un peu de chance, un

--proxy-allow-ips 172.17.42.1

fera l'affaire.

Visiblement, cette option ne prend qu'une adresse ip comme entrée, et pas un nom d’hôte
Dans l'idéal, faire un

--proxy-allow-ips nginx

serait le plus simple mais je suppose que ca ne marchera pas.

Sinon il faudra passer dynamiquement l'IP du container docker au container de ton app dans une variable d’environnement, a coup de docker inspect, du style :

NGINX_IP=$(docker inspect --format '{{ .NetworkSettings.IPAddress }}'  nginx)
docker run -ti --rm -p 8000:8000 -e NGINX_IP=$NGINX_IP --name myapp prod_myapp:latest bash 

puis dans le lancement de gunicorn, quelque chose du genre :

exec gunicorn_django -w $NUM_WORKERS \
  --user=$USER --group=$GROUP --log-level=$LOGLEVEL \
  --log-file=$LOGFILE 2
   --proxy-allow-ips $NGINX_IP
  >>$LOGFILE -b 127.0.0.1:8000
répondu 13-Mar-2015 par jc (2,704 points)

Bien pensé, j'y ai beaucoup cru mais ce n'était pas cela le problème. Même sans l'option (qui au passage en vrai s'appelle --proxy-allow-from), j'arrive quand même à faire tourner l'application.

...