Building Docker Images for Deploying Angular Apps

| By Maina Wycliffe | | | Angular

In this post, we are going to look at how to deploy an angular app using docker. Docker containers can be used to simplify the process of developing, testing and deploying your app into different environments. With docker containers, you can be assured that the application will run the same no matter the environment in which it is deployed.

In this demo, we are going to build a docker image for deploying an angular app to two different environments. One for production and the other for staging. Our demo application is going to have 3 environments – development, staging and production. We will be using the  development environment locally for developing and testing using ng serve. While the other two environments are deployed remotely. If you don’t know how to setup environments in angular, you can checkout this post I did earlier. Without further ado.

How it works

Once you are ready to deploy on either environment – staging or production, we are going to use a dockerfile to specify how our deployment image with our built app is going to be build. A dockerfile is a special file that contains instructions on how to build our docker image. Since we need to automate the build process as much as possible, we are going to be building the angular app together with docker image.

First, we are going to pull a NodeJS (node:8.X.X) from docker hub and use it to build our angular application. Then, we will copy our compiled angular application inside the dist directory to our deployment container. Our deployment image will be a nginx alpine image – as you might have guessed using nginx proxy server. We will also need to copy the configuration to redirect all paths to index.html and compress our server output.

Getting Started

To make things simple, we will have two dockerfiles for each of our deployment environments. They will have some minor differences such as the target environment when building our angular application. We are going to be using a multi stage docker build, where in stage 1, we will create a docker image to build our angular application.

And then in the second stage we copy the results of the first stage and use it build and create a super light deployment docker image. This allows our final image to only contain the important files for deployment without any development files and tools being carried over. You can learn more about docker multistage build here.

First, we need to create a new directory called .docker in the root of our angular workspace. Inside it we are going to create three files. Two dockerfiles (prod.dockerfile and staging.dockerfile) and a nginx (nginx.conf) configurations file.

Nginx Configurations

In this configuration file, we are going to have rules for redirecting all paths to index.html and add rules to compress content before being sent to the browser. You can replace this with apache or any other web server you are familiar with. Just make sure the configuration files are okay for your server and copy them in the correct directory inside your final image. Inside the nginx configuration file (nginx.conf), add the following content:

worker_processes  1;

events {
    worker_connections  1024;
}

http {
    server {
        listen 80;
        server_name  localhost;
        root   /usr/share/nginx/html;
        index  index.html index.htm;
        include /etc/nginx/mime.types;
        gzip on;
        gzip_min_length 1000;
        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;

location / {
            try_files $uri $uri/ /index.html;
        }
    }
}

Creating the Dockerfiles

Both dockerfiles will be the same, with some minor differences. For instance, the staging dockerfile will build targeting staging environment while the production will build with the prod flag. It is also possible to use the same dockerfile for both, but I find separating them doesn’t hurt. It also allows me to experiment with the staging version before making the final changes to the production one. This is all up to you. We are going to separate the dockerfiles into two sections, staging 1 and stage 2. As I said earlier, stage 1 will build the angular application and stage two will create a docker image for deployment.

Stage 1

First we need a base image to build our first docker image on, since we are building using NodeJS, we will use node:8.11.4 docker image. Feel free to use any version of NodeJS you are comfortable with.

FROM node:8.11.4 as node

Next, we declare a working directory inside our image and then copy our angular workspace into the directory.

WORKDIR /app

COPY . .

Next, we need to install our @angular/cli and if you are a fan of Yarn like me, install it too.


RUN npm i yarn

RUN yarn global add @angular/cli@latest

Next, install the dependencies for your project by running either yarn install or npm install depending on the package manager you are using. And finally, it’s time to build your angular application. For staging environment, we will use the following command:


RUN ng build --configuration=staging

While for production environment, we will use the following command:

RUN ng build –prod

And now let’s move to stage two.

Stage 2

In this stage, we are going to base our image on nginx:alpine image.

FROM nginx:alpine

And then, copy all build artefacts to /usr/share/nginx/html directory and copy the nginx.conf to the /etc/nginx/conf.d/default.conf.

COPY --from=node /app/dist/angular-docker-deployment /usr/share/nginx/html
COPY --from=node /app/.docker/nginx.conf /etc/nginx/conf.d/default.conf

NB: One thing to note for those using Angular 5, copy the DIST directory instead of the project name directory inside the DIST directory.

COPY --from=node /app/dist /usr/share/nginx/html

You can check out both docker files here.

Building Docker Images

And finally, you can build your image by running the following command at the root of your angular workspace: Windows:

docker build --rm -f .docker\staging.dockerfile -t webapp:latest .

Linux and Mac:

docker build --rm -f .docker/staging.dockerfile -t webapp:latest .

Replace webapp:latest with your preferred image name and add your image tag after colons. To build a production image, replace .docker\staging.dockerfile with .docker\prod.dockerfile. Windows:

docker build --rm -f .docker\prod.dockerfile -t webapp:latest .

Linux and Mac:

docker build --rm -f .docker/prod.dockerfile -t webapp:latest .

And your docker image is ready for deployment. In the next post, I will cover how to deploy your docker image once you have built it. Sample Code You can find the whole code for this post here.

Angular 6 - Angular CLI Workspaces

One of the least talked about features of Angular 6 is Angular CLI Workspaces. Workspaces or Angular CLI Workspaces give angular developers …

Read More
Logging HTTP Errors in Angular 6

In my last post, I looked at how you can use HTTP Interceptors to attach and refresh authorization tokens. In this post, we are going to use …

Read More
Refreshing Authorization Tokens – Angular 6

In this post, we are going to build a http interceptor for refreshing authorization tokens once expired. The idea here is to be able to …

Read More
Getting Started with Debugging Angular Apps in VSCode

In this post, I am going to show you how to get started with debugging angular apps in VSCode. We shall target Firefox, Chrome and Microsoft …

Read More
Angular Material Autocomplete with HTTP Lookup

In this demo, we will build an angular autocomplete component that gets autocomplete suggestions from a http service such as a REST API. The …

Read More
Lazy Loading Images in Angular 6

In most web apps, images form a huge chunk of the size of the content. If you had, let’s say over 50 images with each having 100Kbs (after …

Read More

Comments