Effortless Development with NestJS, Docker, and Docker-Compose
Creating a new NestJS application is a walk in the park, thanks to its incredible CLI. With a single command, nest new app-name
, you have a fully functional application up and running. However, as your application grows in complexity and relies on external services like Postgres or Redis, setting everything up can become a daunting task. This is where Docker containerization comes into play, ensuring that your application works as expected, regardless of the environment, and automatically installing all necessary dependencies.
Creating a New Project
To create a new NestJS application, you can use the dedicated CLI. After installing the CLI globally, run nest new app-name
to generate a new application. The application will be generated in the app-name
folder in the current directory. The CLI wizard will ask you to choose between npm and yarn; for this guide, we’ll use npm.
Adding Docker with Multi-Stage Build
Containerizing your application with Docker has numerous advantages. It ensures that your application behaves consistently across different environments and allows you to automatically install external dependencies when starting the application. Docker images are also easily deployable on platforms like Heroku and work well with CI solutions like CircleCI.
To take advantage of Docker’s multi-stage build feature, create a Dockerfile
at the root of your application:
“`
development stage
FROM node:12.13-alpine AS development
WORKDIR /usr/src/app
COPY package*.json./
RUN npm install
COPY..
RUN npm run build
production stage
FROM node:12.13-alpine AS production
WORKDIR /usr/src/app
ARG NODEENV=production
ENV NODEENV=$NODE_ENV
COPY –from=development /usr/src/app/dist.
CMD [“node”, “dist/main”]
“`
This Dockerfile
uses the multi-stage build feature to keep the production image as small as possible by separating the development and production stages.
Adding Docker-Compose
To take your development environment to the next level, you can use docker-compose to wrap everything together. Create a docker-compose.yml
file in the application root directory:
“`
version: ‘3.7’
services:
main:
build:
context:.
target: development
volumes:
-.:/usr/src/app
– nodemodules:/usr/src/app/nodemodules
ports:
– “${SERVERPORT}:3000″
– “9229:9229”
environment:
– NODEENV=${NODEENV}
dependson:
– redis
– postgres
networks:
– app-network
redis:
image: redis
networks:
– app-network
postgres:
image: postgres
environment:
– POSTGRESPASSWORD=password
– POSTGRESUSER=user
– POSTGRES_DB=db
volumes:
– pgdata:/var/lib/postgresql/data
ports:
– “5432:5432”
networks:
– app-network
volumes:
node_modules:
pgdata:
networks:
app-network:
driver: bridge
“`
This docker-compose.yml
file defines three services: main
, redis
, and postgres
. The main
service uses the Dockerfile
to build the application, while the redis
and postgres
services use official images. The volumes
section mounts the current directory and node modules into the container, and the ports
section exposes the necessary ports.
Running the Application in Development
To run the application, use the following command:
docker-compose up
This will start the application, Redis, and Postgres services, and make them available on your host machine.
Adding npm Packages
When adding new npm packages, use the following command to rebuild the Docker image:
docker-compose build --build-arg NODE_ENV=development main
Setting up a Debugger in Visual Studio Code
To set up a debugger in Visual Studio Code, create a launch.json
file with the following content:
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "attach",
"name": "Attach to Docker",
"remoteRoot": "/usr/src/app",
"port": 9229,
"address": "0.0.0.0"
}
]
}
Then, update the start:debug
script in package.json
to include the --debug
parameter:
"start:debug": "nest start --debug 0.0.0.0:9229",
Finally, update the docker-compose.yml
file to use the --debug
parameter:
command: ["npm", "run", "start:debug"]
With these changes, you can now debug your application using Visual Studio Code.
Summary
In this article, we’ve seen how to create a fully fledged development environment for a NestJS application using Docker and docker-compose. By configuring the Visual Studio Code internal debugger to work with Docker, we’ve improved developer productivity.