Deploy single-spa to AWS Fargate (Docker)

Patrick O'Connor
Geek Culture
Published in
9 min readApr 30, 2021
Architecture Diagram

Overview

Over the past few weeks I’ve been looking to challenge myself, in building something requiring a bit of troubleshooting, but still relevant in today’s world, or even possibly the future for web development. That’s when I came across single-spa. Now at first, you might say, what is that, isn’t that a bit redundant to name something single spa, which expanded is a single page application? We’ll come back to that at the end, to truly understand why the name was given, you first need to use the framework.

Single SPA in my opinion has shifted the way I see web development from a static building block to more of a fluid connection of lego pieces. React changed the landscape of web development in 2013, with the compilation of JSX from javascript files being compiled into traditional HTML/CSS blocks, that made your web app just work. This introduced:

  • A more rapid form of web development
  • Ease in writing clean/concise code
  • Allowing developers to add more complexity to their logic easily.

So as you can probably tell, I think React is pretty cool. However while React has made web development easier, it’s just a milestone. Web dev is continually evolving with new ideas and concepts like single spa, starting to once again change the landscape. The single spa is powerful in its ability to one-up React with the concept of micro frontends. Imagine building three entirely different React projects, with the intention that they would all live on the one web page acting like one, but developed separately. That’s very much the idea behind a single spa.

Single spa works with the idea that we have a headshell, and below it sits our micro frontends. This is a powerful tool, especially when you start to think about centralized operations, like authentication. Now we can have one consistent auth pattern on the shell level shared to its children while giving development teams full development control over their apps isolated from each other.

But enough talk, as I said, to understand we must build, so let’s build.

Workshop

Clone & verify your micro-frontends

The first thing we want to do is pull the codebase we’re going to be working with for this lab. We can do this by cloning the following repo into a safe workspace:

git clone https://github.com/oconpa/single-spa-on-Fargate.git

Inside this project you should find four subfolders titled:

  • history
  • navshell
  • science
  • shell

The project we are going to deploy is a PoC for a university website. This site will have a homepage, a science page, and a history page. The history and science page are managed completely by their own independent team, while the navbar and outer shell are managed at the top level by the university. The idea is that each development team should have their own independent control over their page, but overall they must adhere to the university’s pattern (Shell).

Before deploying our apps to our cluster, we should first verify that they work. Let’s test our navshell first. We can do this by going into the folder, downloading relevant packages, and running a local standalone server.

cd navshell
npm install
npm run start:standalone

If you receive no errors from running the above commands, you should now be able to hit your localhost on port 8080 to see a similar view to the one displayed below.

Awesome, we’re now able to render our base navbar. To verify both the science and history page work, repeat the above step for both those subfolders, checking port 8080 to make sure they render properly.

Once you’ve verified all site's work, we can now move on to deployment of them.

Deploy your micro-frontends

I’ll now show you how to deploy the micro-frontend for the navbar. At the end of this section, you will have to repeat these steps for both the history and science page.

First things first, because we are using docker we need to check as to whether we have it installed, you can check this in your terminal with:

docker --version

If docker is installed, the command should return a version, otherwise, install it from here.

Once installed you’ll need to log on to the AWS console and navigate to the Elastic Container Registry (ECR) service. Once there, select the Repositories option to the left, and Create Repository.

Give your repository a name of your choice, I have chosen navbar > Create repository.

Your repository should now be created and viewable from the ECR repositories page. When you’re ready, select your newly created repository and select view push commands to the top right of the service (see below).

Make sure you have the AWS cli installed and configured to talk to your AWS account.

Run these commands in your local terminal to docker build and upload your image to ECR.

Once the image is in ECR we can now set up our Fargate cluster, but first, we need to set up our load balancer. Our load balancer will be used to expose our cluster to the internet, we will do this for each of our clusters.

Navigate to the EC2 service.

Once there, scroll to the very bottom of the left menu, where you’ll find Load Balancers under Load Balancing.

You’ll then want to select Create Load Balancer > Application Load Balancer.

Give your load balancer a name and select all subnets available under your VPC of choice. The load balancer must be internet-facing and listening on port 80 (HTTP). Next

On the Configure Security Settings page, click Next.

Create a new security group, ensuring it’s open to port 80 (HTTP), then Next.

For Configure Routing select the following:

  • Name Custom name, I put NavBar.
  • Target type: IP

Click Next.

Step 5: Register Targets, Click Next

Then Create.

After the load balancer has been created navigate back to the ECS, to create our cluster.

From there select Create Cluster > Networking only > Next Step.

Give your cluster a name, I gave mine navbar-cluster > Create.

If it fails, try create the cluster again.

Awesome we now have our first cluster created, let’s now create a task definition; this will point to our docker image and tell our cluster what it is we are spinning up.

On the left-hand menu of ECS select Task Definitions > Create new Task Definition.

On the Select launch type compatibility, select FARGATE > Next step.

For Configure task and container definitions you’ll have to give your task definition a unique name, I gave mine navbar-task.

Then for Task size select:

  • Task memory (GB) : 0.5GB
  • Task CPU (vCPU) : 0.25 vCPU

Then Under Container Definitions > Add container.

You should then see a pop-up menu appear from the right. The only fields you need to fill are:

  • Container Name: I gave navbar-container.
  • Image: This will be the URL of the repository you made at the start of this lab in ECR. e.g. should look somewhere along the lines of 143681329876.dkr.ecr.us-east-1.amazonaws.com/navbar.
  • Port mappings: 80.

Once done select Add > Create.

After your task definition has been completed go back to task definitions to view your newly created definition. Select this definition > Actions > Create Service.

Almost there, I promise 😊.

Creating a service is how we spin up tasks within our clusters, it communicates to the cluster what we want to exist within it.

When directed to the Create Service page for Step 1: Configure service put in the following:

  • Launch type: Fargate
  • Cluster: The cluster we made earlier, in my case navbar-cluster
  • Service Name: Give your service a custom name, I gave mine navbar-service
  • Number of Tasks: 1

Then Next Steps

For Configure network select the following:

  • Cluster VPC: Choose the same VPC as your Load Balancer, I choose the default.
  • Subnets: I choose all
  • Load balancer type: Application Load Balancer
  • Load balancer name: Select from the dropdown, the one you created
  • Container name: port: select your navbar container and select Add to load balancer
  • Production listener port: Select 80:HTTP from the dropdown
  • Target group name: Select the target group you created with your load balancer from the dropdown

Next step.

On the Set Auto Scaling, click the Next step.

Create Service.

If you look at the task running in the navbar service, after a few minutes it should go green (RUNNING), meaning it’s successfully deployed. You can test the website by hitting the Load Balancer DNS. If you get back to the following page, it means it’s working.

IMPORTANT: You’ve now successfully deployed your first of three micro-frontends. Now go back and repeat the above steps for both science and history, before continuing.

Load up your shell (Locally)

By now you should have all your micro-frontends spun up in Fargate clusters on the cloud. Let’s now spin up our shell locally and use the university site.

To do this you’ll have to go back to the cloned repo into the shell subfolder.

cd shell

Open the folder in a code editor of your choice as we will need to add the load balancer endpoints to the shell. In the file src > index.ejs you should see the following on lines 52–57:

"@University/root-config": "//localhost:9000/University-root-config.js",
"@University/nav": "http://<ADD NAVBAR LOAD BALANCER HERE>/asset-manifest.js",
"@University/history": "http://<ADD HISTORY LOAD BALANCER HERE>/asset-manifest.js",
"@University/science": "http://<ADD SCIENCE LOAD BALANCER HERE>/asset-manifest.js"
}

To connect your shell, you’ll have to add the three load balancers you created in the section above into this file replacing where it says to add that specific load balancer.

Once you’ve added the load balancer endpoints you’ll have to first download the relevant dependencies and then run the app locally.

npm install
npm start

This will spin up a local server on port 9000 which should render all the pages from the clusters you’ve deployed.

Note: If when trying to load up the app you face CORS issues, or the site isn’t loading, try add this extension to your browser (here) and then toggle it on, before reloading your page.

Conclusion

At the start of this article, I touched on the name of single-spa (single-page application). So now that you’ve used it you’re probably starting to understand the naming convention behind it.

React in itself is a single-page application, as from a user's perspective the entire website is loaded to the browser after the first load of the site. The idea of micro-frontend adds another layer of single to the React SPA, hence creating a single spa overall experience.

I hope you enjoyed the workshop and are now starting to think about where this framework can be used in your own personal projects. Stay tuned to more posts as I will continue to explore the limits of this framework and what features I can build on top of it.

--

--

Patrick O'Connor
Geek Culture

WorldWide Prototyping Engineer at Amazon Web Services (AWS). My opinions are my own.