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.
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.
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:
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.
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/[email protected]
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.
In this stage, we are going to base our image on nginx:alpine image.
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:
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.
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.
You can find the whole code for this post here.