Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
December 19, 2020 03:07 pm GMT

Build and run Angular application in a Docker container

Cover image by Alice Achterhof on Unsplash

In this blog post I would like to show you how to run your Angular application in a Docker container, then Ill introduce a multi-stage Docker build which will make the container smaller and your work more automated.

Without further introduction, lets get hands dirty and put an Angular app into the Docker container. For purpose of this blog post Ill use my old project aston-villa-app. Its a simple dashboard with league standings of one of my favourite football club Aston Villa.

dashboard

But if you want to use your project you can go with it, all the steps will be the same as for my app.

Ok, so to get my application youll need first to clone it, so open a terminal and type:

> git clone https://github.com/wkrzywiec/aston-villa-app.git
Enter fullscreen mode Exit fullscreen mode

Now, youve got it in your local folder and then enter it. Next make sure that you have installed Node.js and Angular CLI on your local PC. Full instruction can be found on the official Angular website.

Now if you installed both prerequisites you can compile an Angular app. Therefore open a terminal in the root folder of the app and type:

> ng build --prod
Enter fullscreen mode Exit fullscreen mode

This will result in creation of a new folder called dist/aston-villa-app in which all compiled files are put.

Then create a new file called Dockerfile that will be located in the projects root folder. It should have these following lines:

FROM nginx:1.17.1-alpineCOPY nginx.conf /etc/nginx/nginx.confCOPY /dist/aston-villa-app /usr/share/nginx/html
Enter fullscreen mode Exit fullscreen mode

This simple Dockerfile will tell Docker to do three things:

  • first to get a nginx Docker image from Docker Hub tagged with 1.17.1-alpine (its like a version number),

  • then copy-paste the default nginx configuration,

  • and finally copy-paste the compiled application (we done it in previous step) to the container.

My default nginx configuration file looks as follows (its located in the same directory as Dockerfile):

events{}http {    include /etc/nginx/mime.types;    server {        listen 80;        server_name localhost;        root /usr/share/nginx/html;        index index.html;        location / {                try_files $uri $uri/ /index.html;        }    }}
Enter fullscreen mode Exit fullscreen mode

I dont want to go that much into details what each line means here (if you would like there are two very nice links with more explanation at the end of this article). In general, here we define the server on which application will be hosted, its port and default behaviour.

Finally, go back to the terminal and use this command:

> docker build -t av-app-image .
Enter fullscreen mode Exit fullscreen mode

If you check the list of locally available Docker images you should get similar output:

> docker image lsREPOSITORY    TAG            IMAGE ID      av-app-image  latest         a160a7494a19      nginx         1.17.1-alpine  ea1193fd3dde        
Enter fullscreen mode Exit fullscreen mode

To run the image youve just created use following command:

> docker run --name av-app-container -d -p 8080:80 av-app-image
Enter fullscreen mode Exit fullscreen mode

With it first you give a name to the container ( --name av-app-container ), then make sure that it will run in the background (-d), next you map container port to your local ( -p 8080:80 ) and finally you pick a base Docker image to be that youve just created - av-app-image.

To check if new container is running in terminal type:

> docker container lsCONTAINER ID  IMAGE         STATUS         NAMES2523d9f77cf6  av-app-image  Up 26 minutes  av-app-container
Enter fullscreen mode Exit fullscreen mode

Or you can enter a web browser and go to http://localhost:8080/.

Alright! That was easy! Wasnt it? I hope it was for you, but you could see that its a multi step process and as such, beside being time consuming, is also error-prone.

So how it can be done better? Maybe it could be better when we include the compile phase ( ng build --prod ) into the Docker build? That sounds promising, lets do it!

To achieve it Id like to introduce something thats called Multi-stage Docker build.

It was introduced in Docker 17.05 and its main goal was to create smaller containers without loosing the readability of a Dockerfile. With this approach we can divide building a Docker image into smaller phases (stages) where result of previous one (or part of it) can be used in another.

To put it into our context, well divide our Docker build into two stages:

  • compiling the source code into production ready output,

  • running compiled app in a Docker image.

Only compiled output from first stage will be moved to the second so small size of the container will be preserved.

Until this point weve done the second step, so lets focus on a first one.

For compiling the source code well go with different Docker image as a base, which is that containing Node.js. The part of Dockerfile that covers building stage is:

FROM node:12.7-alpine AS buildWORKDIR /usr/src/appCOPY package.json package-lock.json ./RUN npm installCOPY . .RUN npm run build
Enter fullscreen mode Exit fullscreen mode

In this case there are more lines which are responsible for:

  • ( FROM ) getting node Docker image from registry and naming the compilation stage as build (so we will be able to refer to it in another stage),

  • ( WORKDIR ) setting default work directory,

  • ( COPY ) copying package.json & package-lock.json files from local root directory this file contains all dependencies that our app requires,

  • ( RUN ) installing necessary libraries (based on a file copied in previous step),

  • ( COPY ) copying all remaining files with a source code,

  • ( RUN ) and finally compiling our app.

To make building our Docker image even more efficient we can add to the projects root additional file called .dockerignore . This one works similar to .gitignore and in it we can define what files and folders we want to Docker to ignore. In our case we dont want to copy any files from node_modules and dist folders, because theyre not needed in compilation.

Therefore this file should look like as follows:

distnode_modules
Enter fullscreen mode Exit fullscreen mode

Alright so lets combine both Docker stages into one and as a result well get:

### STAGE 1: Build ###FROM node:12.7-alpine AS buildWORKDIR /usr/src/appCOPY package.json package-lock.json ./RUN npm installCOPY . .RUN npm run build### STAGE 2: Run ###FROM nginx:1.17.1-alpineCOPY nginx.conf /etc/nginx/nginx.confCOPY --from=build /usr/src/app/dist/aston-villa-app /usr/share/nginx/html
Enter fullscreen mode Exit fullscreen mode

The only adjustment that I made here is that Ive added comments before each stage and also Ive added --from=build flag to tell Docker that it needs to copy compiled files from build stage (also the source path have changed, because files are located in a different folder).

Going back to a terminal, first you need to create a Docker image:

> docker build -t av-app-multistage-image .
Enter fullscreen mode Exit fullscreen mode

And then run the app (on a different port):

> docker run --name av-app-multistage-container -d -p 8888:80 av-app-multistage-image
Enter fullscreen mode Exit fullscreen mode

And if you now enter http://localhost:8888/ youll see that its running!

If you want to check this project go to its repository on GitHub:

GitHub logo wkrzywiec / aston-villa-app

Aston Villa Dashboard made in Angular 7

References


Original Link: https://dev.to/wkrzywiec/build-and-run-angular-application-in-a-docker-container-19pm

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To