Reputation: 5965
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?
Upvotes: 4
Views: 10573
Reputation: 59
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"
Upvotes: 1
Reputation: 627
"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
Upvotes: 7
Reputation: 1090
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
Upvotes: 14