So I want to have a single Nginx web server serving both frontend and backend with Docker. Here is my docker-compose:
version: "3.8"
services:
db: #mysqldb
image: mysql:5.7
container_name: ${DB_SERVICE_NAME}
restart: unless-stopped
environment:
MYSQL_DATABASE: ${DB_DATABASE}
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
MYSQL_PASSWORD: ${DB_PASSWORD}
MYSQL_USER: ${DB_USERNAME}
SERVICE_TAGS: dev
SERVICE_NAME: mysql
ports:
- $MYSQLDB_LOCAL_PORT:$MYSQLDB_DOCKER_PORT
volumes:
- ./docker-compose/mysql:/docker-entrypoint-initdb.d
networks:
- backend
mrmfrontend:
build:
context: ./mrmfrontend
args:
- REACT_APP_API_BASE_URL=$CLIENT_API_BASE_URL
- REACT_APP_BACKEND_ENDPOINT=$REACT_APP_BACKEND_ENDPOINT
- REACT_APP_FRONTEND_ENDPOINT=$REACT_APP_FRONTEND_ENDPOINT
- REACT_APP_FRONTEND_ENDPOINT_ERROR=$REACT_APP_FRONTEND_ENDPOINT_ERROR
- REACT_APP_CUSTOMER=$REACT_APP_CUSTOMER
- REACT_APP_NAME=$REACT_APP_NAME
- REACT_APP_OWNER=""
ports:
- $REACT_LOCAL_PORT:$REACT_DOCKER_PORT
networks:
- frontend
nginx:
image: nginx:alpine
container_name: backend-nginx
restart: unless-stopped
ports:
- 8000:80
volumes:
- ./MRMBackend:/var/www
- ./docker-compose/nginx/backend:/etc/nginx/conf.d/
networks:
- backend
- frontend
app:
build:
args:
user: admin
uid: 1000
context: ./MRMBackend
dockerfile: Dockerfile
image: backend
container_name: backend-app
restart: unless-stopped
working_dir: /var/www/
volumes:
- ./MRMBackend:/var/www
networks:
- backend
volumes:
db:
networks:
frontend:
driver: bridge
backend:
driver: bridge
And here's the Dockerfile for the frontend:
FROM node:16.13.0 as build-stage
WORKDIR /app
COPY package.json ./
COPY package-lock.json ./
COPY ./ ./
RUN npm i
ARG REACT_APP_API_BASE_URL
ARG REACT_APP_BACKEND_ENDPOINT
ARG REACT_APP_FRONTEND_ENDPOINT
ARG REACT_APP_FRONTEND_ENDPOINT_ERROR
ARG REACT_APP_CUSTOMER
ARG REACT_APP_NAME
ENV REACT_APP_API_BASE_URL=$REACT_APP_API_BASE_URL
ENV REACT_APP_BACKEND_ENDPOINT=$REACT_APP_BACKEND_ENDPOINT
ENV REACT_APP_FRONTEND_ENDPOINT = $REACT_APP_FRONTEND_ENDPOINT
ENV REACT_APP_FRONTEND_ENDPOINT_ERROR = $REACT_APP_FRONTEND_ENDPOINT_ERROR
ENV REACT_APP_CUSTOMER=$REACT_APP_CUSTOMER
ENV REACT_APP_NAME=$REACT_APP_NAME
ENV GENERATE_SOURCEMAP=false
RUN npm run build
The problem is that the frontend container can't seem to start. It exit always at startup.
From my understanding I should copy the build content of the build-stage into the nginx folder "/usr/share/nginx/html" but how can I do it from the docker-compose file?
Just using volumes won't work. I need nginx in the docker-compose because it's also serving the backend.
Please note that the backend is working correctly.
UPDATE
My first approach was to use a Dockerfile for the frontend where I copied the content of the build directly into an Nginx image
# Stage 1
FROM node:16.13.0 as build-stage
WORKDIR /app
COPY package.json ./
COPY package-lock.json ./
COPY ./ ./
RUN npm i
ARG REACT_APP_API_BASE_URL
ARG REACT_APP_BACKEND_ENDPOINT
ARG REACT_APP_FRONTEND_ENDPOINT
ARG REACT_APP_FRONTEND_ENDPOINT_ERROR
ARG REACT_APP_CUSTOMER
ARG REACT_APP_NAME
ENV REACT_APP_API_BASE_URL=$REACT_APP_API_BASE_URL
ENV REACT_APP_BACKEND_ENDPOINT=$REACT_APP_BACKEND_ENDPOINT
ENV REACT_APP_FRONTEND_ENDPOINT = $REACT_APP_FRONTEND_ENDPOINT
ENV REACT_APP_FRONTEND_ENDPOINT_ERROR = $REACT_APP_FRONTEND_ENDPOINT_ERROR
ENV REACT_APP_CUSTOMER=$REACT_APP_CUSTOMER
ENV REACT_APP_NAME=$REACT_APP_NAME
#avoid javascript out of memory
ENV GENERATE_SOURCEMAP=false
RUN npm run build
# Stage 2
FROM nginx:1.17.0-alpine
COPY --from=build-stage /app/build /usr/share/nginx/html
EXPOSE $REACT_DOCKER_PORT
CMD nginx -g 'daemon off;'
But in this way I think I'm deploying two Nginx. One in the Dockerfile and one in the Docker-compose. Am I right?