I have a full web application with a Spring Boot backend and an Angular frontend, both dockerized using Docker and Docker Compose. While I can access the root URL of my Angular application, navigating to other routes results in a "Welcome to nginx!" page
My Setup
Docker Compose File:
services:
postgres:
container_name: postgres-readly
image: postgres
environment:
POSTGRES_USER: username
POSTGRES_PASSWORD: password
PGDATA: /var/lib/postgresql/data
POSTGRES_DB: readly
ports:
- 5432:5432
volumes:
- postgres:/data/postgres
networks:
- readly-network
restart: unless-stopped
mail-dev:
container_name: mail-dev-bsn
image: maildev/maildev
ports:
- 1080:1080
- 1025:1025
readly-api:
container_name: readly-api
image: readly/readly:0.0.1-SNAPSHOT
ports:
- 8088:8088
networks:
- readly-network
depends_on:
- postgres
readly-frontend:
container_name: readly-frontend
image: readly/readly-frontend:0.0.1-SNAPSHOT
ports:
- 4200:80
networks:
- readly-network
depends_on:
- readly-api
networks:
readly-network:
driver: bridge
volumes:
postgres:
driver: local
Angular Dockerfile:
# Stage 1: Build the Angular application
FROM node:18 as build-stage
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
FROM nginx:alpine
COPY nginx.conf /etc/nginx/nginx.conf
COPY --from=build-stage /app/dist/frontend /usr/share/nginx/html
EXPOSE 80
Nginx Configuration (nginx.conf):
events {}
http {
server {
listen 80;
location / {
root /usr/share/nginx/html;
index index.html;
try_files $uri $uri/ /index.html;
}
# Handle JavaScript | CSS files with the correct MIME type
location ~ \.(js|css)$ {
root /usr/share/nginx/html;
include /etc/nginx/mime.types;
}
# Catch-all location to handle refreshes on any route
location ~ ^/.+$ {
root /usr/share/nginx/html;
index index.html;
try_files $uri /index.html;
}
}
}
Problem When I navigate to http://localhost, I can see the root page of my Angular app. However, navigating to other routes like /login results in Nginx serving its default welcome page or returning a 404 error. Here are the relevant logs:
2024-05-29 23:15:38 172.18.0.1 - - [29/May/2024:22:15:38 +0000] "GET / HTTP/1.1" 200 615 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36"
2024-05-29 23:15:42 172.18.0.1 - - [29/May/2024:22:15:42 +0000] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36"
2024-05-29 23:19:14 172.18.0.1 - - [29/May/2024:22:19:14 +0000] "GET /login HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36"
I expected that after configuring Nginx to serve the index.html
for all routes, I would be able to navigate to different paths within my Angular application (e.g., /login
, /dashboard
) without encountering the Nginx default page or 404 errors. Instead, I would see the corresponding Angular components rendered for each route.
Angular Version: 17.1.0
Spring Boot Version: 3.2.5
Nginx Version: alpine
Despite these efforts, the issue persists. What am I missing or doing wrong? Any help would be greatly appreciated!
I've found a solution to the issue. The Dockerfile's COPY command was not correctly copying the Angular build output to the appropriate directory in the nginx server. The previous command was assuming an Angular Universal application structure, which includes a browser subfolder in the build output. However, our Angular application does use Angular Universal, and as such, the build output includes a browser directory.
COPY --from=build /app/dist/frontend/browser /usr/share/nginx/html
This change ensures that the built Angular application is correctly copied to the /usr/share/nginx/html directory in the nginx server. This will ensure that the nginx server can correctly serve our Angular application.