Connecting PostGreSQL DB with NestJS Backend


( this article is not written by ChatGPT )
This article is the continuation of dockerizing your whole backend application ( NestJS server and PostGres DB ) using docker compose series. in this article we will learn about
How you can spin up your postgres server using docker
Connecting your NestJS application with Postgres using TypeORM
Creating simple API endpoints to add and get data from DB
Spinning up PostGres Docker Container
in order to run your postgres container runing the following command
docker run \
--name postgres_server \
-p 5432:5432 \
-e POSTGRES_PASSWORD=password \
-e POSTGRES_DB=dummy \
-d \
postgres
This command starts a PostgreSQL database in Docker with the following settings:
--name postgres_server
→ Names the containerpostgres_server
.-p 5432:5432
→ Maps container's PostgreSQL port (5432) to your machine's port 5432.-e POSTGRES_PASSWORD=password
→ Sets the database superuser (postgres
) password topassword
.-e POSTGRES_DB=dummy
→ Creates a database nameddummy
on startup.-d
→ Runs the container in the background (detached mode).postgres
→ Uses the official PostgreSQL image from Docker Hub.
Our postgres container is created sucessfuly we can more forward by creating our nestJS application, you can skip the below step we you have the nest server already setup
Creating a NestJS Server
If you havn’t already install the nestjs cli then run:
npm install -g @nestjs/cli
1. Create a New Project
nest new dockerizing-backend
2. Navigate to the Project
cd dockerizing-backend
4. Run the App
npm run start:dev
now if you hit localhost:300/ , and if everything goes well you will be prompt as
wohoo!! we have our backend server running, lets move forward this
Setting up configurational variable
installing the nest/config module
npm install @nestjs/config
create
.env
file at the root of your project with following variables ( password and DB name will be same as we used while creating the docker container )DB_HOST=localhost DB_PORT=5432 DB_USER=postgres DB_PASSWORD=password DB_NAME=dummy
we now have our configurations ready we will be setting up the typeORM to use these configs while initializing our application
in
app.modules.ts
file add the following configurations
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { TypeOrmModule } from '@nestjs/typeorm'; // Import TypeOrmModule for database connection
import { ConfigModule } from '@nestjs/config'; // Import ConfigModule for environment variables
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true, // Makes config accessible in all modules
envFilePath: '.env', // Optional, defaults to `.env`
}),
TypeOrmModule.forRoot({
type: 'postgres',
host: process.env.DB_HOST, // Database host
port: parseInt(process.env.DB_PORT || '5432'), // Database port
username: process.env.DB_USER, // Database username
password: process.env.DB_PASSWORD, // Database password
database: process.env.DB_NAME, // Database name
entities: [],
synchronize: true, // Set to false in production
}),
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
This NestJS code connects your app to a PostgreSQL database using TypeORM and environment variables.
ConfigModule.forRoot()
→ Loads variables from.env
(like DB host, port, etc.) and makes them available everywhere.TypeOrmModule.forRoot()
→ Uses those variables to set up the PostgreSQL connection:type
,host
,port
,username
,password
,database
→ DB connection details.entities: []
→ Where your entity classes go (empty for now).synchronize: true
→ Auto-creates/updates tables from entities (good for dev, risky for prod).
Basically .env
holds DB details → ConfigModule reads them → TypeORM uses them to connect to Postgres.
Running the Application
npm run start:dev
if everything goes well you will see the green outputs regarding the Configmodule and TypeORM which means our application has sucessfully connected to the Database.
Now at this point you can pause this and finish going forward because you have sucessfully connected our nest application with postgres but if you wish to hold on and see how the DB communication stick to till the end
To test it out we will be creating two simple API endpoints for creating a dumy recording in our DB and fetching that record
Creating the Dumy APIs
Creating an item entity
Create
item.entity.ts
in the samesrc
directory where your app module is present// create a new file named item.entity.ts import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm'; @Entity('items') // Define the table name export class Item { @PrimaryGeneratedColumn() // Auto-incrementing primary key id: number; @Column({ type: 'varchar', length: 255 }) // String column with a max length of 255 characters name: string; }
now back to your
app.module.ts
file you will need to includeTypeOrmModule.forFeature([Item])
in the imports array
...
import { Item } from './item.entity';
@Module({
imports: [
ConfigModule.forRoot({
...
}),
TypeOrmModule.forRoot({
...
}),
TypeOrmModule.forFeature([Item]), // Register Item entity with TypeORM
],
...
})
export class AppModule {}
- once our item entity is register create simple controller at app.controller.ts
import { Body, Controller, Get, Post } from '@nestjs/common';
import { AppService } from './app.service';
import { Item } from './item.entity'; // Import the Item entity
import { Repository } from 'typeorm';
import { InjectRepository } from '@nestjs/typeorm';
interface ItemI {
name: string;
}
@Controller()
export class AppController {
constructor(private readonly appService: AppService,
@InjectRepository(Item) // Inject the repository for Item entity
private itemRepository: Repository<Item> // Inject the repository for Item entity
) {}
@Get("/item")
async getItem(): Promise<Item[]> {
// return all the results from db
return await this.itemRepository.find();
}
@Post("/item")
async createItem(@Body() item: ItemI): Promise<Item> {
// Create a new item instance and save it to the database
console.log("Creating item:", item);
const newItem = this.itemRepository.create(item);
return await this.itemRepository.save(newItem);
}
}
This controller exposes two simple APIs for the Item
entity using TypeORM’s repository:
GET /item
→ Fetches and returns allItem
records from the database.POST /item
→ Takesname
from the request body, creates a newItem
instance, saves it to the database, and returns the saved record.
It uses @InjectRepository(Item)
to inject the Item
repository for database operations.
now that Our app is setup with simple dumy apis run
npm run start:dev
and on postman you will see
Adding an entry to database item table
fetching entries from item table in db
🙌🙌Huray!!!!!!!!!!!!! our Application is working and is sucessfully able to make operations on postgres db
Outcome
Phew! In this tutorial, we learned how to quickly spin up a Postgres server using Docker and connect it to our NestJS application. We also tested the database connection by creating two demo APIs — one for adding a dummy entry to our Item
table and another for fetching those entries.
Way Forward
This article is part of my complete guide on dockerizing your backend application services. If you’ve been following along, great! And if you just stumbled upon this tutorial, you might want to check out the full guide where I walk you through dockerizing your NestJS application with a Postgres database using Docker Compose.
Subscribe to my newsletter
Read articles from Nabeel Ahmed directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
