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.
With that configuration:
- '
/main.jsserves the real JavaScript file.' - '
/assets/logo.pngserves the real image file.' - '
/users/42falls back toindex.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.
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:
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:
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
distfolder 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 toindex.html. - Debugging inside the browser only. It is often faster to inspect the running container and verify that
index.htmland 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_filesin Nginx and copy the correct Angular build output into the image. - Keep Docker, Nginx, and Angular
base-hrefaligned, especially for subpath deployments. - If refresh works on
/but not on nested routes, the server routing configuration is the first place to look.

