How to deploy a Dockerized Node JS (TypeScript) Application to Amazon EC2 Service — 2023
Tags: typescript, docker, aws, nodej
Published: 2023-01-23 21:09:47

**1. Introduction**
There are several options available once you’ve created a web application to publish it online and make it accessible to others. Elastic Compute Cloud, a well-known service, is one of the platform’s offerings from Amazon Web Services (AWS) (EC2).

It’s important to have a basic grasp of EC2 and how to deploy to it because it forms the foundation for many of AWS’ other services.

In this article, we’ll learn how to setup an EC2 instance, configure it, and deploy a straightforward Node.js application to it. Your Node project will be operating on AWS by the conclusion of this tutorial, and you’ll have a better grasp of how to connect with a fundamental system of AWS.

**2. Prerequisites**
In order to follow through this tutorial, you’ll need the following:

- **An AWS Account**
You can checkout this tutorial on how to create an AWS account.

- **Node and Npm**
You need to have Node and Npm installed on your computer. You can install them [here](https://nodejs.org/en/).

- **Docker**
Docker is a very lightweight virtual machine that comes with all the applications and dependencies needed to run your program. Docker allows us to group our programs into manageable parts that may be run everywhere Docker is deployed. This eliminates the excuse “but it works on my computer!”

Since i won’t be going into great detail, this tutorial will presume a basic understanding of Docker. If you want to learn more about docker, i’ll create an article very soon where i’ll teach you how to use docker for production ready applications.

Now, make sure you have docker downloaded on your machine. You can download [here](https://www.docker.com/).

---


- **Node Application**
You need a server application running. Let’s qucikly setup a node application.

Open the terminal and run:

```
mkdir node-ec2 
cd node-ec2 
npm init --yes
```
Next, let’s install express and typescript:

```
npm install express --save
npm i -D typescript @types/express @types/node ts-node
```
**Generate a tsconfig.json:**

```
npx tsc --init
```
Go to the package.json file once these libraries have been installed to see a new dev dependencies object and also update it to have the build and start script:

```
{
  "name": "node-ec2",
  "version": "1.0.0",
  "main": "index.ts",
  "scripts": {
    "build": "tsc --project ./",
    "start": "npm run build && node build/index.js"
  },
  "license": "MIT",
  "dependencies": {
    "express": "^4.18.2"
  },
  "devDependencies": {
    "@types/express": "^4.17.15",
    "@types/node": "^18.11.18",
    "ts-node": "^10.9.1",
    "typescript": "^4.9.4"
  }
}
```
Open your prefered editor to create an _**index.js**_ file to setup Express and define a request handler.

```
import express, {Express, Request, Response} from "express";
const app: Express = express();
const port = 8080;

app.get('/status', (req: Request, res: Response) => {
    res.send({status: "Server is healthy!"});
});

app.listen(port, () => {
    console.log(`App is running at http://localhost:${port}!`)
});
```
We can start up the server by running:

```
npm start
```
When we navigate to [http://localhost:3000/status](http://localhost:8080/status), we ought to receive a response with the status “Server is healthy!” As soon as that succeeds, be careful to shutdown the server by pressing CTRL+C.

Let’s create a Docker image of our straightforward Node application so that it can be deployed to EC2.

---

**3. Dockerizing our Node Application**
Create a file and name it _Dockerfile_

```
FROM node:16-alpine

WORKDIR /usr/src/app

COPY package*.json ./

RUN npm install

COPY . .

RUN npm run build

EXPOSE 8080
CMD [ "node", "build/index.js" ]
```
We can use the above docker script for simple node applications. Now let’s build the docker image using the command below:

```
docker build . -t node-ec2
docker run -p 8080:8080 node-ec2
```
If you navigate to [http://localhost:3000/status](http://localhost:8080/status), we ought to receive a response as before. Now shutdown the server by pressing CTRL+C.

Finally, let’s push our docker image to [Docker Hub](https://hub.docker.com/):

```
docker login # Enter your Docker Hub credentials here
docker tag node-ec2 <YOUR_DOCKER_USERNAME>/node-ec2
docker push <YOUR_DOCKER_USERNAME>/node-ec2
```

---


**Deployment to EC2**
Now that we’ve dockerized our application, we need to setup an ec2 instance for it to run on.

Head over to AWS and sign in.

On the navigation bar, click on the search box, search for _EC2_. 

On you open up the EC2 page, you’ll have a page that looks like this:


![Ec2 dashboard](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6vkawpyfkexag97o3wem.png)

Click on _Launch Instance_.

On the next page, you should have a view like below:


![Launch Ec2 instanc](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xh109eg5654h59p6c6hf.png)

---

**AMIs**
Here is where we choose the AMI, or short for Amazon Machine Image. An AMI is a server that may be purchased in a variety of configurations.

For instance, we might choose an Amazon Linux 2 AMI, or if you scroll down, you’ll find other instances with Ubuntu running on them.

Each AMI is a copy of a machine’s operating system and possibly some other software that has been frozen.

Click on _Browse more AMIs_ to view the list of several AMIs available.


![Ec2 Amis](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/041zfxf8hxdloyxrv6kb.png)

To make things simple, we can utilize this to create an EC2 instance that is already set up using Docker!

To do this, we need to click “AWS Marketplace AMIs” on the left and then type “ECS” into the search bar. Several results ought to come up, however we want the “ECS Optimized Amazon Linux 2” image.

This image, which includes Docker, is designed specifically for running containers. The next page will open after you click “Select” on the selected image:


![Select ami](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/70d7a10j7wozealzzd7x.png)

After clicking Select, a pop up will show, then you’ll click on Continue.

Enter your instance name. For example, node-ec2.


![Launch instance](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eiq60xsr4oyp1ir7brzz.png)

**Instance Types**
We decide what kind of instance we want on the next view. In general, this determines the resources that will be made available to the server that we’re launching, with scaling fees for machines with higher performance.

Scroll down the page to select the instance type — It is advised to utilize the _t2.micro_ instance type since it qualifies for the free tier:


![Free tier instance](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oqwhsswcth4vacg9qa6n.png)

**Key Pair**
It is important that you create a key pair before launching the application in order to be able to access it.


![Key pair](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gf1k3cf46b1rjnj7xod0.png)

Click on create key pair and you should have a pop up like the one below:


![Create key pair](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a7sot3rjpii4jico2vc9.png)

Enter your key pair name. Leave the Private key file format as .pem. Once you click on _Create key pair_, It will be downloaded automatically.

**Network Settings (Security Group)**
This signifies that any traffic utilizing the **TCP protocol** that enters through **port 22** is permitted **(0.0.0.0/0 denoting any location)**. To enable everyone to use our app at port 8080, we must add one more rule.

Make sure you select the check boxes for allowing Http and Https from anywhere.

![Network group settings](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b8c165ulrw26vbzibarf.png)

> There are some other advanced configurations that you can set up depending on your app needs. We don’t need to do that for now.

You can now go ahead to launch the instance.


![Launch Instance](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v54azv2pzdk6vrboefkp.png)

On the next page that shows, please wait patiently for the instance to be launched successfuly.

Once the instance is launched successfully, you’ll see a page like the one below:


![Launch instance success](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sxs3s6p1bkjclfzhwiij.png)

**Click on the Instance Id.**

Connecting to Your EC2 Instance
Once you click on the Intance Id, a new tab is open and you see a page like this:


![Connect to Ec2 instance](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s9oogbwmoh0ddrofbldk.png)

Click on the check box to view the instance details. On the section below, copy the Instant Public Ipv4 address.

Now, go to your computer terminal and enter the following commands:

```
chmod 400 <NAME_OF_KEYPAIR_FILE>
ssh -i <NAME_OF_KEYPAIR_FILE> ec2-user@<PUBLIC_IPV4_ADDRESS>
```
Once you’re logged into the server, enter the docker command below:

```
docker run -p 8080:8080 <YOUR_DOCKER_USERNAME>/node-ec2
```

> For M1 Mac users, you might experience an error like this:

```
WARNING: The requested image's platform (linux/arm64/v8) does not match the detected host platform (linux/amd64) and no specific platform was requested
exec /usr/local/bin/docker-entrypoint.sh:
```

If you have an error like the one above, just run the docker command like below:

```
docker run --platform linux/amd64 -d -p 8080:8080 <YOUR_DOCKER_USERNAME>/node-ec2

```
You should have your app running successfully by now. You’ll be able to reach the instance using the same address you used to SSH into the instance. Simply navigate in your browser to:

```
<Public_Ipv4_Address>:8080/status
```
**Security**
When it comes to securing your EC2 instance, there are several measures you should put in place.

Using a _.pem_ file: A pem file allows you to be able to authenticate to the instance direclty without public access.
Checking the security groups: You can make your instance available only via SSH or HTTPS protocol.
There are other measures to put in place for securing our instance, but that’ll be a seperate tutorial for now.

**Other AMIs**
There are hundreds of different AMIs, many of which come from different communities and have pre-installed applications. It’s worth looking through them to see if there’s a simple method to set up anything you’ve wanted to work with.

**Adding a Custom Domain**
You might want to create a domain name and direct it at your application now that it is operating on a server.

**Conclusion**
Since RDS (AWS’ database service) is essentially simply highly optimized EC2 instances with a lovely dashboard, EC2 is the backbone of many AWS services.

Understanding this foundational tool in AWS’ armory will inevitably lead to the discovery of fresh ways to carry out concepts.

In this article, we’ve used Express to build a straightforward Node.js application, dockerized it, set up EC2 for deployment, and then deployed it to the EC2 instance.

If you want to learn how to architect an EC2 instance, with load balancers, docker and Amazon RDS, i’ll be uploading another tutorial soon.

Kindly follow me to stay updated on my latest tutorials.

Cheers! 🥷🏻

#docker #nodejs #ec2 #express #typescript