问题
I am trying to get nginx to proxy a websocket connection to a backend server. All services linked via docker-compose.
When i create the WebSocket object in my frontend react app:
let socket = new WebSocket(`ws://engine/socket`)
I get the following error:
WebSocket connection to 'ws://engine/socket' failed: Error in connection establishment: net::ERR_NAME_NOT_RESOLVED
I believe the problem comes from converting ws://
to http://
and that my nginx configuration does not seem to be pick up the match location correctly.
Here is my nginx configuration:
server {
# listen on port 80
listen 80;
root /usr/share/nginx/html;
index index.html index.htm;
location ^~ /engine {
proxy_pass http://matching-engine:8081/;
proxy_http_version 1.1;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location / {
try_files $uri $uri/ /index.html;
}
# Media: images, icons, video, audio, HTC
location ~* \.(?:jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm|htc)$ {
expires 1M;
access_log off;
add_header Cache-Control "public";
}
# Javascript and CSS files
location ~* \.(?:css|js)$ {
try_files $uri =404;
expires 1y;
access_log off;
add_header Cache-Control "public";
}
# Any route containing a file extension (e.g. /devicesfile.js)
location ~ ^.+\..+$ {
try_files $uri =404;
}
}
Here is part of my docker-compose configuration:
matching-engine:
image: amp-engine
ports:
- "8081:8081"
depends_on:
- mongodb
- rabbitmq
- redis
deploy:
restart_policy:
condition: on-failure
max_attempts: 3
window: 120s
client:
image: amp-client:latest
container_name: "client"
ports:
- "80:80"
depends_on:
- matching-engine
deploy:
restart_policy:
condition: on-failure
max_attempts: 3
window: 120s
docker-compose resolves the 'matching-engine' automatically (i can make normal http get/post requests that nginx resolves correctly, and nslookup finds the matching-engine correctly, so i believe the basic networking is working correctly for HTTP requests which leads me to think that the problem comes from the match location in the nginx configuration.
How can one pick up a request that originates from `new WebSocket('ws://engine/socket') in a location directive. I have tried the following ones:
location ^~ engine
location /engine
location /engine/socket
location ws://engine
without any success.
I have also tried changing new Websocket('ws://engine/socket')
to new Websocket('/engine/socket')
but this fails (only ws:// or wss:// prefixes are accepted)
What's the way to make this configuration work ?
回答1:
As you are already exposing port 80 of your client container to your host via docker-compose, you could just connect to your websocket-proxy via localhost:
new Websocket('ws://localhost:80/engine')
来源:https://stackoverflow.com/questions/52757997/configure-nginx-reverse-proxy-with-browser-websocket-and-docker-compose