Angular
Nginx
Docker
404 Error
Web Development

Angular Nginx Docker 404

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

An Angular app that works locally can still return a 404 after deployment behind Nginx in Docker. The failure usually appears when you refresh a deep link such as /users/42 or open that URL directly in a new tab.

This is almost always a routing problem rather than a Docker problem. Angular handles routes in the browser, but Nginx only knows how to serve files unless you explicitly tell it to fall back to index.html.

Why the 404 Happens

Angular uses client-side routing. When the browser first requests /dashboard, Nginx tries to find a real file or directory at that path. Since a typical single-page application only has static assets plus index.html, Nginx returns 404 unless configured otherwise.

The fix is to serve index.html for unknown application routes and let Angular Router decide what screen to render.

Nginx Configuration for an Angular SPA

The most important directive is try_files. It tells Nginx to serve the requested file if it exists, and otherwise fall back to index.html.

nginx
1server {
2    listen 80;
3    server_name _;
4
5    root /usr/share/nginx/html;
6    index index.html;
7
8    location / {
9        try_files $uri $uri/ /index.html;
10    }
11}

With that configuration:

  • '/main.js serves the real JavaScript file.'
  • '/assets/logo.png serves the real image file.'
  • '/users/42 falls back to index.html, then Angular handles the route in the browser.'

If your app lives under a subpath such as /portal/, the rule must match that base path and the Angular build must use the same base href.

Building and Serving with Docker

A common deployment pattern is a multi-stage Docker build. The first stage compiles the Angular app, and the second stage serves the generated files with Nginx.

dockerfile
1FROM node:20-alpine AS build
2WORKDIR /app
3
4COPY package*.json ./
5RUN npm ci
6
7COPY . .
8RUN npm run build -- --configuration production
9
10FROM nginx:1.27-alpine
11COPY nginx.conf /etc/nginx/conf.d/default.conf
12COPY --from=build /app/dist/my-app /usr/share/nginx/html

The dist/my-app path must match your Angular output directory. If the copy path is wrong, Nginx may start successfully but serve an empty directory or the default welcome page instead of your app.

You can test the container locally with a command like this:

bash
docker build -t angular-nginx-demo .
docker run --rm -p 8080:80 angular-nginx-demo

After the container starts, open http://localhost:8080. Then try a hard refresh on a nested route to confirm the fallback works.

Matching Angular Configuration to the Server

Nginx is only one part of the setup. Angular must also generate asset URLs that match the deployment location.

If the app is hosted at the domain root, the default base href is usually fine. If it is hosted under a subdirectory, build with the matching base href:

bash
npm run build -- --configuration production --base-href /portal/

When the base path and the Nginx location block disagree, you may see broken assets, blank pages, or 404 errors for JavaScript bundles even if the route fallback itself is correct.

Common Pitfalls

  • Missing try_files $uri $uri/ /index.html; in the main location block. This is the most common cause of deep-link 404 errors.
  • Copying the wrong build output into the Nginx image. Check the actual dist folder name produced by your project.
  • Deploying under a subpath without updating Angular base-href. Route fallback might work while static assets still fail.
  • Using the same Nginx location for both the SPA and an API. API routes usually need a separate location /api/ proxy block so they do not fall back to index.html.
  • Debugging inside the browser only. It is often faster to inspect the running container and verify that index.html and the built asset files are really present in /usr/share/nginx/html.

Summary

  • Angular routes are handled in the browser, but Nginx serves files.
  • A direct request to a client-side route returns 404 unless Nginx falls back to index.html.
  • Use try_files in Nginx and copy the correct Angular build output into the image.
  • Keep Docker, Nginx, and Angular base-href aligned, especially for subpath deployments.
  • If refresh works on / but not on nested routes, the server routing configuration is the first place to look.

Course illustration
Course illustration

All Rights Reserved.