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'.
Related
I have a React project which is Dockerized along with asp.net core 6.0 app and SQL Server database. the production yaml file is as below:
version: '3.9'
services:
# UI Container spec. note that 'ui' is the name of the container internally (also 'container_name')
ui:
container_name: myapp-ui-prod
image: myapp-ui-prod
env_file: ./UI/.env
build:
context: ./UI
dockerfile: DockerFile_UI.prod
ports:
- 1337:80
networks:
- psnetwork
links:
- api
# Database Container spec.
sql:
container_name: myapp-sql
image: myapp-sql
environment:
ACCEPT_EULA: 'Y'
SA_PASSWORD: 'Pa55w0rd'
build:
context: ./DockerDB
dockerfile: DockerFile_SQL
ports:
- 1633:1433 # Map 1433 from inside the container to 1633 host to avoid port conflict with local install
networks:
- psnetwork
# API container spec.
api:
container_name: myapp-api
image: myapp-api
build:
context: ./Api
dockerfile: DockerFile_API
environment:
ASPNETCORE_ENVIRONMENT: Development
ASPNETCORE_URLS: http://+:5555
ports:
- "5555:5555"
networks:
- psnetwork
links:
- sql
networks:
psnetwork:
driver: bridge
The React project can ping api container successfully while when I call the api graphql endpoint through http it gives net::ERR_CONNECTION_TIMED_OUT error. The nginx configuration file is as below:
upstream api_backend {
server api:5555;
keepalive 8;
}
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;
}
# server_name example.com;
location /api {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://api/api;
proxy_redirect off;
}
}
# server {
# }
And the ApolloClient configuration in React app is:
const client = new ApolloClient({
uri: process.env.REACT_APP_BASE_URL+ '/api/graphql',
cache: new InMemoryCache()
});
the .env file contents is:
REACT_APP_BASE_URL="http://api:5555"
The project works when I use localhost:5555 IP address.
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'.
I have a multi-container docker app in React that uses Nginx as a server. When I try to open it in the browser I get 502 Bad Gateway error with a message:
2021/12/30 11:58:44 [error] 31#31: *31 connect() failed (111: Connection refused) while connecting to upstream, client: 172.23.0.1, server: , request: "GET /favicon.ico HTTP/1.1", upstream: "http://172.23.0.2:3000/favicon.ico", host: "localhost:3050", referrer: "http://localhost:3050/"
Here is nxing config file:
upstream client {
server client:3000;
}
upstream api {
server api:5000;
}
server {
listen 80;
location / {
proxy_pass http://client;
}
location /sockjs-node {
proxy_pass http://client;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
location /api {
rewrite /api/(.*) /$1 break;
proxy_pass http://api;
}
}
Here's the fragment of docker-compose for Nginx:
nginx:
depends_on:
- api
- client
restart: always
build:
dockerfile: Dockerfile.dev
context: ./nginx
ports:
- '3050:80'
How can I fix this?
Thank you for posting this question, it helped me.
Also, in docker-compose.yml file inside the root directory. I had to add stdin_open: true,
client:
stdin_open: true
build:
dockerfile: Dockerfile.dev
context: ./client
volumes:
- /app/node_modules
- ./client:/app
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
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.