How to setup docker compose for your development environment (nest js)

How to setup docker compose for your development environment (nest js)

Before we get hands on , let's try to understand what docker is, why we need it and what docker compose is . You can skip to the hands on section if you already know what docker and docker compose is.

Docker is a containerization tool. It helps to easily create virtual environments on one machine ,thereby allowing you setup project for development, testing or production without interfering with or having to change the configuration on your local machine . Anything you do on docker is completely separated from what runs on your local machine , Uhmmmm not totally though ,we'd see to that part once we get to volumes. One of the problems docker solves it to help create a consistent environment for both development and production, that way we do not have the scenario of "it works on my machine but it does work on the cloud".

docker-compose is a tool (which ships with docker on windows) that is used to build and share multi-container application.

To learn more about docker and docker compose you can visit the official links at

Docker docs

docker compose docs

With that's said let's get hands on. I will be using nest js for the demo here but you can modify to suit any programming language or framework you prefer.

First is to create a nest application .

$ npm i -g @nestjs/cli

$ nest new project-name

Afterwards create a dockerfile (a file named "Dockerfile". Note: make sure you spell correctly...)

# Use the official Node.js image as the base image
FROM node:16

# Set the working directory in the container
WORKDIR /app

# Copy package.json and package-lock.json to the container
COPY package*.json ./

# Install project dependencies
RUN npm install

# Copy the rest of the application code to the container
COPY . .

# Start build the dist folder
RUN npm run build

# Expose the application port (if necessary)
EXPOSE 8000

# Start the Nest.js application
CMD [ "npm", "run", "start:prod" ]

The comment on each steps explains what each steps does .

Now you are ready to create a docker-compose.yml file .

To know what a yml file is and how it differs from json. Use can Google difference between JSON and yml.

Now create a file named docker-compose.yml and paste the content

version : "3.1"

services:
    app:
        container-name: my_nest_api
        ports:
            - 3000:3000
        build : .
        command : npm run start:dev
        volumes:
            - ./src : /app/src

Let's explain what's going on the version specify the docker-compose version you are using make sure you check by running docker-compose --version . On the command line.

The services section describes the list of container services you want to run . In our case we only have one for api. You can have others for frontend and database.

The port section is a list and we only have one mapping 3000:3000 . Means port 3000 exposes the port 3000 which nest uses by default to the public. The first number is the port that exposes the inner port (which is the second number and also the nest port) .

Build specify the path to get the dockerfile from which is in our current directory represented by "."

Note : you can also use the "image :" and specify the docker image you want to use.

Command represent and replaces the CMD command in the docker file so it is run instead of the CMD [ "npm", "run", "start:prod" ] in our docker file.

The volumes is the bit where I said we will get to . You can use volumes to persist data from your containers because containers are ephemeral i.e they are not meant to stick around for long you use them and once you are done replace them ,but what about the data on them ,maybe the changes you made and all. well that what you use volumes for - to persist the data in the container.

The line - ./src :/app/src . Helps to sync you source directory to the /app/src directory on the container . With this, any changes you make to you file on your local machine will sync to that on the container and the --watch mode triggered by the npm start:dev command will be able to detect the changes and then restart the container as you save .

That way your development environment is isolated and also very similar to the one you would be running on your cloud with a docker container .

A NEST JS SPECIFIC INSTRUCTIONS: on you tsconfig file add

"watchOptions": {
    "watchFile": "fixedPollingInterval"
}

This option sets the strategy for watching files to "fixedPollingInterval." In TypeScript's watch mode, the compiler monitors changes to files and recompiles them accordingly.
The "fixedPollingInterval" strategy uses a fixed polling interval to check for changes in files. It means that TypeScript will periodically check for changes at a fixed interval, rather than relying on native file system events

Now navigate to your root directory and run.

docker-compose up --build

The --build flag is to build the image before spinning up a container from it. You can exclude it after the first run.

In your src/app.service.ts make changes to the hello world and see your container restart seemlessly .

Navigate to localhost:3000 on your browser or do a get request from postman or insomnia ,or any http client you use, to view the changes .

To learn how to deploy to production with docker and github-actions on AWS , check out my post on How to deploy to AWS using docker compose and github action

I hope this helps thanks .