4

I'm running a simple react app in a docker container. During development I'm using the proxy key in package.json to specify my backend api url: "proxy": "http://localhost:5000"

Everything works fine when I run npm start locally. However, when I npm start inside a docker container it's pointing to "http://localhost:3000". I'm tried setting the proxy manually as well, as demonstrated by my Dockerfile below, but nothing seems to work:

FROM node:13-alpine
WORKDIR /app

# install dependencies
COPY package*.json ./
RUN npm install --silent

# copy source code
COPY src/ ./src/
COPY public/ ./public/

RUN npm config set proxy http://localhost:5000  # set manully
CMD ["npm", "start"]

Am I doing something wrong or is this not possible?

Johnny Metz
  • 5,977
  • 18
  • 82
  • 146

3 Answers3

12

You need to set the port to your backend service instead of localhost while running the app in docker. Check the following docker container and it's services for example. We have the frontend running in port 3000 and backend running in port 5000. So, replace localhost with "proxy": "http://backend:5000"

version: '3'

services:
  backend:
    build: ./backend
    ports:
      - 5000:5000
  frontend:
    build: ./frontend
    ports:
      - 3000:3000
    links:
      - backend
    command: npm start

Suman Kharel
  • 920
  • 11
  • 13
  • 1
    Hi @Suman It seems very interesting your answer. tried your answer in my App but it didnt work. Just in case that you have time to help me out. Here is a link to a post that i wrote yesterday. https://stackoverflow.com/questions/63136530/how-to-connect-api-with-react-app-through-docker Thanks – Zenit Jul 30 '20 at 10:13
  • 1
    @Zenit it seems that you have received your answer. If not please let me know so i can look it up for you! – Suman Kharel Aug 14 '20 at 12:32
7

"proxy": "http://localhost:5000" works perfectly fine in the development stage, because the webpack DevServer handles proxying by itself. Once you deploy your React application, it stops operating. I have experienced the same problem when trying to make my containerized React application talk to the containerized API. I was using Nginx as a web server to serve the React application. I followed this guide to integrate Nginx with a Docker container. This is how the nginx.conf initially looked like:

server {

  listen 80;

  location / {
    root   /usr/share/nginx/html;
    index  index.html index.htm;
    try_files $uri $uri/ /index.html;
  }

  error_page   500 502 503 504  /50x.html;

  location = /50x.html {
    root   /usr/share/nginx/html;
  }

}

but after I made a few tweaks here and there, I came up with this configuration (I am going to talk what api stands for in a bit):

server {

  listen 80;

  location / {
    root   /usr/share/nginx/html;
    index  index.html index.htm;
    try_files $uri $uri/ /index.html;
  }

  location /api {
    resolver 127.0.0.11;
    proxy_set_header X-Forwarded-Host $host;
    proxy_set_header X-Forwarded-Server $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_pass http://api:8000;
  }

  error_page   500 502 503 504  /50x.html;

  location = /50x.html {
    root   /usr/share/nginx/html;
  }

}

What has changed? I added a root location for the API endpoints, since all of them have a common prefix /api. The proxy_pass property lets us proxy all the request coming to the /api to our backend that is exposed via port 8000. api is a just a name of the container defined in the docker-compose.yaml.

For the reference, this is my React app's Dockerfile:

# build environment
FROM node:15.2.1 as build
WORKDIR /app
COPY ./client ./
RUN yarn
RUN yarn build

# production environment
FROM nginx:stable-alpine
COPY --from=build /app/build /usr/share/nginx/html
COPY --from=build /app/nginx/nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

and the most important file (docker-compose.yaml):

version: "3.8"

services:
  client:
    build:
      context: .
      dockerfile: client/Dockerfile
    container_name: $CLIENT_CONTAINER_NAME
    restart: unless-stopped
    env_file: .env
    ports:
      - "1337:80"
    networks:
      - my-network
    links:
      - api
  api:
    build:
      context: .
      dockerfile: server/Dockerfile
    container_name: $API_CONTAINER_NAME
    restart: unless-stopped
    env_file: .env
    ports:
      - "8000:8000"
    networks:
      - my-network
    links:
      - mongo
  mongo:
    image: mongo
    container_name: $DB_CONTAINER_NAME
    restart: unless-stopped
    env_file: .env
    environment:
      - MONGO_INITDB_ROOT_USERNAME=$MONGO_INITDB_ROOT_USERNAME
      - MONGO_INITDB_ROOT_PASSWORD=$MONGO_INITDB_ROOT_PASSWORD
      - DB_NAME=$DB_NAME
      - MONGO_HOSTNAME=$MONGO_HOSTNAME
    volumes:
      - ~/data/db:/data/db
    ports:
      - 27017:27017
    networks:
      - my-network

networks:
  my-network:
    driver: bridge
Taiyr Begeyev
  • 547
  • 1
  • 9
  • 12
0

If you are using Docker, in your client's package.json, instead of "proxy":"http://localhost:5000", you need change it to "proxy":"https://<container_name>:5000"

For example, since I name my express container as "express-server", I need to add this:

// in client-side's package.json
"proxy": "http://express-server:5000"

enter image description here

kenjigoh
  • 39
  • 4