Running an Angular application on Docker (for dummies)
For one of our projects we needed to develop a (simple) dashboard application to monitor production environments. Angular is one of the most popular frontend frameworks at the moment, as is Docker as container platform, so we chose to combine these 2 to develop the dashboard.
Preparation for Angular development
When getting started with Angular development, you will first need to install NodeJS and NPM. While writing this blog, NodeJS version 10.15.0 was being used. The corresponding NPM version is 6.4.1. You can check both versions by executing the below statements. For development we use a 64-bit Windows 10 system.
node --version
npm --version
When you have NPM on your system, you can install the Angular CLI (Command Line Interface) very easy by executing the below command.
npm install -g @angular/cli
We have used version 7.1.4 of the Angular CLI. Again, when you want to check your version, this can be done by executing ‘ng version’.
Setting up an Angular application
Now that we have installed the Angular CLI, we can generate our Angular application. It is pretty easy to setup the initial application. This can be done by executing the below statement. Make sure you execute this statement from the directory where you want to generate your project. This will automatically create a new (sub)directory ‘test-application’ with the sources of the Angular demo application. You can accept all defaults in the wizard.
ng new test-application
After the application is generated successfully, we can run the application:
cd test-application
ng serve
As you can also see in the log, you can now access the application via http://localhost:4200.
Now let’s run it on Docker
Now that we have this simple application running, let’s try to run it on a Docker container. But first a brief explanation about some Docker terms:
- The ‘Dockerfile’ is a file used to construct a Docker Image. This is basically the blueprint of what the Docker Image should contain and how it should be installed and configured.
- A Docker Image is built by the ‘Dockerfile’. It’s basically the artifact of the ‘Dockerfile’. However, a Docker image does not run anything yet.
- A Docker Container is the Docker part that actually runs the image. A Docker Container gets spinned up from a Docker Image.
We (obviously) used Docker for Windows on our local system. For this blog version 18.09.1 of Docker was used. You can check your version via ‘docker –version’.
Dockerfile
Now we know what Dockerfiles, images and containers are, we also know that we need to start by creating a ‘Dockerfile’. This file can be created in the root of the Angular application (so directly within the ‘test-application’ directory):
FROM node:11.6.0-alpine AS builder
COPY . ./test-application
WORKDIR /test-application
RUN npm i
RUN $(npm bin)/ng build --prod
FROM nginx:1.15.8-alpine
COPY --from=builder /test-application/dist/test-application/ /usr/share/nginx/html
As you can see, this Dockerfile consists of 2 parts (stages). Both starting with the ‘FROM’ tag. The first one is the stage that will just be used for building the Angular application. The final stage will only contain a webserver and does not require build tools like Node. This obviously has a positive effect on the size of the final image.
The builder stage explained
The ‘builder’ stage will be initialized from the external node image. We will use the (lightweight) Alpine Linux distribution.
Tip: If you want to see how the parent images are built, just look them up on DockerHub. When you search ‘node’ and click the version we use (11.6.0-alpine), we can see the Dockerfile which is used to build this image.
Next, we use the ‘COPY’ tag to copy the current directory (which is the ‘test-application’ directory) content to the Docker image. When you want to exclude files to be copied to the stage(s) and/or image(s), you can create a ‘.dockerignore’ file on the same level as the ‘Dockerfile’. We will also change the working directory of the image to this new directory using the ‘WORKDIR’ tag.
Finally we will run the commands ‘npm i’ and ‘ng build –prod’ to retrieve the required Node modules and build a (production-like) release. The built result will be stored in the ‘dist’ folder.
Building the actual Docker image
Now that we have a binary version of our application available in the builder stage, it’s time to create our runtime Docker image. We will use an Nginx image as it’s base. Nginx is a webserver which we will use to run the built binary from the builder stage.
Again, we will use the ‘COPY’ tag to place the binary files on the image. However, this time the source is not the host system, but the builder stage.
.dockerignore
As mentioned before, the ‘.dockerignore’ file can be used to prevent files being copied to the Docker images. In our case, we won’t include the ‘dist’ folder, because we want to construct this in the builder stage. Copying it from the host system first would not make sense. We also exclude the ‘node_modules’ folder which contains all required Node modules. This folder will be (re)constructed within the builder stage itself by the ‘npm i’ command:
dist/
node_modules/
Building the image and running the container
Now that we have all configuration in place, we can build the Docker image by executing the following command:
docker build --rm -t test-application:latest .
The ‘–rm’ flag is used to automatically remove the intermediate containers once the image has been built successful. The ‘-t’ flag is used to provide a tag name of the Docker image. This tag name is also used when we run the image on a Docker container:
docker run --rm -d -p 90:80/tcp
test-application:latest
Again, the ‘–rm’ flag is used to automatically clean up (remove) the container once it’s stopped. The ‘-d’ flag Is used to start the container in detached mode. Finally, we will connect port 90 of the host system to TCP traffic on port 80 within the image. Port 80 is the default port used by Nginx.
When you browse to http://localhost:90, you will now see the application which is running from Docker!
Tip: When you don’t see your Angular application or changes that should have been deployed, you can try to browse in incognito mode, or to clear the browser cache (CTRL + SHIFT + R in Firefox and Chrome)
Sources:
Geen reacties
Geef jouw mening
Reactie plaatsenReactie toevoegen