Deploying NestJS application on Elastic Beanstalk

Viewed 4894

I am trying to deploy my NestJS application to AWS elastic beanstalk, but did not had any success, can someone please write step by step how can I achieve that?

Full explanation:

I have a nestjs app with typeorm but didn’t configured it to work with RDS, so we will leave it for now (maybe there is a connection, idk).

First of all I made a CodePipline that when I am pushing new version to my github repo it automatically deploying the whole repo to my eb instance that works on node 12.x.

Now, I want that on every git push, the instance will install the dependencies, build the nest app, and start the server from the /dist/main.js.

I have added a Procfile with:

web: npm install && npm run build && npm run start:prod

I have also added PORT environment variable on EB that configured on main.ts and when not found to use 8080.

And my package.json scripts are like a newly created nest app:

  "scripts": {
    "prebuild": "rimraf dist",
    "build": "nest build",
    "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
    "start": "nest start",
    "start:dev": "nest start --watch",
    "start:debug": "nest start --debug --watch",
    "start:prod": "node dist/main",
    "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
    "test": "jest",
    "test:watch": "jest --watch",
    "test:cov": "jest --coverage",
    "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
    "test:e2e": "jest --config ./test/jest-e2e.json"
  }

When deploying I see in the logs that it did something like this:

Jan 23 20:01:14 web: > app@0.0.1 start /var/app/current
Jan 23 20:01:14 ip-172-31-17-171 web: > sudo npm i -g @nestjs/cli && node dist/main
Jan 23 20:01:14 web: We trust you have received the usual lecture from the local System
Jan 23 20:01:14 web: Administrator. It usually boils down to these three things:
Jan 23 20:01:14 web: #1) Respect the privacy of others.
Jan 23 20:01:14 web: #2) Think before you type.
Jan 23 20:01:14 web: #3) With great power comes great responsibility.
Jan 23 20:01:14 web: sudo: no tty present and no askpass program specified
Jan 23 20:01:14 web: npm ERR! code ELIFECYCLE
Jan 23 20:01:14 web: npm ERR! errno 1
Jan 23 20:01:14 web: npm ERR! app@0.0.1 start: `sudo npm i -g @nestjs/cli && node dist/main`
Jan 23 20:01:14 web: npm ERR! Exit status 1
Jan 23 20:01:14 web: npm ERR!
Jan 23 20:01:14 web: npm ERR! Failed at the app@0.0.1 start script.

So I am getting 502 when entering the env url.

So maybe it is a permission issue with npm? Or I need to deploy on some way only the /dist folder? What do you think the problem is?

It is my first time trying to deploy a backend server to eb :)

5 Answers
  • I got stuck with the deploying the nestjs app to AWS elastic beanstalk for a while so that I decide make the guide here. I make the deploy guide step by step here for deploying the simple app.

  • The reason WHY the deploying is usually FAILED because it does not know NEST dependencies (it does not install dev dependencies) and Typescript code which need to compile before uploading to server.

  • In my case, Use the compression for making the zip file (you can use the command line eb but try to use this first for simple).

  • Firstly, Preparing the zip file, this is really IMPORTANT for avoiding the FAILED while it is deploying.

    • You need to make dist folder. For doing this, we remove the dist folder first and run the command nest build (* this one do the tsc for compile Typescript for us).
    • Now, we have the dist folder, the next thing we need to do is copying the package.json ( * this one installing the DEPENDENCIES for us ) into dist folder to let server know installing the dependencies that we do not bring the node_module here.
    • In package.json, yarn start to run nest start but the AWS does not know Nest command so that we need to point it out by using node main.js (this file is in dist file, you need to make the path to main.js correctly). For doing this, we create the Procfile (reference this) and add the conntent is web: node src/main.js. Remember copying it into the dist file.
    • Compressing file correctly as this
  • Secondly, from AWS console creating the application or environment then uploading the zip file and get successful status. If not, check the log file to know why it failed. Maybe it does not the nest command, etc...

Hoping this guide will help you.

Cheer!

I was stuck with the following EBS eb-engine.log error:

"Instance deployment: You didn't include a 'package.json' file in your source bundle. The deployment didn't install a specific Node.js version."

"Instance deployment failed to generate a 'Procfile' for Node.js. Provide one of these files: 'package.json', 'server.js', or 'app.js'. The deployment failed."

Using all previous answers, the following works for me with CodePipeline and EBS:


buildspec.yml

version: 0.2
phases:
  install:
    commands:
      - npm install
  build:
    commands:
      - npm run build
  post_build:
    commands:
      - cp -R node_modules/ dist/node_modules # nodejs needs this
      - cp Procfile dist/Procfile # EBS needs this
artifacts:
  files:
    - "**/*"
  discard-paths: no
  base-directory: dist

Procfile

web: node main.js

The way it works is that CodeBuild handles Nest building, and CodeDeploy only deploys what's in dist/

Node will need node_modules so post build I copy it to dist/

But EBS complains there's no package.json or any file it recognizes in dist/, and since Procfile is usually at root, copy it so EBS finds it and starts by using node main.js

"build": "nest build && cp package.json dist/",
"postbuild": "cd dist && zip ../dist.zip -r * .[^.]*",
"start": "node main.js"

Modifying just these three scripts, it works for me. Procfile is not required.

Finally in the root folder of the project, the dist.zip file that was generated I upload it to Amazon

Change your artifacts to copy everything, so that Codebuild can copy your node_modules, package.json, dist folder automatically.

artifacts:  
  files:  
    - "**/*"

Then in your package.json, change the start command to production by default -

"start": "node dist/main"

Here is my buildspec.yml and package.json which works fine on Nestjs deployment on Elastic beanstalk

The mysterious part is this: where is sudo npm i -g @nestjs/cli coming from?

I'm also deploying to Elastic Beanstalk but I only have web: npm run start:prod in my Procfile. The build happens in CI, for that I'm using GitHub Actions. The general outline of the workflow file is as follows:

  1. Checkout
  2. Setup Node
  3. Install dependencies and build app
  4. Generate deployment ZIP archive
  5. Upload deployment archive to Elastic Beanstalk

I suggest you make your Procfile be like mine, run the build script locally, generate the deployment archive using something like zip -r deployment.zip dist package* Procfile and upload it to Elastic Beanstalk and see what the outcome is.

Related