Search code examples
node.jsdockerhttpexpressfetch

Docker: http requests from a container to other stalled


I use VPS for testing my web apps online. And I use Docker to run many web apps in the same server. Here is my

docker-compose.yml

version: "3.7"

services:

  gateway:
    build:
      context: ./gateway
      dockerfile: Dockerfile
    restart: always
    ports:
      - 80:3000
    networks:
      erealm:
        ipv4_address: 10.5.0.2

  db:
    image: mysql/mysql-server:5.5
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: 4lf483t0
    networks:
      erealm:
        ipv4_address: 10.5.0.3

  phpmyadmin:
    image: nazarpc/phpmyadmin:latest
    environment:
      - MYSQL_HOST=10.5.0.3:3306
    restart: always
    depends_on:
      - db
    ports:
      - 1234:80
    networks:
      erealm:
        ipv4_address: 10.5.0.4

  static:
    build:
      context: ./static
      dockerfile: Dockerfile
    restart: always
    networks:
      erealm:
        ipv4_address: 10.5.0.5

  onlinecv:
    build:
      context: ./onlinecv
      dockerfile: Dockerfile
    restart: always
    ports:
      - 81:3000
    networks:
      erealm:
        ipv4_address: 10.5.0.10

  speeqapi:
    build:
      context: ./speeq/api
      dockerfile: Dockerfile
    restart: always
    environment:
      MYSQL_SERVER: 10.5.0.3
      MYSQL_PORT: 3306
      MYSQL_USER: xxxxxxxxxx
      MYSQL_PASSWORD: xxxxxxxxxx
      MYSQL_DATABASE: xxxxxxxxxx
    depends_on:
      - db
    networks:
      erealm:
        ipv4_address: 10.5.0.20

  speeqfe:
    build:
      context: ./speeq/fe
      dockerfile: Dockerfile
    restart: always
    environment:
      REACT_APP_API_SERVER: 10.5.0.20:3000
      REACT_APP_STATIC_SERVER: 10.5.0.5:3000
    ports:
      - 82:3000
    depends_on:
      - db
      - static
      - speeqapi
    networks:
      erealm:
        ipv4_address: 10.5.0.21

networks:
  erealm:
    driver: bridge
    ipam:
      config:
        - subnet: 10.5.0.0/24

The main ideia behind this scheme is having only HTTP ports open to the world, while all necessary services run protected by Docker internal network, unaccesible to the world outside.

I use the gateway service to map the HTTP requests coming for the different apps to different ports. So, I have my online CV mapped to CNAME cv.eddealmeida.net and this Speeq app mapped to CNAME speeq.eddealmeida.net in my DNS zone, both pointing to this server. When my server receives a request to http://cv.eddealmeida.net or http://speeq.eddealmeida.net, the Node/Express-based gateway application (listening to port 80) splits the HOST paraments of the request an applies a simple mapping to send the requests to port 81 and 82 respectively.

Well, everything is running fine, but for the internal requests. First I had a problem with nternal name resolution, which I solved by giving IPs to all services, as you may see.

Now my internal requests are going to their correct places, but... the fetch requests made by the speeq frontend are stalling. They just keep stalling, over and over again. I tested the API using curl and everything is fine, it aswers correctly my command line requests. So, there is no problem with my API / Database connection or something like that. Google Chrome gave me this explanation, but I can't see me fitting in any of the cases mentioned.

Have someone ever lived a situation like this to give me a hint? I've been fighting this for the last 24 hours and run out of ideas. I double-checked everything and it still won't work.


Solution

  • I have few assumptions that might help.

    1- Regarding the usage of IPs, I would suggest trying to use network aliases instead of IPs and this is a long-term solution

    2- I can see that you are using ReactJS as a front-end which is a client side - I am assuming that you are using static files after building your React application - in this case you need to expose the backend/api to public ip through port mapping or using domain name points to a public ip where your api is listening or any similar method in order to make the front-end application able to reach it when you open it from the browser (which is a different device in your case). So if speeqfe is a reactjs frontend you need to change the environment variables value which points to the other containers to a public ip in order to make it work properly after building the static files