I have made a MEAN stack application and want to containerize it using docker for publishing on azure app services. To do so i created 3 service, the client, the server and the nginx for handling the reverse proxy. as per my compose.yaml file:
services:
nginx:
build:
context: ./proxy
dockerfile: Dockerfile # Custom Nginx Dockerfile
container_name: proxy
image: jeroenp98/waresy-proxy:latest
ports:
- "80:80" # Expose Nginx on port 80 to the public
depends_on:
- client # Ensure frontend and backend are running before Nginx starts
- server
networks:
- app-network
server:
build: .
container_name: waresy-server
image: jeroenp98/waresy-server:latest
environment:
- JWT_SECRET=${JWT_SECRET}
- MONGODB_URI=${MONGODB_URI}
expose:
- "3000:3000"
networks:
- app-network
client:
build:
context: ./client
dockerfile: Dockerfile
container_name: waresy-client
image: jeroenp98/waresy-client:latest
expose:
- "80:80"
depends_on:
- server
networks:
- app-network
networks:
app-network:
driver: bridge
However the issue i'm running in to is when i run the container using
docker compose up
and visit localhost:80 i will see the default nginx welcome screen instead of my angular app.
enter image description here
The api is working however and i can make requests to it.
i cannot figure out why the container is serving this index.html file and not the index.html generated by the npm build command.
this is the nginx.conf settings:
server {
listen 80;
listen [::]:80;
# Proxy requests to the frontend
location / {
proxy_pass http://client:80; # Forwarding to the frontend's internal port 80
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 requests to the backend API
location /api/ {
proxy_pass http://server:3000; # Forwarding to backend's internal port 3000
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;
}
}
client dockerfile
# client/Dockerfile
FROM node:22.12.0-alpine AS builder
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm install -g @angular/cli
RUN npm install
COPY . .
RUN npm run build
FROM nginx:alpine
# Copy built Angular files
COPY --from=builder /app/dist/client/browser /usr/share/nginx/html
CMD ["nginx", "-g", "daemon off;"]
nginx dockerfile
# Use the official Nginx image
FROM nginx:alpine
# Remove the default Nginx config
RUN rm /etc/nginx/conf.d/default.conf
# Copy Nginx config to the container
COPY nginx.conf /etc/nginx/conf.d/
# Expose port 80 to the outside world
EXPOSE 80
# Start Nginx
CMD ["nginx", "-g", "daemon off;"]
Any help would be appreciated
i checked the files in the docker container but couldn't find the index.html file from the angular app.
i checked the output path of the angular.json file which is set to
"outputPath": "dist/client"
i tried copying the files from both /app/dist/client and /app/dist/client/browser
So the issue was that even though the output of the build was set to dist/client/browser instead of dist/client like the angular.json file says, the reason i saw the default nginx html page was that it did not replace it during the COPY command with the angular html page.
i fixed it by first removing the default index.html page first before copying the angular build output to it.
So this the added RUN rm -rf /usr/share/nginx/html/* line fixed the issue.
FROM nginx:alpine
# delete default nginx index page
RUN rm -rf /usr/share/nginx/html/*
# copy the build output from the builder stage to the nginx html directory
COPY --from=builder /app/dist/client/browser /usr/share/nginx/html
CMD ["nginx", "-g", "daemon off;"]