Raphael Matto
Raphael Matto

Reputation: 31

WebSocket connection to 'wss://react-apps.raphe.localhost:3000/ws' failed:

I've had a docker-compose/nginx setup going for years & it's been beautiful—hot reload worked for React, Vue, Golang, Flask, Django, Php, etc & all the services could talk to each other, & I used it for projects at several companies ... but recently I decided to update to modern versions of the Alpine, Node, Python, etc Docker images. It's been a mostly smooth transition except for the node services, where I've hit a wall. Both vanilla CRA (create-react-app) and vanilla Vite React SWC installs come back with the same error, after I start the docker-compose/nginx network:

CRA:

WebSocket connection to 'wss://react-apps.raphe.localhost:3000/ws' failed: 

Vite:

WebSocket connection to 'wss://vite-react-apps.raphe.localhost:8082/' failed: 

w/CRA, the page loads, but there is no hot-reload. With Vite/SWC I get a blank white page. For reference, the url for one of the services (CRA) is: https://react-apps.raphe.localhost:8082/. If I start either service in dev mode without docker/nginx, they run fine w/hot-reload, e.g., these both work:

http://localhost:3000/
http://localhost:5173/

I found various solutions for solving those ^ issues on the web. One was to put WDS_SOCKET_PORT=0 in the .env or docker-compose environment. Another, with vite, was to mess around with the vite.config.js & I tried everything under the sun in that file. Another was to use WATCHPACK_POLLING=true with CRA and CHOKIDAR_USEPOLLING=true with vite. Nothing worked ...

...so, after a couple days of pain, I tried rolling all my code back a year, and got the same error! So I'm really dead in the water. I started to think it might have something to do with my Docker or Chrome versions, since those are the only pieces of the puzzle I haven't rolled back & were updated recently. Could that really be the issue?

Has anyone else dealt with this? It's crazy annoying. Here's an example of one of my development docker-compose services, for reference:

  react-apps:
    container_name: ${COMPOSE_PROJECT_NAME}-react-apps
    restart: always
    build:
      context: ../rfe_react_apps/
      dockerfile: Dockerfile.dev
    command: yarn start
    environment:
      - REACT_APP_SENTRY=${SENTRY}
      - REACT_APP_ENV=development
      - BROWSER=none
    expose:
      - 3000
    volumes:
      - ../rfe_react_apps/:/app/

... & the relevant bit in the nginx config:

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    include /etc/nginx/conf.d/certs.txt;
    ssl_protocols TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    server_name react-apps.*;
    location / {
        proxy_pass http://react-apps:3000;
    }
}

... & the full vite Chrome console error, in case there's a clue there (I don't totally understand what it's trying to tell me):

GET https://vite-react-apps.raphe.localhost:8082/src/main.jsx 500
client.ts:78 WebSocket connection to 'wss://vite-react-apps.raphe.localhost:8082/' failed: 
setupWebSocket @ client.ts:78
(anonymous) @ client.ts:68
client.ts:78 WebSocket connection to 'wss://localhost:5173/' failed: 
setupWebSocket @ client.ts:78
fallback @ client.ts:43
(anonymous) @ client.ts:99
client.ts:48 [vite] failed to connect to websocket.
your current setup:
  (browser) vite-react-apps.raphe.localhost:8082/ <--[HTTP]--> localhost:5173/ (server)
  (browser) vite-react-apps.raphe.localhost:8082/ <--[WebSocket (failing)]--> localhost:5173/ (server)
Check out your Vite / network configuration and https://vitejs.dev/config/server-options.html#server-hmr .

At this point I've given up, & I rely on this stack for income. I will be so happy if anyone can unstick me here!

Upvotes: 1

Views: 1299

Answers (2)

yousef elsayed
yousef elsayed

Reputation: 41

I had a similar issue to yours.

where i have multiple docker containers one for nginx and the other for vite react app and in development i was using the nginx to serve the react app and nginx configurations was set to respond to any request on / path by forwarding the request to the dev server on a separate container but websocket was failing and giving me the same error as your.

so the following configuration fixed it

server {
  location / {
    proxy_pass http://client; # this is my docker container address not important to you
    # the following lines is for vite to be able to connect over web socket
    # so the hmr functionality can work
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "Upgrade";
  }
}

i'm using vite 5.2.0, and the websocket connection was hitting on the root path /

I hope this answer helps you, or anyone had a the same issue as me and was searching on the internet for a quite some time.

Upvotes: 1

Raphael Matto
Raphael Matto

Reputation: 31

I banged my way to a solution (no errors now, hot-reload works), although I don't love it. Here's what I had to change to get the CRA service going: added these vars to the CRA service's environment in my docker-compose file:

- WDS_SOCKET_HOST=localhost
- WDS_SOCKET_PORT=3000

... and swapped out the expose section for this:

ports:
  - 3000:3000

That has the unintended side-effect of making the service available at http://localhost:3000, which is fine (since this is just a development environment), but messy. For vite, SWC was erroring out, something about missing bindings, so I switched to vanilla vite/React and finally got lucky with this combination: the docker-compose service:

vite-react-apps:
    container_name: ${COMPOSE_PROJECT_NAME}-vite-react-apps
    restart: always
    build:
      context: ../rfe_vite_react_apps/
      dockerfile: Dockerfile.dev
    command: yarn dev --port 5173 --host
    ports:
      - 5173:5173
    volumes:
      - ../rfe_vite_react_apps/:/app/

Again, annoyingly, this means the service is also available at http://localhost:5173/. So the important bits there ^ are the --port 5173 (for some reason, it says 5173 is already in use otherwise, even when it isn't), and, again, swapping out the expose section for ports. I also had to add this to my vite.config.js:

  server: {
    hmr: {
      port: 5173,
      host: "localhost",
      protocol: "ws",
    },
  },

Again, don't love this! ... but it's only for my development docker-compose file. Everything works fine in production, I can use expose instead of ports, etc. Not sure why I have to do this stuff now, it worked so beautifully before. If anyone knows of a cleaner solution, or can explain why things changed, I'd love to know.

Upvotes: 0

Related Questions