Deploying a Node.js app to AWS Elastic Beanstak
April 5th, 2018
A simple Hello World example using the EB CLI
Hi there! Today we’ll show you how to create an Elastic Beanstalk environment and deploy your Node.js application to it with a single eb deploy command. We’ll assume you already have a Node.js application working locally. If you don’t, you can use the app code we prepared for this post which is a very simple express app created with the express generator package as stated here.
Let’s first explain what that Elastic Beanstalk thing is. According to AWS docs:
With Elastic Beanstalk, you can quickly deploy and manage applications in the AWS Cloud without worrying about the infrastructure that runs those applications. AWS Elastic Beanstalk reduces management complexity without restricting choice or control. You simply upload your application, and Elastic Beanstalk automatically handles the details of capacity provisioning, load balancing, scaling, and application health monitoring.
So basically EB is a high level layer that allows you to deploy a full application without having to think of the type of EC2 instance you need, the ELB configuration, the software you need to install in EC2 (for example Node, npm, etc) and many more things. And the coolest thing is that you can configure some scaling rules and EB will automatically lift or shutdown instances depending on the server loads. This makes using AWS as simple as ever.
What are we trying to do
The road-map for today is quite simple and has the following steps:
- Create an IAM user to handle deployments
- Create an EB app and environment
- Deploy our Node.js app to the EB app from the previous step with a single command.
There are some pre-requisites to get started with this:
- You must have the AWS and the EB CLI installed. Pretty straightforward tutorials here and here.
- Have a Node.js app ready to be deployed. You can create a sample app with express-generator
Create an IAM user
I always like to have good control over who does what within my AWS account. Usually whenever I start a new project I create a new IAM user with specific permissions depending on the project needs. Let’s get this started. Head over to your AWS console and open the IAM console. Select the Users option on the left side menu:
Hit that blue “Add user” button to create a new user account. We will create a new eb-deploy-user user which will have only programmatic access through the CLI.
Next step is to define permissions for the new user. As already said, you should always restrict as much as possible the permissions. In our case we are going to use just the EB deploy capabilities, so we’ll just assign the Elastic Beanstalk Full Access permission. For this we’ll create a new Group called eb-full-access and assign that group to our new user:
Continue hitting next and you should get a review screen that looks similar to this:
We’ll be using those access key and secret soon, so you can either leave this window open or download the CSV file using the “Download .csv” button.
Now open a console in your laptop and configure a new profile for the AWS cli. We’ll call this new profile eb-deploy-user . In order to do this we’ll use the aws configure tool like this:
Follow the prompt and you’ll end up with a new profile. If you want to confirm you can open the ~/.aws/credentials file and see that the new profile is there. We’re all set in terms of auth setup, now let’s move forward and create our first EB app.
Creating the EB App
We’ll do everything using the EB CLI tool. So to get started we’ll need to initialize our Node project as an EB project. For this we’ll use the eb init command and we’ll pass as an argument the new user profile we created using the --profile option:
We chose all the default options here. You’re free to play with other configurations, for the sake of simplicity we’re going the “default” way. If you head over to the Elastic Beanstalk console in your browser you’ll see that now you have a new application named elasticbeanstalk-helloworld . Make sure you’re on the US West Oregon zone, otherwise you won’t see your app listed.
Now it’s time to create our first EB environment. Basically in EB you have a top level entity which is the Application. Then within an application you can have multiple environments. In a real world case you’d have environments such as Development, Staging or Production. In our case we’ll create a single environment to show how things work.
Creating the EB Environment
In order to create our first environment we’ll use the eb create command that the EB CLI provides. Again, follow the prompt using all the default options for now:
After creating the EB app and environment you’ll notice that there’s a new directory in the root of you Node project called .elasticbeanstalk . This directory contains a YML file with the deployment configuration and looks like this:
branch-defaults: master: environment: elasticbeanstalk-helloworld-dev group_suffix: null global: application_name: elasticbeanstalk-helloworld branch: null default_ec2_keyname: null default_platform: Node.js default_region: us-west-2 include_git_submodules: true instance_profile: null platform_name: null platform_version: null profile: eb-deploy-user repository: null sc: git workspace_type: Application
This file tells the EB CLI all it needs to know in order to deploy your app. The branch-defaults property is where EB decides to which environment it should deploy depending on the local git branch you’res standing. In this case if we’re on the master branch, it will deploy to the elasticbeanstalk-helloworld-dev environment we just created. You can create extra environments and assign git branches to them.
The environment creation takes a few minutes as EB has to create the EC2 instance and configure everything. It will also attempt to deploy our app but as you’ll see later in your EB console, the deployment will fail. We need an extra configuration step in order to make things work.
Configuring the Node Command
The reason our app intial deployment fails is because EB looks at our application code and sees there’s an app.js file. When there’s an app.js file it assumes that’s the entry file and will attempt to run node app.js . But in our case we want to run the application using the npm start command. So what we’ll do is tell EB to use that instead of trying to run our app.js file.
Select the Configuration option on the left side menu within your app in the EB console and click the little “Modify” button within the “Software” box:
Now you’ll see that there’s an empty field called “Node command”. All you have to do is enter “npm start” as the start command and hit the “Apply configuration” button on the top right corner.
As you can see you can also change the Node version in your instance among other options. I highly encourage you to go over all of them and play with it to get a better understanding of the EB platform.
Once you apply the config, EB will automatically try to run the app again but this time using our new node command. And if everything went well, now you’ll see a Green status in your dashboard which means that things are working! You can click the environment URL and you’ll see our Express hello world page in your browser.
The EB URL for our app
Deploying your app from the console
With this configuration set, you can now deploy directly from your console without having to open the AWS console in the browser. All you have to do is run the eb deploy command and voila! Always make sure that you have commited the changes you want to deploy to the branch configured in the config.yml file. The deploy command always looks at your local branch and builds using that, if you have uncommitted changes they won’t be available in the deployed app.
Easy, isn’t it? Now you can deploy to multiple environments in EB directly from your local console using a single command. I’d like to mention a special case where you have transpiled code. We have some projects written in ES6 using Babel and they require a transpilation step. In these cases we do a build process that creates a zip file and use the deployment artifact option on the build.yml file to tell EB that we want to upload a specific built zip file instead of uploading the whole project. If you have questions about this I’ll be happy to help, just leave a comment!
The code for this tutorial can be found here: https://github.com/xoor-io/elasticbeanstalk-helloworld
On an upcoming post I’ll explain how to build a pipeline that will automatically deploy to EB any changes as soon as you push them to your git repo. Stay tuned!
And if you liked it, share it on Twitter!