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.