
How to Dockerize and Deploy Angular
Lukas MauserThis Dockerfile builds your Angular app with Node and serves the compiled static files through nginx, using a multi-stage build to keep the final image tiny.
If you're just here to copy and paste, here's the final Dockerfile that will produce an image for your Angular app:
FROM node:22-alpine AS build
WORKDIR /app
# Install dependencies first so this layer is cached when only source changes
COPY package.json package-lock.json ./
RUN npm ci
# Build the production bundle
COPY . .
RUN npm run build
FROM nginx:1.27-alpine AS runtime
# Replace the default nginx config with one that supports client-side routing
COPY nginx.conf /etc/nginx/conf.d/default.conf
# Angular 17+ outputs to dist/<your-app-name>/browser
# Replace angular-app with the name from your angular.json
COPY --from=build /app/dist/angular-app/browser /usr/share/nginx/html
EXPOSE 8080
CMD ["nginx", "-g", "daemon off;"]
You also need a small nginx.conf next to your Dockerfile so deep links and page refreshes fall back to index.html:
server {
listen 8080;
server_name _;
root /usr/share/nginx/html;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
}
And here's the .dockerignore file:
node_modules
dist
.angular
.git
To build and run the image, use these commands:
docker build -t angular-app .
docker run -p 8080:8080 angular-app
Not just here to copy and paste? Let's go over what's happening in the Dockerfile!
The Setup
For this tutorial, I assume you have a standard Angular project created with the Angular CLI. Locally you'd run ng serve to work on it, but that starts a development server that is not meant for production.
For deployment we do two things instead. First we run ng build, which compiles your app into a folder of plain static HTML, CSS, and JavaScript. Then we hand those files to nginx, a fast web server that is very good at serving static assets. That is why the Dockerfile has two stages: one to build, one to serve.
The Dockerfile
The first stage uses Node to install dependencies and build the app:
- Base image:
- Uses Node.js 22 on Alpine for a small build image.
npm ciinstalls the exact versions from your lockfile, which is faster and more reproducible thannpm install.
- Build step:
npm run buildrunsng buildand writes the compiled app todist/<your-app-name>/browser. Since Angular 17 the browser output lives in thatbrowsersubfolder, so double check the path against your owndistfolder.
The second stage throws away Node entirely and only keeps the compiled files:
- Runtime image:
- Uses
nginx:1.27-alpine, which is a couple of megabytes rather than the hundreds Node would add. - Copies our custom
nginx.conf. Thetry_filesline is the important part. Angular is a single-page app, so every route has to fall back toindex.html. Without it, refreshing on a route like/dashboardwould return a 404. - Copies the built files from the first stage into nginx's web root.
- Listens on port 8080 and starts nginx in the foreground so the container stays alive.
Make sure to add the .dockerignore file so node_modules and previous builds are not sent to the Docker daemon. This speeds up the build and keeps the image clean.
Deployment
You can deploy this Docker container to any cloud provider that supports Docker. For example, you could use platforms like Heroku, DigitalOcean, or AWS ECS. Because I am the co-founder of Sliplane, I will show you how to deploy it there.
After signing up, you can create a new service by selecting your GitHub repository. Then just keep the default settings and click on deploy.

After deployment your Angular app will be available under a subdomain of sliplane.app, usually it's just your service name.
You can also see the logs of your app, view metrics such as CPU and memory usage, add persistent storage, and much more. Whenever you push to your repository, Sliplane will automatically deploy your app.
If you want to try out Sliplane, the first 2 days are free! Try it out and let me know what you think :)
Next Steps
Is there anything else you want to know? Do you need help dockerizing your Angular app or deploying it to a specific platform? Feel free to reach out!
Cheers,
Lukas