deploy nextjs with elastic beanstalk and docker

How To Deploy Nextjs Project On AWS Elastic Beanstalk And Docker In 10 Minutes

introduction

In this tutorial we will see how we can deploy our NextJS application using NodeJS and Docker on Elastic Beanstalk, but first, lets talk about what Elastic Beanstalk is.

Elastic Beanstalk is AWS managed service for deploying, scaling and managing web application and services. Being a managed service means that AWS Elastic Beanstalk will take care of all deployment from capacity provisioning, load balancing, and auto scaling to application health monitoring. All you need to do is upload your code as we will do in this walk through. Though there are other managed services like  Heroku, Vercel, Engine Yard, Netlify, Azure DevOps, and DigitalOcean App service, that perform capacity provision, Elastic Beanstalk some more edge than they do, especially cost wise.

Let’s talk briefly about the pros and cons of Elastic Beanstalk.

pros of Elastic Beanstalk

Support: AWS Elastic Beanstalk has of support for many popular programming languages, including Java, .NET, PHP, Node.js, Python, Ruby, Go, and also Docker web applications.
Powerful Customization: Elastic Beanstalk as a combination of various AWS Service deployed for you means you can customize them to your taste. With that you can SSH into the EC2 server, change the Security group, add environment variables, increase or decrease server type, etc. They are all under your control.
Price and Flexibility: One good thing about Elastic Beanstalk is its good pricing. While you can easily match your application load to the deployed service, and also easily scale down. Thanks to the Autoscaling group.

cons of elastic beanstalk

Deployment Speed: The deployment on Elastic Beanstalk ranges from 5 minutes to 15 minutes for the simplest application. While this looks cool, it may be a drawback especially if you are managing a simple application that requires fast deployment and response in real time.
Stack Upgrades: The Beanstalk stack is a combination of AWS services that meets your application deployment requirement managed by AWS team. This translates to recieving regular updates. This updates are not mentioned in some cases, therefore can turn out you will be blind to what is going on in your stack. However, AWS CloudWatch events and logs can come to help with visibility.
Complex Troubleshooting: This is a bounce of from the above point. For one like me, I love to get my hands dirty when troubleshooting, however, with elastic beanstalk, I can be a little difficult finding what went wrong when an application fails deployment or health check. Like while I attempted deploying the first time, the Health status was 5xx error. There are different causes of that error there, and so, I had a hard time figuring out the issue. Though, AWS did justice bu providing the logs to give hints as to what is going wrong.

create beanstalk application

That been said, let’s move into deploying our application. We will start with using NodeJS, and then later, see how we can use docker.

Search for the AWS Elastic Beanstalk, then click the Create Application.

Click create application for elastic beanstalk

You will be asked for the Application Name. I named mind testbeanstalk. Also, I added tags to identify my deployment.

Enter a name for elastic beanstalk

After naming the project, you will be asked to choose the platform that Elastic Beanstalk will use in hosting your application. Click on the dropdown arrow to reveal the options. Since we are hosting a NextJS application which is a framework off React which is a framework from Javascript, we will choose the NodeJS Platform, and use the latest of the branch and version. We will deal with deployment using other platforms in later tutorial.

Select NodeJS platform for elastic beanstalk

Once we settled the platform, we will select the Application code, and since we are not testing Elastic Beanstalk, go ahead and select the Upload Your Code option.

You can also clone and upload the same Nextjs source code I used from my repository here. I have extracted the needed artifacts from the next build before pushing to that repository. You will see how to use the full source code later when we use docker multistage build to host Elastic Beanstalk.

upload zipped source code folder

Let’s proceed to select the location to upload the folder. As at the time of this writting, AWS Elastic Beanstalk only allows only two source code origin. Local File which is a zip file you upload from your machine, or Public S3 URL, which is the URL of the S3 bucket where you upload the code.

I have the code in my local and zipped it already. So, I will select the Local File option, then Choose File.

zip

NOTE: You will need to zip the root content of your project before uploading it into Elastic Beanstalk. Make sure your project contains the package.js, index files and node_modules directory in the zipped folder.

Upload your source code to elastic beanstalk

One more important step is to tell Elastic Beanstalk to ignore any elevated commands when compiling our code. So, we will add the NPM_CONFIG_UNSAFE_PERM in the environment properties.

Click the Configure More Options, select Software, click the Edit button.

Click Software in elastic beanstalk

Scroll down to find the Environment Properties and type in NPM_CONFIG_UNSAFE_PERM under Name, and true under value. Then, click on the Save button.

Set the environment variables for elastic beanstalk

In the next window, click on the Create App button. This send you configuration in “active mode” and since Elastic Beanstalk is a managed service, AWS will commence the deployment of your application and also configuration of all the needed services on your behalf. The service includes, EC2, AutoScaling Group, Security Group, and some more.

Create beanstalk
checking your deployment

You should get a screen like the below showing you the process of deploying you application. This will usually take some minutes to complete.

Successful deployment of nodejs nextjs elastic beanstalk

After the above process completes, you will get a status page showing the Health status and the Beanstalk URL for you application. You will also get some events logs at the bottom of the health status.

Deployed nodejs with elastic beanstalk

Grab the URL of from Elastic Beanstalk deployment and paste in your web browser. The app we deployed is a NextJS app default page.

And you successfully deploy your application using Elastic Beanstalk, next, we will deploy the same application using Docker to Elastic Beanstalk.

nextjs deployed with nodejs on elastic beanstalk
deploy with docker to elastic beanstalk

To begin, we will create a Dockerfile at the root of our source code directory. We will use the multi-stage docker configuration. This will ensure our image is a light as possible.

FROM node:18-alpine AS builder

WORKDIR /app 

COPY package.json /app

RUN npm install

COPY . .

RUN chmod -R 777 /app

RUN npm run build

FROM node:18-alpine AS runner

WORKDIR /app

COPY --from=builder /app/.next/standalone ./.next/standalone
COPY --from=builder /app/.next/static ./.next/standalone/.next/static
COPY --from=builder /app/public ./.next/standalone/public

EXPOSE 3000

CMD [ "node", "./.next/standalone/server.js" ]
dockerfile for docker deployment with elastic beanstalk

Now, let’s create our Elastic Beanstalk for docker deployment. Enter the name of your application.

Name the docker application

Under the Platform option, we will select the Docker. The branch and platform version remains the latest from AWS.

Select docker platform
zip the source code

Then, select the Upload Your Code option, and again upload the zipped source code containing the Dockerfile at the root of your project. Get the source code from here.

Then click on the Create Application.

Zipped source code

After a few minutes you should see the successful deployment of your application using docker engine which AWS Elastic Beanstalk created for us.

Deployed docker elastic beanstalk application
conclusion

Now you can deploy your application using AWS Elastic Beanstalk using NodeJS and Docker. You can also checkout how to deploy using aws code pipeline too.

troubleshooting
  1. ERROR: permission denied for npm run build
    SOLUTION: Change the file or directory mode to executable or to allow the present user access to it.
    RUN chmod -R 755 /app
  2. ERROR: Getting a 502 error after the deployment completes with a severe health status.
    SOLUTION: Change the start command inside the packaga.json from “next start”, to “node server.js” or “node startfile.js”.
    Where the startfile.js is your script that is responsible to start your application.
  3. ERROR: Error: Cannot find module ‘/var/app/current/server.js’
    SOLUTION: Check to be sure the server.js is at the root of the project. Add it there if it is not and rezip the directory.
  4. ERROR: 100.0 % of the requests are failing with HTTP 5xx.
    SOLUTION: The means the application deployed successfully, however, it could not be served. Check that the zips artifacts are the correct files and directories compiled to run the application. For Next, check that you compiled the build into a standalone subdirectory inside the .Next directory after the build.
  5. ERROR: RUN npm run build
    —> Running in c9296c1b349e
    sh: next: Permission denied

    SOLUTION:This happens when Elastic Beanstalk does not have root permission to run the npm run build command. Add the .npmrc file in the root of the project. Add the below snippet in the file.
    unsafe-perm=true
    You can set this environement configuration in the Beanstalk console.
    Environment > EnvironmentName > Configuration
    Scroll to Software Settings and add the environment variable NPM_CONFIG_UNSAFE_PERM = true.

    Also, create a 01_fix_permissions.config inside .ebextensions directory in the root of your project and add the config below.
files:
"/opt/elasticbeanstalk/hooks/appdeploy/pre/49_change_permissions.sh":
mode: "000755"
owner: root
group: root
content: |
#!/usr/bin/env bash
sudo chown -R ec2-user:ec2-user tmp/

Posted

in

by

Tags:

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *