Automating Node.js Deployment to AWS Elastic Beanstalk with GitHub Actions
Automating the deployment of your applications can save you time and streamline your development process. This step-by-step guide will walk you through deploying a Node.js application to AWS Elastic Beanstalk and setting up a CI/CD pipeline using GitHub Actions. By the end, you'll have a fully automated workflow that tests and deploys your code every time you push to your main branch.
This tutorial is designed for beginners with a general familiarity with Git, GitHub, and AWS.
You can find the complete code for this tutorial in this GitHub repository.
What is AWS Elastic Beanstalk?
AWS Elastic Beanstalk is a service that makes it easier to deploy and manage applications in the AWS cloud. You simply upload your application, and Elastic Beanstalk automatically handles the deployment details of capacity provisioning, load balancing, auto-scaling, and application health monitoring.
Why use it?
- Simplicity: It abstracts away the complexity of setting up servers, load balancers, and databases.
- Scalability: It can automatically scale your application up or down based on demand.
- Cost-Effective: With the AWS Free Tier, you can run a simple application like the one in this guide at no cost. You only pay for what you use as your application grows.
What is GitHub Actions?
GitHub Actions is a CI/CD (Continuous Integration/Continuous Deployment) platform that allows you to automate your build, test, and deployment pipeline. You can create workflows that build and test every pull request to your repository or deploy merged pull requests to production.
Our Workflow Structure:
-
Event: A trigger that starts the workflow, such as a
push
to a branch. -
Jobs: A set of steps that execute on a runner. We will have a
test
job and adeploy
job. - Steps: Individual tasks that run commands in a job.
Why Combine Elastic Beanstalk with GitHub Actions?
Combining these two powerful tools creates a seamless CI/CD pipeline. With every push to your repository, GitHub Actions will automatically test your Node.js application and, if the tests pass, deploy it to your Elastic Beanstalk environment. This automation eliminates manual deployment steps, reduces the risk of human error, and allows you to release new features faster.
Prerequisites
Before we start, make sure you have the following set up:
- An AWS Account: You'll need an account with an IAM user that has permissions for Elastic Beanstalk. We'll create the necessary roles during the tutorial.
- A GitHub Repository: This is where your Node.js application code will live. For this tutorial, we will be using a pre-configured repository.
- Node.js: Ensure you have Node.js (version 18 or higher) installed on your local machine.
Let's Get Started!
Step 1: Set Up Your Node.js Application
To get you started quickly, a simple Node.js application using Express and TypeScript has been prepared.
- Clone the Repository: Open your terminal and clone the sample application:
git clone https://github.com/samowolabi/nodejs-elastic-beanstalk-with-githubactions-app.git
cd nodejs-elastic-beanstalk-with-githubactions-app
- Install Dependencies:
npm install
This project has a straightforward structure:
-
.github/workflows/ci.yml
: The GitHub Actions workflow file. -
src/index.ts
: The main application file. -
test/app.test.js
: A simple test file. -
package.json
: Defines project scripts and dependencies. -
tsconfig.json
: The TypeScript configuration file.
Step 2: Set Up AWS Elastic Beanstalk
Now, let's create the environment on AWS where our application will be deployed.
- Navigate to Elastic Beanstalk: Log in to your AWS Management Console and go to the Elastic Beanstalk service.
-
Create a New Environment:
- Click on Create Application.
-
Application name: Enter a name, for instance,
nodejs-app-eb-gh-app
. -
Platform: Select
Node.js
. For this guide, "Node.js 18" is used. -
Application code: Keep
Sample application
selected for now. - Under Presets, select Single instance (which is free-tier eligible).
- Click Next.
- Configure Service Access: This screen is crucial for granting Elastic Beanstalk the necessary permissions.
-
Service role: This role allows Elastic Beanstalk to manage other AWS resources on your behalf.
- If you don't have one, select Create and use new service role.
- A new window will open to create an IAM role. The role will be pre-configured. Simply click Create role.
- Back on the Elastic Beanstalk screen, refresh the dropdown and select the new role (
aws-elasticbeanstalk-service-role
).
-
EC2 instance profile: This role grants permissions to the EC2 instances that will run your application.
- Click Create and use new instance profile.
- In the new window, name your role (e.g.,
aws-elasticbeanstalk-ec2-new-role
). - The necessary policies (
AWSElasticBeanstalkWebTier
, etc.) will be attached automatically. Click Create role. - Return to the Elastic Beanstalk screen, refresh, and select the newly created instance profile.
-
Review and Launch:
- You can skip the networking, database, and tags setup for this simple deployment by clicking Skip to review.
- On the Review page, look over your configurations and click Submit.
AWS will now start building your environment. This process can take a few minutes. Once it's complete, you can access the provided domain, and you will see the default sample application page.
Bonus: Setting Up Environment Variables
Your Node.js application might require environment variables. You can set them up in the Elastic Beanstalk console:
- Go to your environment's page.
- Click Configuration > Software > Edit.
- Under Environment properties, add your key-value pairs (e.g.,
NODE_ENV
=production
). Elastic Beanstalk automatically provides thePORT
variable.
Step 3: Configure the CI/CD Pipeline with GitHub Actions
Now it's time to connect your GitHub repository to your new Elastic Beanstalk environment.
- Get AWS Access Keys: The GitHub Actions workflow needs credentials to deploy to your AWS account.
- In the AWS IAM console, navigate to Users and select your IAM user.
- Go to the Security credentials tab and click Create access key.
- Select Third-party service, acknowledge the recommendation, and proceed.
- You will be provided with an Access key ID and a Secret access key. Copy these immediately, as you won't be able to see the secret key again.
Note: Ensure your IAM user has the necessary permissions. For this deployment, the following policies are recommended:
elasticbeanstalk:*
,s3:*
,ec2:*
,iam:PassRole
, andlogs:*
.
-
Add Credentials to GitHub Secrets:
- In your GitHub repository, go to Settings > Secrets and variables > Actions.
- Click New repository secret and add the following:
-
AWS_ACCESS_KEY_ID
: Your AWS access key ID. -
AWS_SECRET_ACCESS_KEY
: Your AWS secret access key.
-
-
Understand the Workflow File:
Open the
.github/workflows/ci.yml
file in your repository. Let's break down what it does:
name: CI/CD
on:
push:
branches: [ main, master ]
pull_request:
branches: [ main, master ]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18.x, 20.x]
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test
- name: Build project
run: npm run build
deploy:
needs: test
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20.x'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Build project
run: npm run build
- name: Generate deployment package
run: |
zip -r deploy.zip . -x '*.git*' 'node_modules/.cache/*' 'src/*' 'test/*' '*.md' '.env*'
- name: Deploy to Elastic Beanstalk
uses: einaregilsson/beanstalk-deploy@v22
with:
aws_access_key: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws_secret_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
application_name: nodejs-app-eb-gh-app
environment_name: Nodejs-app-eb-gh-app-env
version_label: ${{ github.sha }}
region: us-east-1
deployment_package: deploy.zip
-
on
: This workflow triggers on apush
orpull_request
to themain
ormaster
branches. -
jobs
:-
test
: This job runs on two Node.js versions (18.x and 20.x). It checks out your code, installs dependencies, and runs your tests (npm test
) and build script (npm run build
). -
deploy
: This job depends on thetest
job succeeding (needs: test
). It only runs on apush
to themain
branch. It performs the build again, zips the necessary files intodeploy.zip
, and then uses thebeanstalk-deploy
action to push the package to your Elastic Beanstalk environment.
-
Important: Update the
application_name
,environment_name
, andregion
in thedeploy
job to match your Elastic Beanstalk setup.
Step 4: Deploy the Application
Now for the magic moment!
-
Push to Main: Commit any changes you've made and push them to your
main
branch.
git add .
git commit -m "feat: setup CI/CD and deploy to Elastic Beanstalk"
git push origin main
-
Monitor the Workflow: Go to the Actions tab in your GitHub repository. You will see your workflow running. Click on it to see the
test
anddeploy
jobs in action.
-
Verify Deployment: Once the
deploy
job is complete, navigate back to your Elastic Beanstalk environment's URL. You should now see the message: "Hello, TypeScript with Express!".
Conclusion and Troubleshooting
Congratulations! You have successfully set up a fully automated CI/CD pipeline. Every time you push a change to your main
branch, GitHub Actions will test your code and deploy it to AWS Elastic Beanstalk.
Common Issues:
-
Deployment Fails: Double-check that your AWS credentials in GitHub Secrets are correct and that the IAM user has the required permissions. Verify that the application and environment names in your
ci.yml
file match your Elastic Beanstalk setup exactly. -
Build/Test Failures: Run
npm test
andnpm run build
locally to debug any issues before pushing. - Check Logs: The first place to look for errors is the GitHub Actions log. For environment-specific issues, check the logs in your AWS Elastic Beanstalk console (Logs > Request Logs > Last 100 Lines).
This automated workflow is a fundamental practice in modern web development that will significantly improve your development and release process.
A practical guide by Samuel Owolabi
Top comments (0)