Streamlining Containerized Web Application Deployment: An All-Inclusive Guide Using AWS ECS, ECR, and CodePipeline
Published: 2024-02-29 17:29:45

In today’s world of technology web applications have become a major part of digital experience. They provide a complete and dynamic solution for various needs, ranging from communication and collaboration to e-commerce and entertainment. To ensure portability, efficiency, scalability, and the ability to provide consistent operation across diverse environments, containerization is required. In this blog, I will guide about streamlining containerized web application deployment using AWS services such as ECS, and ECR along with CodePipeline to accommodate continuous change requirements.
First of all, let us understand the use case of services that will be used for this project.

**CodeCommit**- It is a version control service, which will be used to store code, documents etc.

**CodeBuild**- It is used to compile source code, runs unit test and produce artifact.

**CodePipeline**- Used to quickly model and configure the different stages of software release process and automate the software change continuously.

**IAM roles**- Used to delegate access to AWS resources.
ECR (Elastic Container Registry)- Used to securely store, manage docker containers images.

**ECS (Elastic Container Service)**- Used to easily deploy, manage and scale docker container.

**AWS Fargate**- Used with ECS to run containers without having to manage servers.

Let us jump directly to the set of steps 
**Steps:**
**Step1:**
In the very first, we will configure IAM roles with the permission policy required in this project for AWS services. To create IAM roles, IAM is used. Permission policies required for this project are: 

AmazonEC2ContainerRegistryPowerUser
AWSCodeCommitReadOnly
CloudWatchLogsFullAccess
Attach those policies to the role.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7h1pcq5zxy2zqcngobvz.png)
**Step 2:** We need to push our code to a repository for which code commit will be used. Search for CodeCommit in the AWS console and click in “Create Repository”. Repository name must be provided for CodeCommit. Descriptions, tag and CodeGuru reviewer are optional.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7w80srd9r759d9v2b2hc.png)

After creating git repository, it provides different way of connection such as HTTPS, SSH, HTTPS(GRC). We will be using HTTPS option to clone the repository so that we can push code to CodeCommit.
To clone the repository, use the code: git clone <url>
In the local system where the web app code is available clone the repository and push the code.
Code to create branch main- git checkout -b main
  Add files: 	           - git add .
  Commit                    - git commit -m <message>
  Push		            - git push origin main 
Content of Docker file used in this project.

```
FROM nginx
WORKDIR /app
COPY . /usr/share/nginx/html
EXPOSE 80
buildspec.yml file is also required which will be configured later.
```

**Step3:** 
Now, we will set up ECR. Visibility setting can be choosen between private and public. In this project we will be using private repository.  A concise name which can be identified by developer should be provided in repository name. 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dyclb96nnb0cer9tv1le.png)
After creating a container repository, it can be shown listed in private along with its URI. 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8bnl27aamxbl98dpfuxi.png)
Click on Repository name to view the push commands.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zj0wmkut1swf8zcdb34s.png)
**Step 4:**
Now, we will set up CodeBuild with source as CodeCommit. CodeBuild will extract code from the CodeCommit repository that we created earlier. Reference type can be selected as branch with relevant name, in our case “main”.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/42cpjth34iqju0yu99y0.png)
We will be using default environment configuration. CodeBuild also requires compute medium, for which we will use EC2. We don’t need to configure EC2. To execute operation of CodeBuild permission is required which is provided by IAM role created earlier. 
buildspec.yml file will be used to build commands which will be provided through CodeCommit. 
The configuration of buidlspec.yml file is given as below.

```
version: 0.2
phases:
  install:
    runtime-versions:
      nodejs: latest
    commands:
      - nohup /usr/local/bin/dockerd --host=unix:///var/run/docker.sock --host=tcp://127.0.0.1:2375 --storage-driver=overlay2 &
      - timeout 15 sh -c "until docker info; do echo .; sleep 1; done"
  pre_build:
    commands:
      - echo log in to Amazon ECR...
      - <provide way to Retrieve an authentication token and authenticate your Docker client to your registry using push commands>
      - REPOSITORY_URI=<replace with the uri of ECR>
      - COMMIT_HASH=$(echo $CODEBUILD_RESOLVED_SOURCE_VERSION | cut -c 1-7
      - IMAGE_TAG=${COMMIT_HASH:=latest}
  build:
    commands:
      - echo Build started on `date`
      - echo Building the Docker image.
      - docker build -t $REPOSITORY_URI:latest .
      - docker tag $REPOSITORY_URI:latest $REPOSITORY_URI:$IMAGE_TAG
  post_build:
    commands:
      - echo Build completed on `date`
      - docker push $REPOSITORY_URI:latest
      - docker push $REPOSITORY_URI:$IMAGE_TAG
      - echo write definitions file...
      -printf'[{"name":"blog-code-pipeline","imageUri":"%s"}]' $REPOSITORY_URI:$IMAGE_TAG > imagedefinitions.json
artifacts:
  files: imagedefinitions.json
```

This buildspec file defines the steps for building and pushing docker image to ECR. Major phases for this file are.
Phases:
Install: For our source code to run we need to install Node.js latest version and also start Docker daemon.
Pre_build: Authenticate Amazon ECR and setting variable for Docker image repository along with determining the image tag.
Build: Commands to build Docker image by specifying ECR repository URI and tag.
Post_build: Push Docker image to ECR and create definition file. Pushing definition file to artifact store.
Commands: 
Commands for starting Docker daemon, authenticating ECR, building Docker image and pushing that image to ECR, creating the definitions file are used in the buildspec.yml file above.
This buildspec file is used to automate the process of building a Docker image from source code in CodeCommit and tagging it with version, and pushing the Docker image to ECR. The resulting image information will be stored in artifact(imagedefinitions.json) file, for further deployment in ECS. 
Note the name “blog-code-pipeline” which we have used.
After writing the buildspec.yml push it to the CodeCommit repository using the same process that we did earlier.
To check whether our setup works well we will run CodeBuild and see the phase details as.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vokpwjne73l05ewhtp71.png)
**Step 5-** In this step we will configure ECS to run the docker container from registry.
First of all, cluster should be made. This will be used to organize container instances regionally so that task requests may be executed on them. Cluster name must be provided along with infrastructure configuration. AWS Fargate serverless will be used in this project. Click on the “create” button in the bottom. The cluster will be made through CloudFormation. It may take few minutes to set up. Progress can be tracked in CloudFormation

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wptujbkz0fuh99tf93ve.png)
Configure task definition- Application's blueprint is found in the task definition. The parameters and one or more containers that make up application are described using it. After creating the cluster, click on the “Task definitions” available in the left navbar.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nef8eau0fj6j1t35ssoc.png)
We can also create task definition using JSON, but for simplicity propose click on “Create new task definition”. Provide the task definition family name and infrastructure to run the task. We will be using default environment setup with Fargate.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zptlctp86a45mmbwe2cx.png)
We will use the default OS architecture and keep the task size to 1vCPU and 3GB memory.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9sdmc67lqfxl4e36u8el.png)
In the container section give the container name and image URI of repository. Container name is configured as per buildsepc.yml “blog-code-pipeline”. For port mapping we will use port 80, as per our Docker file. We can customize the other option, but for this sample project leave other section as default and click on “create” button at last

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hcj3deg2a684yegw9mjq.png)
Now, click on the cluster that we created earlier and go to the services section. In order to execute and manage a given number of instances of a task description concurrently in an Amazon ECS cluster, we must build services.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k2yrfd5copq9u9dsuq74.png)
The cluster name will be selected by default. We will use Fargate as capacity provider keeping the platform version latest.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fmkobaodz3glx7nw46na.png)
In the deployment configuration section service and provide family name along with service name. We will leave other setting as default.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/emeee1fax5cgg171zdv2.png)
**Step 6:**
Set up CodePipeline
At last CodePipeline must be configured so that when code is pushed to CodeCommit it trigger CodeBuild and then ECS for deploying changes without requiring manual intervention.
Name should be provided for the pipeline to be identified.
We can create new service role in Code Commit.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/et6srmw4ovcwgo76o8ig.png)
The source will be CodeCommit which contains code that we push from our local system. It must be configured according of CodeCommit repository, as our previous configuration.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a1ogmyki8t99l9plfmz8.png)
In the build phase, build provider must be selected and relevant name must be provided

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0u3y3glon7gdkiw59l8o.png)
In the last deploy provider must be provided which will be used for deploying the containerized web app. ECS will be used as build provider which we configure earlier. Provide.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/usir0dwuo9awg346v0bq.png)
the cluster name ,service name and image definitions file accordingly.
After clicking on “Release change” of CodePipeline it will first get the code form CodeCommit and run CodeBuild and deploy using ECS. It may take some time to complete the whole process.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8x2b5t85xd8ttxml5yb2.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bug6wat9t0b9jjscdwxv.png)
 Now, to see the output go to ECS. In the task section of the cluster that we created. We can see public IP address for the hosted web app.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e7trt0c4kru0l9v0f13a.png)
Copy and paste that IP address in the browser where we can see our website is hosted.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dmt1thgd712jb6efcvkh.png)
Now, if we make any change to our source code of web app and push it to CodeCommit, it will automatically run CodePipeline and the change will be deployed in ECS automatically.
In this way we have successfully deployed our containerized web app using ECS, ECR and CodePipeline.