Search code examples
angularspring-bootdockernginxdocker-compose

Issues with Nginx and Dockerized Angular Application Routes


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

# 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.

Additional Information

  • 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!


Solution

  • 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.