Search code examples
reactjsdocker-composewebsocketdockerfiledjango-channels

web socket url with domain name of backend container but doesnot resolve into ip of backend container


i made a docker container for react app and another for django app . now when i make a websocket call

const socket = new WebSocket(
      // `ws://${WEB_SOCKET}:${WEB_SOCKET_PORT}/ws/lobby/`//this works when i feed ip of django app
      'wss://backend:8000/ws/lobby/'

    );

it says home.jsx:9 WebSocket connection to 'wss://backend:8000/ws/lobby/' failed:\

here is docker-compose.yml file

services:
    django-backend:
      container_name: backend 
      restart : always 
      build:
        context: ./server
      ports:
        - "8000:8000"
      depends_on:
        - postgres
        - redis 
      volumes:
        - ./server:/app 
.
.
    chess-frontend:
      container_name: frontend
      restart : always 
      build:
        context: ./chess-front
        target: development  
      ports:
        - "5173:5173"
      volumes:
        - ./chess-front:/usr/src/app

presently i am checking ip of django container and manually updating the web socket url .my question is

  • is there a way to make websocket url using domain name (ie. container name )
  • if not can i automatically get django container's ip in docker-compose up and update in url .

Solution

  • after research i found that web socket urls with domain name of host container do not resolve into ip of host container , even if they are in same network.

    check this stack overflow thread

    however i came up with a way to automatically update the ip of host container by running bash script before the frontend container starts . This fetches ip of backend container and updates my .env file variable

    Dockerfile of react app

    FROM node:alpine AS base 
    WORKDIR /usr/src/app 
    COPY package*.json /usr/src/app/
    RUN npm install 
    
    FROM  base AS development 
    COPY . .
    COPY update_env.sh /usr/src/app/
    EXPOSE 5173
    RUN chmod +x /usr/src/app/update_env.sh
    CMD ["sh", "-c", "npm run dev"]
    FROM base AS production
    COPY . .
    EXPOSE 5173
    CMD ["npm" , "run" , "build"]
    

    update_env.sh

    #!/bin/sh
    BACKEND_CONTAINER_NAME="backend"
    ENV_FILE_PATH="./.env"
    BACKEND_IP=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $BACKEND_CONTAINER_NAME)
    
    if [ -n "$BACKEND_IP" ]; then
        # Checks if VITE_IP already exists in the .env file
        if grep -q '^VITE_IP=' "$ENV_FILE_PATH"; then
            # Updates the existing VITE_IP value
            sed -i "s/^VITE_IP=.*/VITE_IP=$BACKEND_IP/" "$ENV_FILE_PATH"
        else
            # Adds VITE_IP to the .env file
            echo "VITE_IP=$BACKEND_IP" >> "$ENV_FILE_PATH"
        fi
    
        echo "Updated VITE_IP in .env file."
    else
        echo "Error: Unable to obtain the IP address of the backend container."
    fi
    

    docker-compose.yml

    chess-frontend:
        container_name: frontend
        restart : always 
        build:
          context: ./chess-front
          target: development  
        ports:
          - "5173:5173"
        volumes:
          - ./chess-front:/usr/src/app
        depends_on:
          - django-backend
        command: sh -c "/usr/src/app/update_env.sh && npm run dev"
    

    now whenever container restarts , i get ip of backend container automatically.