In this write up we’ll see how to dockerize an Angular app in an efficient manner with Docker’s Multi-Stage Builds.
At the time of writing this post, I'm using Angular v7
Prerequisites
- NodeJS +8
- Angular CLI (
npm i -g @angular/cli@latest
) - Docker +17.05
- Basic understanding of Docker and Angular CLI commands
The plan
To dockerize a basic Angular app built with Angular CLI, we need to do the following:
- npm install the dependencies (dev dependencies included)
- ng build with --prod flag
- move the artifacts from
dist
folder to a publicly accessible folder (via an an nginx server) - Setup an nginx config file, and spin up the http server
We’ll do this in 2 stages:
- Build stage: will depend on a Node alpine Docker image
- Setup stage: will depend on NGINX alpine Docker image and use the artifacts from the build stage, and the nginx config from our project.
Initialize an empty Angular project
$ ng new myapp
Add a default nginx config
At the root of your Angular project, create nginx folder and create a file named default.conf with the following contents (./nginx/default.conf):
server {
listen 80;
sendfile on;
default_type application/octet-stream;
gzip on;
gzip_http_version 1.1;
gzip_disable "MSIE [1-6]\.";
gzip_min_length 1100;
gzip_vary on;
gzip_proxied expired no-cache no-store private auth;
gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript;
gzip_comp_level 9;
root /usr/share/nginx/html;
location / {
try_files $uri $uri/ /index.html =404;
}
}
Create the Docker file
### STAGE 1: Build ###
# We label our stage as ‘builder’
FROM node:10-alpine as builder
COPY package.json package-lock.json ./
## Storing node modules on a separate layer will prevent unnecessary npm installs at each build
RUN npm ci && mkdir /ng-app && mv ./node_modules ./ng-app
WORKDIR /ng-app
COPY . .
## Build the angular app in production mode and store the artifacts in dist folder
RUN npm run ng build -- --prod --output-path=dist
### STAGE 2: Setup ###
FROM nginx:1.14.1-alpine
## Copy our default nginx config
COPY nginx/default.conf /etc/nginx/conf.d/
## Remove default nginx website
RUN rm -rf /usr/share/nginx/html/*
## From ‘builder’ stage copy over the artifacts in dist folder to default nginx public folder
COPY --from=builder /ng-app/dist /usr/share/nginx/html
CMD ["nginx", "-g", "daemon off;"]
Build the image
$ docker build -t myapp .
Run the container
$ docker run -p 8080:80 myapp
And done, your dockerized app will be accessible at http://localhost:8080
And the size of the image is only ~15.8MB, which will be even less once pushed to a Docker repository.
You can see a full example in this GitHub repository: https://github.com/avatsaev/angular-contacts-app-example
Top comments (8)
What changes need to make to access HTTPS request from nginx? While trying to access HTTPS I am getting CORS error. I think we have to configure HTTPS on nginx. Can you please help for same.
Great post Aslan. I'm new to Angular and was able to get this up and running in 10 mins.
Thanks for the tutorial, how do I use this docker image to run my application in AWS code build/code pipeline?
Hi Aslan, thank you for sharing, it's working for me, I jut want to know the way to Dockerize my Angular App to let it rebuild automatically after every change when I'm in dev mode.
Thank you! Great for getting started
Thanks for the article. How can i build an angular docker image in order to promote it in different environments? I don't want to build an image for each environment
I wrote a post about a way to do that dev.to/beaussart/runtime-config-wi... :)
Hi, this was simple enough to follow even with IVY. Yet having a hard time doing it for universal angular app.