Need for an automated Deployment system
Deployment is perhaps the most important aspect of developing a product. There are numerous ways to deploy a website. It can be done manually or automated. I used to deploy our website manually, and it used to consume a lot of time. It had to be done very carefully as one mistake could cost the company thousands of dollars. Now, imagine having multiple environments, Autoscaling Groups, and Load Balancers. It complicated my manual deployment tenfold. That is when I chose AWS CodePipeline to automate my deployment process. This saved time and allowed me to deploy the product smoothly with zero downtime. It improved my productivity significantly, and I was able to explore more areas that were beneficial to me.
Why AWS pipeline why not Jenkins ??
The reason for choosing AWS Pipeline is that it is simpler, and all the other aspects needed for the automated deployment of my product were maintained within AWS. Moreover, the cost of using AWS Pipeline is much less compared to the hassle of configuring an open-source pipeline such as Jenkins.
Pre-requirements for AWS pipeline.
Create an instance with the CodeDeploy agent installed and a web server such as NGINX or Apache.
Configure the NGINX file located in /etc/nginx/sites-available/default to change the default server path from /var/www/html/index.html to /var/www/html/dist, as ‘dist’ will be the built folder that holds the build files.
Commands to install the code-deploy agent.
sudo apt-get update
sudo apt-get install ruby-full ruby-webrick wget -y
cd /tmp
wget https://aws-codedeploy-us-east-1.s3.us-east-1.amazonaws.com/releases/codedeploy-agent_1.3.2-1902_all.deb
mkdir codedeploy-agent_1.3.2-1902_ubuntu22
dpkg-deb -R codedeploy-agent_1.3.2-1902_all.deb codedeploy-agent_1.3.2-1902_ubuntu22
sed 's/Depends:.*/Depends:ruby3.0/' -i ./codedeploy-agent_1.3.2-1902_ubuntu22/DEBIAN/control
dpkg-deb -b codedeploy-agent_1.3.2-1902_ubuntu22/
sudo dpkg -i codedeploy-agent_1.3.2-1902_ubuntu22.deb
systemctl list-units --type=service | grep codedeploy
IAM role attached to the instance that has access to AWS code deploy,s3 & Code-pipeline.
Buildspec.yml file and appspec.yml file.
There are 3 Steps in a deployment process. Source,Build, Deploy
SOURCE
The first stage of the deployment process is Source. Creating a connection between your source code and CodePipeline is crucial. For this exercise, we have a simple JavaScript code to replicate a working environment. You can fork the source code from my GitHub repository, which is linked on the main page of this blog. or Click Here.
Navigate to CodePipeline in the AWS console AWS console. and click “Create Pipeline”.
Create a new role for the pipeline.
Select “GitHub (Version 2)” as the source provider and click “Connect to GitHub”.
Create a connection between your Git repository and CodePipeline, and authorize your GitHub account.
- Select the repository where your code is located and the branch, then click “Next”.
BUILD
The second stage is Build. We need to build our code. In my project, I used the build stage to build the Docker image of the source code. For this example, our source code is a simple JavaScript code, and we are going to install its dependencies and build a folder in this stage. To accomplish this, we need a Buildspec.yml file. This YAML file is the blueprint for the CodeBuild process to build our application.
- Click “Create Project” and give a name for the project.
2. Create a new role for the build process.
3. Select the operating system on which you want your build to run. I have selected Amazon Linux as my build OS because my instance is also Amazon Linux.
- Specify the runtime as “Standard” and select an image on which CodeBuild will run (example: architecture as ARM64, amd64, X86_64). I have chosen standard 4.0, as this format supports our source code, which is built on Vite JS. I also chose the latest image version, as shown in the above image.
5. Click “Create Project” (Note: We are giving our Buildspec.yml file in our code).
This is the Buildspec file
version: 0.2
phases:
pre_build:
commands:
#installs dependencies for the code
- npm install
build:
commands:
# builds a code in a folder called dist
- npm run build
post_build:
commands:
artifacts:
files:
- '**/*'
This is the structure for a Buildspec file. In the pre-build phase, it installs dependencies. In my project, I will use a Docker build command to build a Docker image. In the build phase, this command builds the code into a dist file. In my project, I used the Docker tag command to tag my Docker image. I haven’t used any post-build commands here. In my project, I used the Docker push command to push the Docker image into my ECR repo.
DEPLOY
The third stage is deployment. In this stage, we will deploy our built code into our server. There are numerous ways we can deploy, like ECS (serverless), Elastic Beanstalk (Blue-Green deployment), and CodeDeploy (EC2 server). ECS is the best way to deploy Dockerized containers.
In this example, we are using CodeDeploy, which will deploy our built code in an EC2 server. As mentioned in the prerequisites, we want to install the CodeDeploy agent on the server. We also have to use the appspec.yml, which is like navigation for CodeDeploy as to where and how to deploy the built code.
1First of all, we have to create an application for CodeDeploy. Navigate to Code Deploy. Enter an Application name and a Compute platform as EC2/on-premises, and then create the application.
Then, create a deployment group. Enter a name and create a service role for CodeDeploy. Select the deployment type as In-Place, and Environment Configuration as Amazon EC2 Instance. Select the instance by its tag name.
Also, we need to create a role for CodeDeploy.
- Now, leave everything to default except tick off “Enable Load Balancer” as we have no load balancer.
This is the Appspec file
version: 0.0
os: linux
files:
- source: /
destination: /var/www/html/
permissions:
- object: /
pattern: "**"
owner: ubuntu
group: ubuntu
hooks:
BeforeInstall:
- location: scripts/before_install.sh
timeout: 1000
runas: root
# During the AfterInstall deployment lifecycle event, run the commands
# in the script specified in "location".
AfterInstall:
- location: scripts/after_install.sh
timeout: 1600
runas: root
# During the ApplicationStart deployment lifecycle event, run the commands
# in the script specified in "location".
ApplicationStart:
- location: scripts/app_start.sh
timeout: 301
runas: root
Understanding the Appspec.yml file is vital for the deployment process as it is the blueprint for CodeDeploy to deploy the built code.
In the above file, I have mentioned the OS of the deployment instance as LINUX. The location to deploy is /var/www/html/dist/, as this is the server path of nginx. In the permission section, I have mentioned the owner and group as ec2-user; if you use Ubuntu, then use UBUNTU.
The hooks section is important as it dictates the commands to be executed during deployment. I have set up bash scripts in a folder called “Scripts” in the source code. Since this is a simple deployment, we have to replace the index.html file in /var/www/html/dist/ with our build folder “Dist” and have to restart nginx in the bash script. You can customize this bash script based on the code’s requirements. In my project, I have to deploy a Docker image as well as a React build folder, so I have added commands to start Docker in the scripts file. You can take a look at the source code in my GitHub repo under the folder “scripts”.
That’s it! You have created a pipeline. Run the pipeline and enjoy your application without the hassle of manual deployment. The source code for my demo is in my GitHub repo. Kindly leave comments on this blog, on my Twitter, or on Facebook. Here is the deployed application.
Next up I am going to do a blog on how to set up CICD for the Docker application.