CRUD API Express with RDS, ECS and Docker
Published: 2021-09-17 13:24:54

### Video Version

Do you prefer the Video Version? 
[![youtube video](https://cdn.hashnode.com/res/hashnode/image/upload/v1631882978925/6wUydrxDn.png)](https://youtu.be/0sbkdX4zTWE)

In this article, we will see how we can connect an ECS instance, based on an image on ECR, to an RDS Postgres instance. 

## Prerequisites

- Docker installed on your machine
- AWS account
 
## Definitions

- **RDS**: Relational Database Service. The AWS service for relational databases such as Postgres. (For more on RDS and Postgres, see my previous article.)

- **ECR**: Elastic Container Registry. Stores Docker images directly on AWS (essentially, an alternative to [Docker Hub](Docker Hub Container Image Library | App Containerization)).

- **ECS**: Elastic Container Service. Deploy and run an application based on an image stored on a registry (it works with both Docker Hub and ECR). 


## Our Steps Today

- Create an RDS Postgres instance
- Test the instance
- Create the ECR repository using the AWS command line interface
- Clone the repository
- Create the Docker image
- Tag the image accordingly to the ECR repository
- Push the image to ECR
- Create the ECS based on the ECR repository, setting env variables
- Final Test

### Create the RDS Postgres Instance

Go on the AWS console and search for RDS:

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1631698563522/Es3q6e62y.png)

Then click on **Create Database**:

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1631698607584/7UOO_06cj.png)

Let's create a PostgreSQL instance. We’ll use version 12.5-R1 so we can take advantage of AWS’ free tier:

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1631698721411/FgejgCWNF.png)

In **Settings**, input values for the following:

- DB instance identifier (the name)
- Master user
- Master password + Confirm password (choose a reasonably secure password)

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1631698896995/sNQNKb0L_.png)

For connectivity, you must be sure that the instance is accessible from the outside. Under **Public access**, select **Yes**  If you have network issues, check your security group’s inbound rules.

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1631699045293/v97e69A5L.png)

Once you’ve finished, click **Create database**.

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1631699267814/JkbsUK78O.png)

Here is a review of our RDS Postgres instance:

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1631699453370/Q2Oo0ByDi.png)

### Test the Instance

To test if the RDS instance is accessible, we can use the `psql` command. You can also test with other command-like tools like `pgadmin` or your local application. 

In the command below, replace `RDS_INSTANCE_IP` with the one you get from the RDS instance summary:

```console
psql --host RDS_INSTANCE_IP --port 5432 --username postgres
```

### Create the ECR Repository Using the Command Line Interface

ECR stands for Elastic Container Registry, and it's the image registry for AWS. Think about it as a place to store and retrieve your Docker images.

In the AWS Console, type `ECR` on the search bar and click on **Elastic Container Registry**:

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1631694550069/wb75EZ1JV.png)

The UI interface looks like this:

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1631694838453/Dw6Hqq20b.png)

This is a good way to check your existing repositories. But to create one, we’ll use the command-line interface.

Get your credentials using the command:

```console
aws sts get-caller-identity
```

Then use the credentials and the region you prefer.  eplace <REGION> with the region of your choice, and replace <AWS_ACCOUNT_ID> with your AWS account ID (you can get it with the commands).

```console
aws ecr get-login-password --region <REGION> | docker login --username AWS --password-stdin <AWS_ACCOUNT_ID>.dkr.ecr.<REGION>.amazonaws.com
```

Let's check if the repository has been created by checking the AWS Console:

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1631695016613/46TgTux2H.png)

Nice! Now let's clone and work on the repository.

### Clone the Repository

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1631693703897/hqeeuJpQ0.png)

Clone the aws-express-template repository:

```console
git clone https://github.com/tinystacks/aws-docker-templates-express.git
```

Now, CD into the directory on the command line:

```console
cd aws-docker-templates-express
```
and open the project with your favorite IDE. If you have Visual Studio Code, you can type:

```console
code .
```

### Check App and Create the Docker Image

If you want to test the project locally, you can install the dependencies (optional - requires npm installed locally):

```console
npm i
```

To build the projects:

```console
npm run build
```

```console
npm run start
```

Before we build the image, let's check the file inside the config folder called `postgres.ts`.

Here you can define some environment variables to access your database:

- `PG_HOST`: The address of the database. We’ll use the RDS instance address here later.
- `PG_PORT`: The port of the database. The default one for Postgres is 5432.
- `PG_USER`: The default user of the database
- `PG_PASSWORD`: The password for the user of the database.
- `PG_DATABASE`: The database we want to access. Note that a database called `postgres` is the default for a Postgres instance

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1631693966439/wx0ehNYYR.png)

To build the image with Docker, use this command: 

```console
docker build -t crud-express .
```

The name doesn't really matter here, as we will retag the local image in order to push it to the ECR repository we will create soon.

### Tag the Image to the ECR Repository

To tag the local image in order to push it to the ECR repository, you need to copy the image URI. For example, you can copy it from the Amazon Console’s list of your repositories in ECR:

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1631695275982/DJ7WuwwFa.png)

```console
docker tag crud-express <AWS_ECR_REPO_URI>  
```

### Push the Image to ECR

Just use the same tag as before to push the image tagged locally to your ECR repository:

```console
docker push  <AWS_ECR_REPO_URI>  
```

After this, wait a couple of minutes for the push to complete. 

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1631695485489/RWkG77sZc.png)

### Create and ECS Task from the ECR Repository Image

Now comes the interesting part. Since we have both:

- an RDS Postgres instance with public access
- an image on the ECR registry

- we can create an ECS instance based on the ECR image, and connect it to the RDS instance using the RDS instance's URI by supplying the `PG_HOST` variable to our application.

In the AWS Console, look for ECS: 

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1631695699922/4rJx8zdG3.png)

Let’s use the Console to configure a custom container:

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1631695862010/vPWRQLJu6.png)

Choose a container name of your choice. Use the ECR URI as your Docker image: 

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1631695952877/NLuIuXuJx.png)

Set the port to 80:

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1631695990264/Nb2Fp0Ijt.png)

Now a very important step - set the environment variable as follows: 

- Key :`PG_HOST`
- Value: Your RDS URI so the ECS app can connect to the RDS instance


![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1631696107648/g589fmG9U.png)

Next, click on **Update**:

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1631696254364/Xb0fCUPSM2.png)

On **Task definition**, you can just click Next:

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1631696303767/BjCV1x3eh.png)

On **Define your service**, also click **Next**:

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1631696529801/L3JWTTVZV.png)

For the cluster, you can choose a name for your cluster and then click **Next**:

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1631696469132/Wf8X7pad8.png)

Then you just have to wait a couple of minutes to let AWS create your resources:

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1631696605618/VOql30ScZ.png)

Once it's done, click on the task:

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1631696768532/EwNXXA7mm.png)

Scroll down and copy the Public IP so we can use with with our favorite API tester:

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1631696872954/tUY6wIkx7.png)

### Final Test

To test our application, we will use Postman. First of all, let's check if the app is up and running. Make a GET request at the endpoint `AWS_APP_IP:80/ping`:

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1631697282351/ZKwbHY_hO.png)

Now let's make a couple of inserts into the database. Make a PUT request with the following body (title and content) at the endpoint `AWS_APP_IP:80/postgresql-item`:

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1631697379486/5OJ4oKQgD.png)

Let's make another one:

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1631697402750/6aRxTfjuG.png)

Now, to get all the items, make a GET request at the endpoint `AWS_APP_IP:80/postgresql-item`:

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1631697471684/WQxL7D9B3.png)

To get a single item, make the same request appending the id of the item at the end of the url
(note that we are not handling errors properly here - this is for demo purposes):

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1631697544449/09TSnN4gL.png)

To update an existing item, you can make a POST request to the endpoint `AWS_APP_IP:80/posgresql-item/1`, specifying an id and passing a message body: 

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1631697642528/M1FDkuHTA.png)

Let's check that the values were updated:

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1631697847772/1sd1TECz8.png)

You can also delete an existing item, making a DELETE request at the endpoint `AWS_APP_IP:80/postgresql-item/ID` (e.g. 2):
![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1631697934173/UvSN1CfV0.png)

And with that we’ve successfully validated connecting an ECS task to a Amazon RDS database!

### Video Version

Do you prefer the Video Version? 
[![youtube video](https://cdn.hashnode.com/res/hashnode/image/upload/v1631882978925/6wUydrxDn.png)](https://youtu.be/0sbkdX4zTWE)