Get the Newsletter

Setup Docker

If you're interested in getting started with Docker to build projects, this article will take you through setting up both your machine and a production quality starter project.

Introduction

The emergence of containers has been changing the software culture; developers and companies are embracing DevOps and CI/CD to automate build, test, and deployment of their products. If you're interested in how you can containerize your Aurelia application, you are in the right place.

The tendency towards microservices and the culture of DevOps brings collaboration to development and operational teams, breaking down a huge system into lightweight, independently-deployable parts. Besides, it helps us to run our applications on the production, stage, and test machines the same way we run them on our very own laptop or computer. Moreover, it would be desirable to be able to deliver releases of our services, back or front-end, with ease and confidence by taking advantage of CI/CD pipelines.

Let's deep dive into Aurelia and containerization.

Configuring Your Environment

Thus far you may have learned how to build your application using Webpack and the CLI-Bundler. To build an Aurelia application inside a Docker container, you first need to have Docker installed on your machine. Please see the Docker docs to get Docker installed on your machine before proceeding to the next section.

Basic Sample

To start let's create an Aurelia application. Then inside the root folder create a Dockerfile with the name Dockerfile like the following:

    
  # use latest version of nodejs
  FROM node:lts-alpine
  
  # install aurelia-cli to build the app & http-server to serve static contents
  RUN npm i -g http-server
  RUN npm i -g aurelia-cli
  
  # set working directory to app
  # henceforth all commands will run inside this folder
  WORKDIR /app
  
  # copy package.json related files first and install all required dependencies
  COPY package*.json ./
  RUN npm install
  
  # copy the rest of the files and folders & install dependencies
  COPY . ./
  RUN npm run build
  
  # by default http-server will serve contents on port 8080
  # so we expose this port to host machine
  EXPOSE 8080
  
  CMD [ "http-server" , "dist" ]
  
  

If you are new to Docker, hopefully the comments above each step help explain what is happening. However, you might have a question regarding why we have separated the copy steps into two separate steps. That's due mainly to the cache mechanism of the docker engine. Read this article and the documentation for a better understanding.

Well, it's time to build our first Aurelia application image by running a docker command:

    
  docker build -t aurelia-basic-docker-app:1 .
  
  

After the image is built successfully, it's time to run our application inside a container:

    
  docker run -it --rm -p 8080:8080 aurelia-basic-docker-app:1
  
  

Open a browser and navigate to http://localhost:8080 . Awesome! You now have a running app.

A More Real World Scenario

There are some flaws with the previous approach. It is too simple for production; no one uses http-server for their production environment, hopefully. Also, it is recommended that you separate the build stage and the publish stage in order to reduce both the dependency count and the final image size. If you are interested in Multi-staged builds with docker, checkout the documentation here .

Let's change our Dockerfile a bit. Ready?

    
  # use latest version of nodejs
  FROM node:lts-alpine as build-stage
  
  # install aurelia-cli to build the app & http-server to serve static contents
  RUN npm i -g http-server
  RUN npm i -g aurelia-cli
  
  # set working directory to app
  # henceforth all commands will run inside this folder
  WORKDIR /app
  
  # copy package.json related files first and install all required dependencies
  COPY package*.json ./
  RUN npm install
  
  # copy the rest of files and folders & install dependencies
  COPY . ./
  RUN npm run build
  
  # use nginx as the http server to serve contents
  FROM nginx:alpine as production-stage
  WORKDIR /usr/share/nginx/html
  # copy files from previous container/stage into the new one
  # from /app/dist to working directory
  COPY --from=build-stage /app/dist ./
  EXPOSE 80
  CMD ["nginx", "-g", "daemon off;"]" ]
  
  

You already know how to create your docker image. As a reminder, it's this command:

    
  docker build -t aurelia-prod-docker-app:1 .
  
  

After the image is built successfully, it's time to run our application inside a container:

    
  docker run -it --rm -p 8080:80 aurelia-prod-docker-app:1
  
  

Using separation of concerns, we give each stage/step its own responsibility: the first stage will build our application and has its own dependencies and the second one uses the output provided by the previous one to serve the requests coming to the http server, in this case nginx. In your browser, navigate to http://localhost:8080 to see the result.

Don't forget to read the official documentation of docker for multi-staged builds and the docker file best practices . You'll find a wealth of fruitful articles around the subject matter.

The most intriguing thing to know is that the aurelia-cli will generate a Dockerfile based on your chosen configuration, if you go through the Custom App installation. If you do so, there is a simple command to build an image:

    
  npm run docker:build
  
  

That will build a production-ready docker image for you and you can bring up a container on your local machine by simply running:

    
  npm run docker:start
  
  

Here's the command to stop the container:

    
  npm run docker:stop
  
  

Now, your front-end Aurelia applications, not only can be deployed to production easier and with more confidence, but at a rapid pace and frequency.