CRUD API Express with RDS, ECS and Docker

Node.js, Docker, ECR, ECS, RDS, Postgres in a single Article

CRUD API Express with RDS, ECS and Docker

Video Version

Do you prefer the Video Version? youtube video

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

Then click on Create Database:

image.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

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

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

Once you’ve finished, click Create database.

image.png

Here is a review of our RDS Postgres instance:

image.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:

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

The UI interface looks like this:

image.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:

aws sts get-caller-identity

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

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

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

Clone the Repository

image.png

Clone the aws-express-template repository:

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

Now, CD into the directory on the command line:

cd aws-docker-templates-express

and open the project with your favorite IDE. If you have Visual Studio Code, you can type:

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):

npm i

To build the projects:

npm run build
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

To build the image with Docker, use this command:

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

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:

docker push  <AWS_ECR_REPO_URI>

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

image.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

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

image.png

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

image.png

Set the port to 80:

image.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

Next, click on Update:

image.png

On Task definition, you can just click Next:

image.png

On Define your service, also click Next:

image.png

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

image.png

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

image.png

Once it's done, click on the task:

image.png

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

image.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

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

Let's make another one:

image.png

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

image.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

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

Let's check that the values were updated:

image.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

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