For production, I have a Dockerfile
which serves a React app using Nginx:
# Stage 1
FROM node:15.6.0-alpine3.10 as react-build
WORKDIR /app/client/
COPY package*.json ./
RUN npm install
COPY ./ ./
RUN npm run build
# Stage 2 - the production environment
FROM nginx:1.19.6
COPY nginx.conf /etc/nginx/conf.d/default.conf
COPY --from=react-build /app/client/build /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
While for the backend written in Node / Express, I have the following Dockerfile
:
FROM node:15.6.0-alpine3.10
WORKDIR /app/server/
COPY package*.json ./
RUN npm install
COPY ./ ./
EXPOSE 8080
CMD ["npm", "start"]
These containers are managed with this docker-compose.yml
:
version: "3.0"
services:
# React Client
web:
image: xxx.dkr.ecr.eu-west-2.amazonaws.com/client:latest
ports:
- "80:80"
# Node Server
server:
image: xxx.dkr.ecr.xxx.amazonaws.com/server:latest
command: npm start
ports:
- "8080:8080"
Here the nginx.conf
:
server {
listen 80;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html =404;
}
include /etc/nginx/extra-conf.d/*.conf;
}
PREMISES
- On local everything works fine, I run React through
react-scripts
and the backend withdocker-compose
(and so without the React client) - Both images have been pushed to
AWS ECR
, their content is the equivalent of theDockerfile
above - When fetching the server, endpoints look like
fetch("/users/:id", {..})
- On
package.json
, I’ve set"proxy": "http://localhost:8080/"
- Both images have both been tested and are working, both on dev and prod
PROBLEM
When hitting an api endpoint from the client, I get a 405 (Not Allowed)
.
That’s actually expected, as I’m not really telling the client (Nginx) where to redirect these calls to.
Inspecting the network tab I can see the request is made against xxx.xxx.xxx.xxx:80
(which represents the client), when it should be redirected to same address but port 8080
instead (where the Express server stands).
On development it works since there’s proxy
set on package.json
, but that’s for development only, so it won’t affect production.
WHAT I TRIED
- Using
links
ondocker-compose
, not supported fromAWS
- Using
driver networks
ondocker-compose
, not supported fromAWS
- Adding
proxy_pass
onnginx.conf
, but haven’t been able to make it working
CONCLUSIONS
So premised all this, how can I connect a React build served with Nginx (client) to a Node server when both dockerized and on production?
I believe it should need some configuration on nginx.conf
, but what I tried didn’t land me that far.
Thank you in advance for your help!
2
Answers
Sample Docker file, Included the Production build in the docker file
To add
nginx
as a server to our app we need to create anginx.conf
in the project root folder. Below is the sample fileFirst you need to specify proxy pass directive for your api calls – I would propose to add
/api
in your fetch calls. Than provide upstream using the same name for your backend service as specified in docker-compose.yml. It is important that backend service proceed the web service in docker-compose.yml, otherwise you would get connection error in nginx like thisnginx: [emerg] host not found in upstream "backend:8080"
You can update your nginx.conf as follows:Or simply in your case provide a proxy pass to localhost as follows: