DEV Community

Cover image for Deploy Your React App to ECS (Fargate)
Mubbashir Mustafa
Mubbashir Mustafa

Posted on • Edited on

Deploy Your React App to ECS (Fargate)

It's assumed that you have already containerized your React app. If you haven't then read this first

Usually, you should deploy your React app using AWS S3 (with Cloudfront) or AWS Amplify. But if your use case is advanced and you want to deploy containerized React app then you could use AWS ECS.

Amazon Elastic Container Service (Amazon ECS) is a service provided by AWS to orchestrate containers and deploy your containerized applications.


Step1: Upload your image to ECR

Amazon Elastic Container Registry (ECR) is a service where you store your container images (like DockerHub). Consider it as npmjs of containers instead of JS packages.

Sign in to your AWS console and head over to AWS ECR.
Alt Text

Click on "Create Repository" and add a new repository. Add whatever name you would like, for the sake of demo I am using "my-app".
Alt Text

Once the repository is created, it will take you back to the repositories list. Select the newly created repository and then click on the "View push commands" button.
Alt Text

Now we need to use these commands one by one to build, tag and push our container image. But before proceeding make sure you have the latest version of AWS CLI installed.

Use the following command to check that AWS CLI is correctly installed on your system.

aws --version

It would output something like this. Your version could be different, it depends when you are reading this article.
Alt Text

Next, we need to create 'Access Keys'. For that, go to "My Security Credentials" from the dropdown with your username.
Alt Text

Click on "Create New Access Key", it will create a new key for you.
Alt Text

Copy "Access Key ID" and "Secret Access Key". We will need it later on.
Alt Text

Now go back to your terminal and enter the following command
aws configure

It will ask for "Access Key ID" and "Secret Access Key", provide them one by one (copied in the previous step). You can skip the next two questions (default region and default output format).
Alt Text

Once aws cli has been configured, now we can run the push commands. Open up the terminal and make sure you are inside your React app's directory. Run each command shown in the popup opened up by clicking the "View push commands" button. Please note that the commands in the screenshot could be different than what you see in your popup and it's totally fine.
Alt Text

*If your 'Dockerfile' is named something other than 'Dockerfile', you will have to specify it using -f flag (see below).
Alt Text


Step 2: Deploy on ECS

Once our container image has been pushed, we are now ready to use ECS and all the awesomeness it has to offer.

Head over to Amazon Elastic Container Service (Amazon ECS) and create a cluster.
Alt Text

Select "Network Only" and click "Next Step".
Alt Text

Give whatever name you would like (but remember it), select "create vpc", click "create".

*Note: You can also choose an existing VPC.

Alt Text

Once the Cluster has been created, select 'View Cluster'.
Alt Text

Select "Task Definitions" from the left sidebar.
Alt Text

Click "Create new Task Definition"
Alt Text

Select "Fargate", click "Next Step"
Alt Text

Enter Task Definition Name, select "ecsTaskExecutionRule" in the "Task Role" and "Task Execution Role" fields. Select "0.5GB RAM" and "0.25 vCPU". Click "Add container".
Alt Text

Now we need to add a container of the image we pushed to ECR earlier. Give a name to container and copy-paste the image URI (can be copied from ECR repositories list). Enter "80" in the port mapping field. Click "Add".
Alt Text

Once the container is added, click "Create" to finish Task creation.
Alt Text

Once the Task is created, you can click on "View task definition"
Alt Text

Now we need to create a service to run the task within our container. But before that, we need to create an Elastic Load Balancer.

ELB

We need to create an Elastic Load Balancer (ELB) so that we can access the react app form the browser (and later on attach to a domain). To do that, head over to EC2.
Alt Text

Select "Load Balancer" from the bottom left.
Alt Text

Click on "Create Load Balancer"
Alt Text

Select "HTTP/HTTPS" and click "Create"
Alt Text

Give a name to your Load balancer. Select VPC from the dropdown (it should be the one that was created by your ECS cluster earlier). You also have to select both of the subnets within the VPC. Click "Next: Configure Security Settings" and ignore the warning (we will add HTTPS later on) and click "Next: Configure Security Groups".
Alt Text

Click on "Create a new security group" and hit "Next: Configure Routing".
Alt Text

Give a name to your target group (a target group is a group of resources where ELB should send requests to). Select "IP" and click "Next: Register Targets".
Alt Text

In "Register Targets" leave everything as it is, click "Next: Review". Review the changes and click "Create". Your ELB is created now. Copy the "DNS Name", as this is going to be the URL to access your container from the browser.
Alt Text

Once the ELB has been created, we can now create "Service" to run the "task" created within our "cluster".

Back to ECS

Go inside the cluster we have created. In the "Services" tab, click "Create".
Alt Text

Select "Fargate" as the launch type. Select the task definition we created above (my-app-task in my case), select revision as 1 (latest). Select "LATEST" in platform version, choose the cluster we created in "Cluster". Give a name to your service. Enter "1" in the "Number of tasks" field. Click "Next step".
Alt Text

In "Cluster VPC", select the VPC that was created by our cluster. Select both of the subnets within the VPC. In the Load balancer type, select "Application Load Balancer". Select the ELB we created earlier in the "Load balancer name" field. Select the container we created in "Container to load balance" section and click "Add to load balance"
Alt Text

Once you click on "Add to load balance", the section will be expanded.
From "target group name", select the "target group" we created while creating the ELB earlier and it will fill the rest of the fields for this section.

Alt Text

Once the "Container to load balance" section's configuration is completed. Click "Next step".
Alt Text

In "Auto scaling" section leave everything as it is and click "Next step". Review the settings and click "Create service". Once the service is created, you will be taken back to the services list page. Once the service we just created has an "Active" status, you can go to the browser and use the DNS Name of ELB to access the container.
Alt Text

To get DNS Name of ELB, select the load balancer we created earlier and the DNS Name would be shown in the description below.
Alt Text

Use the address in the browser to access your react app.
Alt Text



Next: Attach domain to ELB


Let's connect:

Linkedin: https://www.linkedin.com/in/mubbashir10/

Twitter: https://twitter.com/mubbashir100

Top comments (13)

Collapse
 
kokkoon profile image
KK

Great post, thanks for sharing....

I dockerized my react app, and can ONLY run the dockerized image with interactive mode (-it) specified in the docker run. Unfortunately, I don't see a way to do the same to add the "-it" to the docker image in the ECS Fargate's task definition.

Is there a way to aviod to have to run in the interactive mode? or a way to specify an interactive mode in the Fargat task definition?

Appreciate if you can advise...

Collapse
 
mubbashir10 profile image
Mubbashir Mustafa

Hi, thanks for stopping by. Let's take a step back, could u please mention why you need to run your production app in the interactive mode? (it will help me propose a possible solution) - thanks.

Collapse
 
kokkoon profile image
KK

Thanks for pointing out "why must I run the container in interactive mode?"... instead of looking at how to run container with -it in AWS, I seems managed to get around the interactive mode requirement by adding ENV CI=true to the dockerfile... i am not sure if that fixed the -it requirement, but i can run it without interactive mode now.

Collapse
 
kokkoon profile image
KK

Hi Mubbashir,

If I run without the interactive mode with below cli

docker run --rm --name=my-react-app --network=mynetwork -p 3000:3000 my-react-app-image

I am getting the server stopped at "Starting the development server..." as shown below:

client@0.1.0 start /usr/src/app
react-scripts start

[HPM] Proxy created: /auth/google -> my-node-server:5000
[HPM] Proxy created: /api/* -> my-node-server:5000
ℹ 「wds」: Project is running at 172.18.0.2/
ℹ 「wds」: webpack output is served from
ℹ 「wds」: Content not from webpack is served from /usr/src/app/public
ℹ 「wds」: 404s will fallback to /
Starting the development server...

my dockerfile is simple:

pull official base image

FROM node:12-slim

set working directory

WORKDIR /usr/src/app

install app dependencies

COPY package*.json ./
RUN npm install
RUN npm install react-scripts@3.4.1 -g

add app

COPY . ./

start app

CMD ["npm", "start"]

But if I run it in my node js console using "npm start" i can start my dev without issue...

Thanks,

Thread Thread
 
mubbashir10 profile image
Mubbashir Mustafa

Ah, so you are trying to use it for development purposes. When we deploy on ECS, we do it for production. For production, you need to use a multistage docker (first build the react app, second copy the built files and serve using Nginx - no nodejs server involved).

For development, you don't need to use ECS. That's something that you will be doing on your local machine, and it's totally fine to use -it for it. You may also want to attach volume to your code directory if you are developing via docker :)

Collapse
 
rynebenson profile image
Ryne Benson • Edited

Can't seem to get this process working anymore. Basically, once I get to the end and I open up the load balancer url in the browser it shows a 503 Error. I believe AWS has changed the "Create a security group" process and you now have to set up the inbound rules. I'm thinking my error could be somewhere at that part of the process. Have you setup a pipeline recently and encountered a similar issue?

Collapse
 
xai1983kbu profile image
xai1983kbu • Edited

Hi! Thank you for your article!
Images after text - "Next: Configure Security Groups" and text - "Next: Configure Routing" are the same. It's not clear what settings you used in step - 3. Configure Security Groups.

Collapse
 
mubbashir10 profile image
Mubbashir Mustafa

Oh, you are right. I will update the images. The image for "Security Group Configuration" is missing.

Collapse
 
saudansari profile image
Saud

Whats the benefit of hosting a react app on fargate as compared to S3? React files are built into static files which don't require a run-time. So, why would you put it on fargate?

Collapse
 
mubbashir10 profile image
Mubbashir Mustafa • Edited

Both are two different models of deployments. Instead of S3 vs ECS, you probably want to know about the benefits of containerized applications. Once you have the idea of why should we containerize our application then ECS comes into play. And then your question would be something like why should we use ECS instead of beanstalk (or other container services)?

So at this point, you need to understand the benefits of containerization in general.

Collapse
 
syqrefind profile image
Daniel Shen • Edited

Could you elaborate your answer a bit more? It would really be helpful if you could point out some of the reasons why we want to containerize a React app, or any other SPA. Thanks in adavance.

Collapse
 
hlachqar profile image
Hamza LACHQAR

Hi, thank you first for your time you spent helping us with this article, it's really helpfull.
I did the first step fine, BUT after finishing the second step, the react app not accessible from the browser using DNS Name as explained in last thing in the step 2.
thanks in advance to anyone can help.

Collapse
 
alanoberto profile image
Alan Oberto

Hi Mubbashir Mustafa, very good post. Why would not split front end of Backend using s3 for static files and ecs for react backend? In that way you can have separate development cycles.