Docker NGINX Proxy does not redirect websites
NGINX proxy forwards HTTP GET requests instead of WebSocket handshakes to my django app.
Facts:
- The rest of the non-websocket proxying works fine for the django app.
- I can get WebSockets to work if I connect directly to the django app container. (Relevant log entries below.)
- The nginx config works from localhost on my development machine (no containerization). (Sample log below.)
Relevant magazines:
Daphne log when connecting via nginx container proxy:
`xxx.xxx.xxx.xxx:40214 - - [24/May/2017:19:16:03] "GET /flight/all_flight_updates" 404 99`
Daphne log when bypassing the container proxy and connecting directly to the server:
xxx.xxx.xxx.xxx:6566 - - [24/May/2017:19:17:02] "WSCONNECTING /flight/all_flight_updates" - -
xxx.xxx.xxx.xxx:6566 - - [24/May/2017:19:17:02] "WSCONNECT /flight/all_flight_updates" - -
Local testing of nginx (non-containerized) operation:
[2017/05/24 14:24:19] WebSocket HANDSHAKING /flight/all_flight_updates [127.0.0.1:65100]
[2017/05/24 14:24:19] WebSocket CONNECT /flight/all_flight_updates [127.0.0.1:65100]
Configuration files:
My docker-compose.yml
:
version: '3'
services:
db:
image: postgres
redis:
image: redis:alpine
web:
image: nginx
ports:
- '80:80'
volumes:
- ./deploy/proxy.template:/etc/nginx/conf.d/proxy.template
links:
- cdn
- app
command: /bin/bash -c "envsubst '' < /etc/nginx/conf.d/proxy.template > /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'"
cdn:
image: nginx
volumes:
- ./cdn_static:/usr/share/nginx/static
- ./deploy/cdn.template:/etc/nginx/conf.d/cdn.template
command: /bin/bash -c "envsubst '' < /etc/nginx/conf.d/cdn.template > /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'"
app:
build: .
image: app
ports:
- '8000:8000'
links:
- redis
- db
volumes:
- ./cdn_static:/var/static
My proxy.template
NGINX config template:
upstream cdn_proxy {
server cdn:80;
}
upstream daphne {
server app:8000;
keepalive 100;
}
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
location /static {
proxy_pass http://cdn_proxy;
}
location / {
proxy_buffering off;
proxy_pass http://daphne;
proxy_read_timeout 300;
proxy_connect_timeout 300;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_redirect off;
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 $server_name;
}
}
UPDATE
I built a more compact example of the problem using a tutorial on the NGINX website and posted it on github at https://github.com/c0yote/nginx-websocket-issue .
You get 426 instead of 404, but I believe this is because the simple server doesn't know how to handle the GET sent by NGINX. In this thought, I reinforced the fact that if you issue a GET (for example from a browser) directly against port 8000, you get the same 426.
So the main problem is NGINX is sending GET.
ADDITIONAL INFORMATION:
tcpdump
shows that GET
the web memory server has a field Upgrade
, but GET
against NGINX it doesn't. This is confusing since the command is wscat
identical with the target port exception.
GIGA UPDATE: *
If I take an NGINX proxy from port 80, say it is running 8080. My only guess is: the js client makes some assumptions about port 80. If anyone knows why this is the case, I'd like to know.
source to share