Deploy a NestJS App
NestJS (opens in a new tab) is a progressive Node.js framework for building server-side applications that focuses on scalability, extensibility, and versatility. Using NestJS, you can build well-architected sites and applications with JavaScript or TypeScript to make it easier to collaborate, scale, and grow your projects.
This quickstart guide explains how to deploy and host a NestJS application to Koyeb using Git-driven deployment, allowing you to use Koyeb for NestJS hosting. The application can be built using either native buildpacks or from a Dockerfile.
You will need:
- A Koyeb account (opens in a new tab)- it's free to get started!
- Node.js (opens in a new tab)
- (Optional) The Koyeb CLI for deployment from the terminal
You can deploy and preview the NestJS application from this guide using the Deploy to Koyeb button:
Consult the repository on GitHub (opens in a new tab) to view this example application.
Install the NestJS CLI
First, use npm
to install the NestJS command line utility globally. This tool can create new NestJS projects, run applications, and manage external library support:
npm install --global @nestjs/cli
Verify that the installation completed successfully:
nest info
The output includes information about your current environment, but will note that you're not currently in a project directory:
_ _ _ ___ _____ _____ _ _____
| \ | | | | |_ |/ ___|/ __ \| | |_ _|
| \| | ___ ___ | |_ | |\ `--. | / \/| | | |
| . ` | / _ \/ __|| __| | | `--. \| | | | | |
| |\ || __/\__ \| |_ /\__/ //\__/ /| \__/\| |_____| |_
\_| \_/ \___||___/ \__|\____/ \____/ \____/\_____/\___/
[System Information]
OS Version : Linux 6.5
NodeJS Version : v18.18.0
NPM Version : 9.8.1
[Nest CLI]
Nest CLI Version : 10.1.17
[Nest Platform Information]
😼 cannot read your project package.json file, are you inside your project directory?
This is expected since you have not yet created a NestJS project.
Create a new NestJS project
Initialize a new NestJS project using the nest new
command. This creates a new directory for the project and begins configuring the project:
nest new example-nestjs
Alternatively, you can fork the repository on GitHub (opens in a new tab) to get a complete copy of the code. If you fork the repository, then you can skip to section on git-driven deployment on Koyeb.
Depending on the local tools you have installed, the nest
command prompts you for the package manager you wish to use for the new project:
⚡ We will scaffold your app in a few seconds..
? Which package manager would you ❤ to use? (Use arrow keys)
❯ npm
yarn
pnpm
Select your preferred package manager. This example will use npm
.
The nest
tool configures the new project directory, installing all of the necessary dependencies and initializing a new Git repository. The project directory contains the following files and directories:
nest-cli.json
: The configuration file for the NestJS client behavior for the project.node_modules/
: The project dependencies.package.json
: The standard Node.js project configuration, defining metadata, scripts, dependencies, etc.package-lock.json
: The lock file for the project dependencies.README.md
: A generic NestJS project README.src/app.controller.spec.ts
: The unit tests for the application controller.src/app.controller.ts
: The basic controller (opens in a new tab) with a single route configured.src/app.module.ts
: The root module for the application.src/app.service.ts
: The service file with a basic method defined.src/main.ts
: The entry file for the application that creates an instance of your application and sets up the server.test/
: The project's end-to-end test files.tsconfig.build.json
: The TypeScript compiler configuration to use when building the project.tsconfig.json
: The TypeScript compiler configuration for the project.
The main app files are tored within the src
directory, and the project configuration is defined at the root level.
Test the NestJS application locally
Run the app locally to test it:
npm run start:dev
This starts a local development server running at localhost:3000
. The application automatically reloads when changes are detected within the project.
Visit localhost:3000
to view the result:
Hello World!
Press CTRL-C to stop the development server when you are finished.
Update application port configuration
This value of the run port (3000) is currently hardcoded in the src/main.ts
file. You can make the port configurable at runtime to make deployment more flexible.
Open src/main.ts
in your text editor and make the following changes:
import { NestFactory } from '@nestjs/core'
import { AppModule } from './app.module'
const port = process.env.PORT || 3000
console.log(`Launching NestJS app on port ${port}, URL: http://0.0.0.0:${port}`)
async function bootstrap() {
const app = await NestFactory.create(AppModule)
await app.listen(port)
}
bootstrap()
The server now listens to the port defined by the PORT
environment variable, and falls back on port 3000 if no value is defined.
Save and close the file when you are finished.
Test out the new functionality by starting the development server with the following command:
PORT=8000 npm run start:dev
The application is now served on port 8000.
Modify the start script
Currently the application's start script is configured to use the development server, but most Node.js projects use the start
script to run in production.
Open the package.json
file in your editor and modify the start
script to match the value being used for start:prod
:
{
...
"scripts": {
"build": "nest build",
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
"start": "node dist/main",
"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"
},
...
}
Save and close the file when you're finished.
This example application should run on any modern version of Node.js. If your application requires a
specific Node.js version, add or set the engines
section in your package.json
file. Consult the build
with Node.js page to learn more.
Create a Dockerfile for the project (Optional)
We can build and run our NestJS project on Koyeb using the native Node.js buildpack, but we can also optionally build from a Dockerfile for more control. To make it possible to build a container image for our application, we just need to create the Dockerfile. We'll also define a .dockerignore
file to tell the builder what files to skip when creating the image.
Start by defining the .dockerignore
file in your main project directory. Inside, paste the following contents:
.git
.gitignore
Dockerfile
.dockerignore
dist
node_modules
.env
README.md
This file tells Docker to not include Git files, the Docker files themselves, dependency directories, built artifacts, or environment files unless explicitly called out within the Dockerfile. This helps ensure that the image we build is not bloated and that the build completes faster.
Next, create a new file called Dockerfile
within the main project directory. Inside, paste the following contents, adapted from this NestJS template (opens in a new tab):
# Build stage
FROM node:lts-alpine AS builder
USER node
WORKDIR /home/node
COPY package*.json .
RUN npm ci
COPY --chown=node:node . .
RUN npm run build && npm prune --omit=dev
# Final run stage
FROM node:lts-alpine
ENV NODE_ENV production
USER node
WORKDIR /home/node
COPY --from=builder --chown=node:node /home/node/package*.json .
COPY --from=builder --chown=node:node /home/node/node_modules ./node_modules
COPY --from=builder --chown=node:node /home/node/dist ./dist
ARG PORT
EXPOSE ${PORT:-3000}
CMD ["node", "dist/main.js"]
This Dockerfile uses a multistage build (opens in a new tab) to separate the build steps from the final image environment. This creates a more streamlined image and allows us to tightly control what files are included in the final image.
Both stages are based on the Alpine version of the base Node.js image (opens in a new tab) and both configure a dedicated user called node
to perform the build and run actions. The application is built and run from /home/node
, the node
user's home directory, to make permissions management more straightforward.
The build stage is configured to copy the package.json
and package-lock.json
files and install the dependencies. It then copies the remaining files, builds the project, and prunes the development dependencies from the environment.
The production stage sets the NODE_ENV
environment variable to production
to tell NestJS that it should run with production features enabled. It then copies the package.json
and package-lock.json
files, the dependencies, and the built artifacts from the build stage. It marks the PORT
environment as user configurable and exposes the port. Afterwards, it executes the same command that the start
script defines in the package.json
file.
If you have Docker installed locally, you can build and test the image on your computer and optionally upload it to a registry. You can deploy container images from any container registry to Koyeb.
We can also build the Dockerfile directly from the repository when we deploy, which is useful as a way of automatically deploying when changes occur. We will demonstrate this method as one of the options in this guide.
Push the project to GitHub
Once you're finished configuring the project locally, you can commit your work and push it to GitHub.
NestJS automatically initializes a Git repository when the nest new
command is run, so we just need to add our project files to it. Run the following commands within the project's root directory to commit the project files and push changes to GitHub.
Remember to replace the values of <YOUR_GITHUB_USERNAME>
and <YOUR_REPOSITORY_NAME>
with your own information:
git add :/
git commit -m "Initial commit"
git remote add origin git@github.com:<YOUR_GITHUB_USERNAME>/<YOUR_REPOSITORY_NAME>.git
git push -u origin main
Deploy to Koyeb using git-driven deployment
Once the repository is pushed to GitHub, you can deploy the NestJS application to Koyeb. Any changes in the deployed branch of your codebase will automatically trigger a redeploy on Koyeb, ensuring that your application is always up-to-date.
To deploy the NestJS app on Koyeb using the control panel (opens in a new tab), follow the steps below:
- Click Create Web Service on the Overview tab of the Koyeb control panel.
- Select GitHub as the deployment option.
- Choose the GitHub repository and branch containing your application code. Alternatively, you can enter our public NestJS example repository (opens in a new tab) into the Public GitHub repository at the bottom of the page:
https://github.com/koyeb/example-nestjs
. - Choose the Builder for your project. We can use either a Dockerfile or buildpack for this repository.
- Name the App and Service, for example
example-nestjs
. - Click the Deploy button.
A Koyeb App and Service will be created. Your application will be built and deployed to Koyeb. Once the build has finished, you will be able to access your application running on Koyeb by clicking the URL ending with .koyeb.app
.
Deploy to Koyeb from a container registry
If you choose to build a container image for the NestJS application, you can optionally deploy the application from a container registry instead of from GitHub.
To deploy a pre-built NestJS container image on Koyeb using the control panel (opens in a new tab), follow the steps below:
- Click Create Web Service on the Overview tab of the Koyeb control panel.
- Select Docker as the deployment option.
- Choose the container image and tag from your registry and click Next to continue.
- Name the App and Service, for example
example-nestjs
. - Click the Deploy button.
A Koyeb App and Service will be created. The container image will be pulled from the container registry and a container will be deployed from it. Once the initialization is complete, you will be able to access your application running on Koyeb by clicking the URL ending with .koyeb.app
.