In this article we will discover the DevOps movement step by step, we will talk about the fundamental concepts then we will make a basic pipeline with GitHub actions to deploy an Angular 6 app, so let’s go.
What is DevOps?
DevOps is used to remove the conflict between the developers' team and the operations team to work together. This conflict is removed by adding a set of best practices, rules, and tools. The DevOps workflow is defined with a set of steps :
Plan
This is the first step, where the team defines the product goals and phases, also defining deadlines and assigning tasks to every team member, this step is the root of the whole workflow. the team uses many methodologies like scrum and agile.
Code:
After planning, there is the code when the team converts the ideas to code. every task must be coded and merged to the main app, here we use an SCM to organize the collaboration to make a clean code and have a full code history to make a rollback in case of failure.
Build:
After coding, we push the code to Github or Gitlab ( SCM ) and we make the build, usually, we use docker images for packaging. also, we can build the code to be a Linux package like deb, rpm … or even zip files, also there is a set of tests like unit tests and integration tests. this phase is critical!
Test:
The build was succeeded, no it’s time to deploy the build artifacts to the staging server when we apply a set of manual and automated tests ( UAT ).
Release:
it’s the final step for the code work, so we make a release and announce a stable version of our code that is fully functional! also, we can tag it with a version number.
Deploy:
A pre-prod or a production server is the target now, to make our app up and running
Operate:
It’s all about infrastructure preparation and environment set up with some tools like terraform for IaaC, Ansible for configuration management, and security stuff configurations …
Monitor:
The performance is very important, so we install and configure some monitoring tools like ELK, Nagios, and datadog to get all information about the applications like CPU and memory usage …
Deploying an angular app
In this example, we will deploy a simple angular app on two environments.
- On VPS ( OVH provider) as a development server.
- on Heroku as a staging server.
So you must have a VPS and a Heroku account to continue with me.
The application repository is here : Github repo.
- Clone the project with
git clone https://github.com/hatembentayeb/angular-devops
- run
npm install && ng serve
to run the app locally
Preparing the deployment for Heroku
Nginx is a popular and powerful web server that can be used to serve a large variety of apps based on python, angular, and react …
I will go through an optimization process to produce a clean and lightweight docker container with the best practices as much as I can.
Writing the Dockerfile
First, we will prepare the Dockerfile to be deployed to the Heroku cloud, so there are some tricks to make it work smoothly, make sure that you have an account and simply click new to create an app :
create a Heroku app
Make sure to give a valid name for your app, then go to your account settings and get your API_KEY
that we will use in the pipeline file:
getting API key
let’s take a look at the dockerfile
of the app:
This Dockerfile is split into two stages :
- Builder stage: The name of the stage is builder, it is a temporary docker container that produces an artifact which is the
dist/
folder created byng build --prod
that compiles our project to produce a singleHTML
page and some*js & *.css
. The base images that are used here aretrion/ng-cli
that contains all requirements to run an angular up and it’s accessible for public use in theDocker-hub
, the public docker registry. Make sure to install all app requirement packages withnpm ci
, theci
command is used often in the continuous integration environments because it is faster thannpm install.
- Final stage: The base image for this stage is
nginx:1.17.5
and simply we copy thedist/
folder from thebuilder
stage to the/var/share/nginx/html
folder in the nginx container with the commandCOPY --from=builder ...
There are additional configurations required to run the app, we need to configure nginx, there is a file nameddefault.conf.template
that contains a basic nginx configuration so we copy it to the container under/etc/nginx/conf.d/default.conf.template
, this file has the $PORT variable that has to be changed when building the docker image in the Heroku environment. Thedefault.conf.template
:
server {
listen $PORT default_server;
location / {
include /etc/nginx/mime.types; root /usr/share/nginx/html/;
index index.html index.htm;
} }</span>
Also, make sure to copy the nginx.conf
under the /etc/nginx/nginx.conf
, you are free to change and modify 😃, but for now I will use the default settings.
The last command is a little bit confusing so let’s break it down :
CMD /bin/bash -c “envsubst ‘\$PORT’ < /etc/nginx/conf.d/default.conf.template > /etc/nginx/conf.d/default.conf” && nginx -g ‘daemon off;’</span>
→ /bin/bash -c ‘ command’: This command will run a Linux command with the bash shell.
→ envsubst: It is a program that substitutes the values of environment variables, so it will replace the $PORT from the Heroku environment and replace it in the default.conf.template
file with its value, this variable is given by Heroku and attached to your app name, then we rename the template with default.conf
which is recognized by nginx.
→ nginx -g ‘daemon off;’: The daemon off;
directive tells Nginx to stay in the foreground. For containers, this is useful as the best practice is for one container = one process. One server (container) has only one service.
Preparing the deployment for the VPS on OVH
We will use the VPS as a development server so no need for a docker now we will use ssh for this after all make sure to have a VPS, ssh credentials, and a public IP.
I assume you have nginx
installed, if not try to do it, it is simple 😙
In this tutorial I will be using the sshpass command, it is powerful and suitable for CI environments.
You can install it with: apt-get install sshpass -y .
lets deploy the app to our server from the local machine, navigate to the repo and run ng build --prod
, then navigate to dist/my-first-app
folder and type this command :
sshpass scp -v -p <password> -o stricthostkeychecking=no -r *.* root@<vps-ip>:/usr/share/nginx/html</span>
If you don’t want to hardcode the password in the command line try to set the SSHPASS
variable with your password like this export SSHPASS=" password"
and replace -p
with -e
to use the environment variable.
Now all things are almost done! great 😃 ! let’s prepare the pipeline in the GitHub actions which is a fast and powerful ci system provided by GitHub inc.
Under the project root folder create the file main.yml
in the github/wokflows
folder, this directory is hidden so must start with a point like this: .github/workflows/main.yml
Preparing the pipeline
let’s take a look at the pipeline steps and configurations :
.github/workflows/main.yml
- Block 1: In this block, we define the workflow name and the actions that must be performed to start the build, test, and deployment. and of course, you have to specify the branch of your repo (by default
master
). - Block 2: The
jobs
keyword has to sub-keywordsbuild
andsteps
, the build define the base os for the continuous integration environment, in this case, we will useubuntu-latest
, also we define thenode-version
as a matrix that allows us to use multiple node versions in the list, in this case, we need only12.x
. The steps allow us to define the workflow steps and configurations ( build, test, deploy...). - Block 3 :
actions/checkout@v1
is used to clone the app code in the ci env. this action is provided by GitHub. Let's define acache
action with the namecache node modules
, the name is up to you 😃, then we use a predefined action calledactions/cache@v1
and specify the folders that we want to cache. - Block 4: Installing and configuring the node run-time with an action called
actions/node-setup@v1
and pass to it the desired node version that we already defined. - Block 5: The show will begin now! let’s configure the build and the deployment to the VPS. Create two environment variables
SSHPASS
for the sshpass command and define theserver
address, make sure to define these values on the GitHub secrets under setting on the top of your repo files. Under therun
keyword put your deployment logic. so we need the sshpass command and the angular cli to be installed, then install all required packages and build the app with the production mode--prod
, next, navigate to thedist/my-first-app
folder and run the sshpass command with a set of arguments to remove the older app in the server and deploy the new code. - Block 6: Now Heroku is our target, so define also two env. variables, the Heroku registry URL and the API KEY to gain access to the registry using docker, next we need to define a special variable
HEROKU_API_KEY
that is used by Heroku cli, next, we login to the Heroku container and build the docker image then we pushed to the registry. we need to specify the target app in my case I named itangulardevops
. After deploying the docker image we need to release it and tell the Heroku dynos to run our app on a Heroku server, using 1 serverweb=1
, note thatweb
is the name of the docker image that we already pushed.
We are almost done! now try to make a change in the app code and push it to GitHub, the workflow will start automatically 🎉 🎉 😄 !
You can view the app here: https://angulardevops.herokuapp.com/
Finally, this tutorial is aimed to help developers and DevOps engineers to deploy an Angular app, I hope it is helpful 😍. for any feedback please contact me!
If this post was helpful click the clap button as much as possible 😃.