Deploying a REST API using Express to Elastic Beanstalk

A couple of weeks ago, I was trying to deploy a small service, but I didn’t wanted to start creating the full infrastructure suite on Fargate yet; hence, the best option is Elastic Beanstalk. For a couple of days I did the deployment manually, but after reading a little bit more about Beanstalk, I found a CLI that simplified a lot of the deployment process.

Here is some documentation if you want to read about it, but for the mean time, I will write a little bit about how I used it. It might be useful to you, if like me, you are looking for ways to do a quick deployment and don’t want to invest time in configuring the CI/CD pipeline or a more complex setup.

Prerequisites

The express application was built using:

  1. Node version 10.15.0

  2. generator-express-no-stress-typescript version 4.2.1

Installing the CLI

To install the CLI, there are two approaches, using HomeBrew or the other one using PIP. In my case, I used Brew because it’s so much simpler (and also because the other way failed for me :).

Just type the following and brew should take care of everything for you:

brew install awsebcli

Configuring the CLI

I’m going to assume you are already using AWS profiles in your machine, if not, I recommend reading about them here.

To start the configuration in your project, navigate to the root folder of it, and type the following command:

eb init —profile [YOUR PROFILE NAME]

It will start a series of questions in the next sequence:

  1. Region: in our case, we selected us-east-1

  2. Elastic Beanstalk Application: it will prompt you create a new app if none is already created.

  3. Platform: in our case, we selected node.js

  4. SSH configuration

  5. Keypair: to connect to the instance, you will need a key pair to use via SSH. The CLI will help you to create one as well.

Important: there is a step asking you if you want to use CodeCommit, this will help you create a pipeline, however, since we are using other source control tools, we ignored it.

Once the CLI finishes, you will see a new folder in your project called: .elasticbeanstalk (notice the dot at the beginning). If you wanna read more about configuration options, go here and here.

First deployment

Now that our app is configured (at least for starters), we need to do a deployment. For that, we need to create an environment with the command:

eb create [ENVIRONMENT NAME]

We used DEV, and after it finishes, we need to update some configuration in the AWS console. We will update the node command, this command is the one nginx will use whenever a new deployment is done.

Elastic Beanstalk environment configuration

Just one more thing, as you can see, the environment uses nginx as base server, so make sure that the application is listening on port 8081 (look at the documentation here). Finally, we can run:

eb deploy

Important: I had an issue, a really weird one when I started doing changes and deploying them, and it seemed like the deployment never grabbed the latest changes. After reading in internet for some time, I found this post; and in one of his IMPORTANT notes, Jared mentioned that the changes must be committed to Git for them to be deployed. I don’t have the answer to why this happens, but seems important to note.

If you are using plain javascript, this could be all, it will give you the URL to use to connect and whatever you have built, should be ready for usage. However, as many of my other posts, I like typescript, and this isn’t the end of our journey.

Deploying Typescript

Using typescript, the deployment is not as straightforward, so we need to add one more step to our config.yml file and in the package.json.

Important: these steps are necessary because Elastic Beanstalk do not install dev dependencies in their machines, so we need to overcome that issue with this new process.

First, we need to add something that helps us to do the compilation of Typescript to Javascript. For that, we will add a shell script in the root of our app with the following contents:

zip dist/$npm_package_name.zip -r dist package.json package-lock.json .env

Then, we will modify the package.json’s scripts with the following:

{
  ....
  "scripts": {
      "compile": "ts-node build.ts && tsc && sh dist.sh",
       ...
  },
  ...
}

And finally, in our config.yml file under the .elasticbeanstalk folder, we will add the following content before the global declarations:

deploy:
  artifact: dist/npm_package_name.zip

Now, let’s explain a little bit about what we are doing.

The scripts in the package.json file were updated to run the shell script after the compilation is finished.

The shell file grabs everything that was compiled and move it into a zip file.

Important: The “npm_package_name” in the shell file will refer to the package.json name attribute. Make sure that in the config.yml file, you type the same name

Next, in the config.yml, we specify the file that we will deploying to the environment in Elastic Beanstalk. So, the ebcli will only grab the zip file and send it. Under the hoods, elastic beanstalk will unzip it and run the command specified in the beanstalk environment.

Finally, run again the eb deploy command, and now our Typescript Express API will run in the cloud.

Summary

Now that all sections have been covered, I hope that the application has been a success and you have deployed your app into the cloud. If you have any comment, don't hesitate in contacting me or leaving a comment below. And remember to follow me on twitter to get updated on every new post.