Search code examples
reactjsdockerflaskdocker-composecontainers

Docker-compose two service cannot access each other. Connection refused


I am new to docker, now I am trying to containerize my frontend and backend, React and Flask application.

I created my docker-compose file as following, I try to expose them on the same network.

version: '3'

services:
  frontend:
    build: ./client
    ports:
      - "3000:3000"
    environment:
      - BACKEND_URL=http://backend:5000
    networks:
      - my-network
    depends_on:
      - backend

  backend:
    build: ./backend
    environment:
      - FLASK_ENV=production
    ports:
      - "5005:5000"
    networks:
      - my-network
networks:
  my-network:
    driver: bridge

Here's my frontend Dockerfile

# Use an official Node.js runtime as a parent image
FROM node:16.13.2-alpine

# Set the working directory to /app
WORKDIR /app

# Copy the package.json and package-lock.json files to the container
COPY package*.json ./

# Install the dependencies
RUN npm install

# Copy the rest of the application code to the container
COPY . .

# Build the application
RUN npm run build

# Expose the port on which the application will run
EXPOSE 3000

# Define the command to start the application
CMD ["npm", "start"]

and here is my backend dockerfile

FROM python:3.9

COPY requirements.txt /app/
RUN pip install --no-cache-dir -r /app/requirements.txt

COPY . /app/
WORKDIR /app/

EXPOSE 5000

CMD ["python3", "-m", "flask", "run"]

In my front end code, I tried to access the backend host port 5000 with this code

axios.post(`http://backend:5000/deletecode`, {
                    'uuid': uuid,
                }, {
                    headers: {
                        'Content-Type': 'application/json'
                    }
                })

But I got a URL not found, and there's nothing return back to me.

Here's what I tried so far to resolve this issue.

  1. I shell in to the front end container and PING the backend service, and got the response.
/app # ping backend:5000

PING backend:5000 (172.21.0.2): 56 data bytes
64 bytes from 172.21.0.2: seq=0 ttl=64 time=0.257 ms
64 bytes from 172.21.0.2: seq=1 ttl=64 time=0.292 ms
  1. I tried to send a URL request within the backend container, and got success
# curl http://localhost:5000/test

{
  "message": "healthy response"
}
  1. I tried to curl the backend/test from my frontend shell, and it's be denied.

/app # curl backend:5000/test curl: (7) Failed to connect to backend port 5000 after 1 ms: Connection refused

  1. I tried to curl the backend/test on port 5005, which is the port exposed to the host, from the host terminal, and got empty response.

shaopengliu@Shaopengs-MBP Evase % curl http://localhost:5005/test curl: (52) Empty reply from server

Thanks for looking into this question thus far, if there's any suggestion of what I might doing wrong, or anything I could tried out, would be much appreciated.


Solution

  • There is an error in your compose.yml file: whenever you specify a port to expose the syntax is: <host_port>:<container_port>, so in your case for the backed you are exposing the container port 5000 on the local port 5005 while your frontend is trying to connect to port 5000. To solve this problem you can simply change:

    backend:
        build: ./backend
        environment:
           - FLASK_ENV=production
        ports:
           - "5000:5000"
        networks:
           - my-network
    

    ---- EDIT -----

    Another option is leaving the current docker-compose configuration:

    backend:
        build: ./backend
        environment:
           - FLASK_ENV=production
        ports:
           - "5005:5000"
        networks:
           - my-network
    

    And then modify the frontend logic to connect the frontend to the port 5005 instead of port 5000:

    axios.post(`http://backend:5005/deletecode`, {
                    'uuid': uuid,
                }, {
                    headers: {
                        'Content-Type': 'application/json'
                    }
                })
    

    This should solve your problem and allow use a different port for the backend (since the 5000 is already in use).