Dockerize React app and Go API - Proxy Problem - reactjs

I am trying to dockerize my React app with Go API and I faced with the following error.
Proxy error: Could not proxy request /api/todos from localhost:3000 to http://localhost:8080.
See https://nodejs.org/api/errors.html#errors_common_system_errors for more information (ECONNREFUSED).
So I found this on google that I need to add those lines in to my package.json
"proxy": "http://localhost:8080","secure": false,
I have tried couple of other alternatives around above solution but didn't work out as well.
If I start my Go API in the container and if I start my React app from console with npm start, It does work. But If I try to compose them that is not working.
Any advice appreciated!
My docker-compose.yml;
version: '3'
services:
go:
build: backend
restart: always
ports:
- '8080:8080'
react:
build: frontend
restart: always
tty: true
ports:
- "8080:3000"
Here is my backend docker;
FROM golang:latest
RUN mkdir /app
ADD . /app
WORKDIR /app
COPY main.go .
RUN go get -v -u github.com/gorilla/mux
RUN go build main.go
CMD ["/app/main"]
And the my frontend docker;
FROM node:14
RUN mkdir /app
ADD . /app
WORKDIR /app
COPY /package*.json /app
RUN npm install
COPY . /app
EXPOSE 3000
CMD ["npm","start"]

I think the error is the docker-compose port mapping
version: '3'
services:
go:
build: backend
restart: always
ports:
- '8080:8080'
react:
build: frontend
restart: always
tty: true
ports:
- "3000:3000"
this property in package.json
"proxy": "http://localhost:8080"
works in developement mode, not in production
Answer to proxy react request to backend
To proxy your request i think you shoud use another strategy
create a front-end server that implements the proxy (here an example) https://gist.github.com/saniaky/3a5e68acc2b1ee69ed49b6a3eaee094a
OR
add another container with nginx as reverse proxy (here an article that explain something similar to your case https://medium.com/#frontendfoo/docker-react-express-reverse-proxy-15d7b37f8dc2)
version: '3'
services:
go:
build: backend
restart: always
ports:
- '8080:8080'
react:
build: frontend
restart: always
tty: true
ports:
- "3000:3000"
revproxy:
build: ../docker-reverseProxy
image: "reverseproxy:1.0.0"
ports:
- "80:80"
server {
listen 80;
location /api {
proxy_pass http://backend/;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
}
location / {
proxy_pass http://frontend;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
}
}
with reverse proxy you can map a request to a specific path (/api as example) to another server (your server exposed on :8080).
With the above configuration with docker compose you will expose your front on path / (:80) and your back on /api (:80)
UPDATE
I try the solution that i suggest in my last comment, the correct proxy configuration shoud be this (considerig the first strategy that i suggest)
....
api: {
target: 'http://go',
pathRewrite: {
'^/api': '/',
},
},
....
In this way the internal routing of docker compose will be routed to the container called "go" (the name that you assign in your docker compose)

When you make a request to http://localhost:8080/ from inside your react container, your system checks if it can resolve that URI.
The issue is that the only thing that is accessible from inside react is port 3000. There is nothing on the localhost of react on port 8080.
However, the service go is accessible on the address http://localhost:8080/ from the host's machine.
Docker uses its own DNS for containers, and you have to be aware of how this works.
To solve the issue, add a network to react and go containers on your docker-compose.yml file:
version: '3'
services:
go:
build: backend
restart: always
ports:
- '8080:8080'
networks:
- some_network
react:
build: frontend
restart: always
tty: true
ports:
- "3000:3000"
networks:
- some_network
networks:
some_network:
Now that your containers can communicate, change the proxy in the package.json file to:
"proxy": "http://go:8080"
This will direct the traffic to the go container on port 8080, as Docker will look up the domain called go on its embedded DNS server.

Related

How to add Reactjs code to django app on docker-compose with nginx-proxy acme-companion

I am trying to setup a complete django react webapp via docker-compose on AWS. I went through a tutorial to create a django backend with database and ssl via nginx-proxy and letsencrypt acme-companion.
Everything works so far, but I struggle to add reactjs code as the frontend. I created a frontend folder with react-code and a Dockerfile to create the static files:
# Dockerfile frontend
FROM node:15.13-alpine as build
WORKDIR /frontend
# add `/app/node_modules/.bin` to $PATH
ENV PATH /frontend/node_modules/.bin:$PATH
# install app dependencies
COPY package.json ./
COPY package-lock.json ./
RUN npm ci --silent
COPY . ./
RUN npm run build
# The second stage
# Copy React static files
FROM nginx:stable-alpine
COPY --from=build /frontend/build /usr/share/nginx/html
I tried to change the default file in nginx/vhost.d/default to access static frontend files as default and the django-backend-app via /api:
# nginx/vhost.d/default
server {
listen 80;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
location /api {
try_files $uri #proxy_api;
}
location /admin {
try_files $uri #proxy_api;
}
location #proxy_api {
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Url-Scheme $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://backend:8000;
}
location /django_static/ {
autoindex on;
alias /app/backend/server/django_static/;
}
}
Here is the docker-compose file:
# docker-compose.yml
version: '3.8'
services:
backend:
platform: linux/amd64
build:
context: ./django
dockerfile: Dockerfile.prod
logging:
driver: "awslogs"
options:
awslogs-region: "eu-central-1"
awslogs-group: "acquirepad_nginx_proxy"
awslogs-stream: "web"
image: "${BACKEND_IMAGE}"
command: gunicorn core.wsgi:application --bind 0.0.0.0:8000 --log-level=debug
volumes:
- static_volume:/home/app/web/staticfiles
- media_volume:/home/app/web/mediafiles
expose:
- 8000
env_file:
- ./.env
frontend:
build:
context: ./frontend
volumes:
- react_build:/frontend/build
nginx-proxy:
container_name: nginx-proxy
build: nginx
logging:
driver: "awslogs"
options:
awslogs-region: "eu-central-1"
awslogs-group: "acquirepad_nginx_proxy"
awslogs-stream: "nginx-proxy"
image: "${NGINX_IMAGE}"
restart: always
ports:
- 443:443
- 80:80
volumes:
- react_build:/var/www/frontend
- static_volume:/home/app/web/staticfiles
- media_volume:/home/app/web/mediafiles
- certs:/etc/nginx/certs
- html:/usr/share/nginx/html
- vhost:/etc/nginx/vhost.d
- /var/run/docker.sock:/tmp/docker.sock:ro
depends_on:
- frontend
- backend
nginx-proxy-letsencrypt:
platform: linux/amd64
logging:
driver: "awslogs"
options:
awslogs-region: "eu-central-1"
awslogs-group: "acquirepad_nginx_proxy"
awslogs-stream: "nginx-proxy-letsencrypt"
image: nginxproxy/acme-companion
env_file:
- ./.env.staging.proxy-companion
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- certs:/etc/nginx/certs
- html:/usr/share/nginx/html
- vhost:/etc/nginx/vhost.d
- acme:/etc/acme.sh
depends_on:
- nginx-proxy
volumes:
static_volume:
media_volume:
certs:
html:
vhost:
acme:
react_build:
When I run docker-compose on the AWS-EC2 instance, the django backend is still displayed by default on the website and I can not get access to the frontend. I have the feeling, that the file /nginx/vhost.d/default does not have any influence on the webapp at all. Help is much appreciated.

Configuring React, NGINX, Docker-Compose

I'm configuring a React application to work with NGINX and docker-compose - I'm getting either 502 Bad Gateway or 504 Timeout errors on NGINX
My docker compose file:
frontend:
build:
context: ../../
restart: always
volumes:
- '../../:/app'
- '/app/node_modules'
ports:
- "3000:3000"
depends_on:
- "backend"
environment:
- CHOKIDAR_USEPOLLING=true
stdin_open: true
tty: true
nginx:
build:
context: ../../nginx
restart: always
ports:
- "80:80"
- "443:443"
volumes:
- volume1:/usr/share/nginx/html
links:
- "backend"
- "db"
My docker file for NGINX:
FROM nginx:latest
COPY . /usr/share/nginx/html
COPY nginx.conf /etc/nginx/
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
My nginx.conf file:
events{
}
http{
server {
listen 80;
server_name localhost;
root /usr/share/nginx/html;
location / {
proxy_pass http://frontend:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
}
If I navigate to localhost I have in the console:
lightchan-nginx-1 | 2022/03/15 19:25:58 [error]
32#32: *8 connect() failed (111: Connection refused)
while connecting to upstream,
client: 172.26.0.1, server: localhost, request:
"GET / HTTP/1.1", upstream: "http://23.221.222.250:3000/", host: "localhost"
Which tells me that nginx is seeing the upstream (ie the internal ip address that docker-compose is using) from http://frontend. But I don't know why the connection is refused. Any ideas?
EDIT: Someone suggested in another thread to replace
# proxy_set_header Connection 'upgrade';
proxy_set_header Connection "";
Which seemingly just turns off websockets. I don't know why that should have any affect, but that hasn't worked either.
I needed
nginx:
build:
context: ../../nginx
restart: always
ports:
- "80:80"
- "443:443"
volumes:
- volume1:/usr/share/nginx/html
links:
- "backend"
- "db"
- "frontend" <-- this line.
Thanks to David Maze for the 'hint'.

Architecture of Spring boot as backend and React as frontend

I want to make a project that uses spring boot as a backend and React as a frontend.
In the spring boot,
#GetMapping("/home")
I'll use that.
In React,
axios({
url: '/home',
method: 'GET'
}).then((res) => {
callback(res.data);
})
It was confirmed that the data was received by running it as 'npm start'.
However, there was a problem with using a docker.
When I returned using curl on Spring Boot, the result came out well.
React did not work properly. (Proxy setup is also completed.)
So Nginx and React were used together.
However, it did not work well.
Is it right to use Nginx when connecting Spring Boot and React?
I'd really appreciate it if you could tell me the architecture how to connect.
The architecture necessarily hopes for a spring boot of the back end and a react of the front using a docker.
However, if there is a better design, it is also good.
Perhaps, the proxy setting may be wrong? (Error does not appear and the value is blank.)
I added code.
Front/Dockerfile
FROM node:12-alpine
RUN mkdir /app
WORKDIR /app
ENV PATH /app/node_modules/.bin:$PATH
COPY package.json /app/package.json
RUN npm install —no-cache
RUN npm install -g react-scripts
RUN npm install -g react-router-dom
RUN apk add —no-cache git
COPY . /app
CMD ["npm", "start"]
nginx.conf
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
upstream docker-nginx {
server client:3000;
}
server {
listen 80;
server_name localhost;
location /sockjs-node {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_pass http://docker-nginx;
}
location / {
proxy_pass http://docker-nginx;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
include /etc/nginx/conf.d/*.conf;
}
front/docker-compose.yml
version: '3.3'
services:
web:
image: nginx:latest
container_name: web
restart: "on-failure"
ports:
- 80:80
volumes:
- ./web/nginx.conf:/etc/nginx/nginx.conf
client:
build:
context: ./client
container_name: client
restart: "on-failure"
expose:
- 3000
volumes:
- './client:/app'
- '/app/node_modules'
environment:
- NODE_ENV=development
- CHOKIDAR_USEPOLLING=true
stdin_open: true
tty: true
networks:
- clonet_network
restart: always
networks:
clonet_network:
external: true
back/docker-compose.yml
version: '3'
services:
home:
build:
context: .
dockerfile: ./Home/Dockerfile
args:
JAR_FILE: ./Home/build/libs/*.jar
container_name: home_con
volumes:
- ./Home:/app
ports:
- 2004:8080
networks:
- clonet_network
restart: always
networks:
clonet_network:
external: true
I added this it in nginx.conf
location /home {
proxy_pass http://localhost:2004;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
localhost:80/home says '502 Bad Gateway'.

browser doesnt display styles on page in docker nginx react

I try docker. I write configuration for compose, and separate dockerfiles.
All services work good, but my frontend app doesnt display styles, console not have errors, style css load success. I dont have idea what is it
Dockerfile for nginx and react
FROM node:16.13.1 as build
WORKDIR /app
ENV PATH /app/node_modules/.bin:$PATH
COPY ./client .
RUN npm install
RUN npm install react-scripts#3.4.1 -g --silent
RUN npm run build
FROM nginx
COPY --from=build /app/build /var/www/client
COPY nginx/nginx.conf /etc/nginx/
EXPOSE 80
nginx.conf, i think trouble here, but what exactly i dont know
events {
worker_connections 1024;
}
http{
server{
listen 80;
location / {
root /var/www/client;
try_files $uri $uri/ /index.html ;
}
location /api {
rewrite ^/api/?(.*) /$1 break;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://deliverycx_backend:5000;
}
}
}
and docker compose
version: "3.9"
networks:
mongodb_net:
driver: bridge
services:
deliverycx_client:
container_name: deliverycx_client
build:
context: .
dockerfile: ./Dockerfile.webserver
ports:
- "80:80"
networks:
- mongodb_net
deliverycx_backend:
container_name: deliverycx_backend
env_file:
- ./server/.production.env
depends_on:
- redis
- mongodb
build:
context: ./server
networks:
- mongodb_net
links:
- redis
ports:
- "5000:5000"
redis:
image: redis
command:
- "redis-server"
- "--loglevel ${REDIS_LOGLEVEL:-warning}"
- "--databases 2"
- "--save 900 1"
- "--save 300 10"
- "--save 60 10000"
volumes:
- ./redis/data:/data
networks:
- mongodb_net
mongodb:
container_name: mongodb
image: mongo
volumes:
- ./mongo/data:/data/db
networks:
- mongodb_net
EDITED: my web server send css files like text\plain, i include mime.types but its not resolve problem

Proxying API Requests in Docker Container running react app

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?
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
"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
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"
You're now running your React app inside a Docker container, so your "localhost" is no longer your local machine, but the container instead. You need to proxy-it to your backend's IP. Are you running the API in another container?

Resources