Deploying A Web App With Docker And AWS Fargate

Cindy Manel
Cindy ManelJune 08, 2022
#tutorial#devops#integration#popular

At Marmelab, deployment is one of the skills that developers must master quickly, and this was not something I was used to doing. I knew Docker and AWS by name, but I have never used them before. For my integration, I had to learn how to deploy a web application with Docker and AWS Fargate.

When I reached the AWS homepage, a lot of information overwhelmed me. There are many services, many acronyms, and it's not easy to find what we need. After deploying an application with AWS Fargate, I am now more comfortable with it. Let's see what I've learned.

Context: Deploying a Web App

During our second sprint integration at Marmelab with Guillaume , we needed to develop an online game based on the board game Aqualin. It was a Nest.js application. You can check the source of this integration projects at marmelab/aqualin.

aqualin

We also had to deploy this game like a real customer project.

Docker and Containers

The tech requirements were to use Docker and AWS.

Docker is a set of the platform as a service (PaaS) products that use OS-level virtualization to deliver software in packages called containers. I will not explain more about it but the Docker overview and how to get started was helpful.

When running a container, it uses an isolated filesystem provided by a container image. Docker can build images automatically by reading the instructions from a Dockerfile.

This is our Dokerfile example:

FROM node:16-alpine

ADD . /app

WORKDIR /app

RUN yarn install

EXPOSE 3000

WORKDIR /app/aqua-webapp/

RUN yarn build

CMD yarn start:prod

Now that Docker can build our image, let's have a look at how to run containers with AWS.

Docker On AWS

First, I found the AWS documentation about Docker and how their collaboration makes things easier for developers. There are many AWS container services. We finally opted for AWS Fargate.

AWS Fargate homepage

Fargate runs containers without managing servers. In the first approach, this looked simple but will see the various issues we encountered and the solutions we implemented.

Setting Up AWS Fargate

First, we need an AWS account to use AWS Fargate then we can click on Get started with AWS Fargate to access the ECS service.

Elastic Container Service (ECS)

On the right panel, there are three services:

  • Amazon ECS: Amazon Elastic Container Service, to run, stop, and manage containers on a cluster.
  • Amazon ECR: Amazon Elastic Container Registry, to manage container image registry.
  • AWS Marketplace

AWS Elastic Container Service homepage

Before we can run our container, we need our Docker image in Amazon ECR, let's click on Repositories.

Amazon Elastic Container Registry (ECR)

At this step, we create a repository and then push an image on it.

AWS Elastic Container Registry homepage

1. Create a repository

After we click on Create repository, we just need to provide a unique Repository name and click on Save at the bottom of the form.

Create repository

On the ECR homepage, let's click on our created repository.

2. Push our Docker image

We already have our dockerfile in our project, the View push commands button will show us all commands we have to run :

Push commands

Tips:

  • we need the AWS Cli on our project,
  • when we run AWS push commands, we have to make sure that we run them the same way as we run aws configure (if we used sudo, we have to use sudo to run push commands). It's the same for the docker commands at each step.

Our web application image is now available in our repository, we click on the image and copy the Image URI for the next step.

AWS ECR image uri

AWS Fargate

In our project, we choose to use the AWS console interface, but all these steps can be done with the AWS Cli. We go back to the ECS Clusters page and click on Get started to actually use AWS Fargate.

1. Container and Task

  • Container

On the Step 1: Container and Task page, we click on the Configure button on the Custom container definition:

Step one of Fargate container definitions

We paste the previously copied URI on the Image field and provide the Container name and the Container port that we want to expose. We can also add environment variables in the Advanced container configuration section.

Edit container form

  • Task

Now, we edit the task and define the task definition name then click on Next.

2. Service

We edit the service and define the Service name.

The first time we used AWS Fargate, I let the Load balancer type to the default check None. However, every time the application was deployed in our continuous deployment, the IP address of the app changed. So the next iteration, we check Application Load Balancer on the Load balancer type field. This creates a Fargate Service with an Application Load Balancer (more details here.

Step one of Fargate container definitions

3. Clusters

We change the name of the cluster ; next, we review the ECS configuration, and finally, click on Create.

4. Ressources creation

Now we can observe resource creation.

creation summary

We click on the load balancer link to add more configuration. On the Description panel, we can actually open our application with the DNS name link.

Congrats!

Wait a minute, the first time we did this, it didn't work 🫤 . That was because only the port 3001 was listening. To fix this, on the Listeners panel, we add one on port 80 and forward the request to the target group.

load balancer description

AWS Fargate and Github actions

One goal of our integration challenge was to set up continuous delivery pipelines in our code repository on GitHub, using Github Actions.

In our GitHub repository, we click on the Action tab and configure a new workflow using Deploy to Amazon ECS. This will create an aws.yml file with explanations about how to use it.

This configuration will use a task-definition file in our repository. If we want to use the task definition from Fargate instead, we have to download it before the step Fill in the new image ID in the Amazon ECS task definition.

We used this code:

  ECS_TASK_DEFINITION:
    aqualin_webapp_task.json # set this to the path to your Amazon ECS task definition
    # file, e.g. .aws/task-definition.json
  ECS_TASK_DEFINITION_NAME: aqualin_webapp_task

 - name: Download task definition
        run: |
          aws ecs describe-task-definition --task-definition ${{ env.ECS_TASK_DEFINITION_NAME }} --query taskDefinition > ${{ env.ECS_TASK_DEFINITION }}

Each time we push on main in our project, this workflow runs and deploys our application with AWS Fargate.

Conclusion

We finally managed to deploy our web application game with Docker and AWS. AWS is vast, the documentation and the community also. AWS Fargate creates and configures a lot of things by itself. I like that we can run containers without managing servers. Somehow it saves time and effort to use it.

However, there are many things to learn, even writing this article, and there are still points I don't understand clearly. It took some iterations to have our web app properly configured.

AWS Fargate is a great service if we know how to use it. An alternative is to deploy with Amazon EC2 (Amazon Elastic Compute Cloud). This AWS article about these two ECS launch types will probably help you to choose.

Did you like this article? Share it!