Docker Compose Nodejs and Postgres example

Docker provides lightweight containers to run services in isolation from our infrastructure so we can deliver software quickly. In this tutorial, I will show you how to dockerize Nodejs Express and Postgres example using Docker Compose.

Related Posts:
Node.js Express & PostgreSQL Rest APIs example
Node.js Express Pagination with PostgreSQL example
Node.js Typescript Rest API with Postgres example
Node.js JWT Authentication & Authorization with PostgreSQL example
Import CSV data into PostgreSQL using Node.js
Export PostgreSQL data to CSV file using Node.js

Dockerizing Node.js and Postgres Overview

Assume that we have a Nodejs Application working with Postgres database.
The problem is to containerize a system that requires more than one Docker container:

  • Node.js Express for API
  • PostgreSQL for database

Docker Compose helps us setup the system more easily and efficiently than with only Docker. We’re gonna following these steps:

  • Create Nodejs App working with Postgres database.
  • Create Dockerfile for Nodejs App.
  • Write Docker Compose configurations in YAML file.
  • Set Environment variables for Docker Compose
  • Run the system.

Directory Structure:


Create Nodejs App

You can read and get Github source code from one of following tutorials:
Node.js Express & PostgreSQL Rest APIs example
Node.js Express Pagination with PostgreSQL example
Node.js Typescript Rest API with Postgres example
Node.js JWT Authentication & Authorization with PostgreSQL example
Import CSV data into PostgreSQL using Node.js
Export PostgreSQL data to CSV file using Node.js

Using the code base above, we put the Nodejs project in bezkoder-app folder and modify some files to work with environment variables.

Firstly, let’s add dotenv module into package.json.

  "dependencies": {
    "dotenv": "^10.0.0",

Next we import dotenv in server.js and use process.env for setting port.

// set port, listen for requests
const PORT = process.env.NODE_DOCKER_PORT || 8080;
app.listen(PORT, () => {
  console.log(`Server is running on port ${PORT}.`);

Then we change modify database configuration and initialization.


module.exports = {
  HOST: process.env.DB_HOST,
  USER: process.env.DB_USER,
  PASSWORD: process.env.DB_PASSWORD,
  DB: process.env.DB_NAME,
  port: process.env.DB_PORT,
  dialect: "postgres",
  pool: {
    max: 5,
    min: 0,
    acquire: 30000,
    idle: 10000


const dbConfig = require("../config/db.config.js");

const Sequelize = require("sequelize");
const sequelize = new Sequelize(dbConfig.DB, dbConfig.USER, dbConfig.PASSWORD, {
  host: dbConfig.HOST,
  dialect: dbConfig.dialect,
  port: dbConfig.port,
  operatorsAliases: false,

  pool: {
    max: dbConfig.pool.max,
    min: dbConfig.pool.min,
    acquire: dbConfig.pool.acquire,
    idle: dbConfig.pool.idle


We also need to make a .env sample file that shows all necessary arguments.




Create Dockerfile for Nodejs App

Dockerfile defines a list of commands that Docker uses for setting up the Node.js application environment. So we put the file in bezkoder-app folder.

Because we will use Docker Compose, we won’t define all the configuration commands in this Dockerfile.


FROM node:14

WORKDIR /bezkoder-app
COPY package.json .
RUN npm install
COPY . .
CMD npm start

Let me explain some points:

  • FROM: install the image of the Node.js version.
  • WORKDIR: path of the working directory.
  • COPY: copy package.json file to the container, then the second one copies all the files inside the project directory.
  • RUN: execute a command-line inside the container: npm install to install the dependencies in package.json.
  • CMD: run script npm start after the image is built.

Write Docker Compose configurations

Let’s make Nodejs connect with PostgreSQL using Docker.

On the root of the project directory, we’re gonna create the docker-compose.yml file. Follow version 3 syntax defined by Docker:

version: '3.8'


  • version: Docker Compose file format version will be used.
  • services: individual services in isolated containers. Our application has two services: app (Nodejs) and postgresdb (Postgres database).
  • volumes: named volumes that keeps our data alive after restart.

Let’s implement the details.


version: '3.8'

    image: postgres
    restart: unless-stopped
    env_file: ./.env
      - db:/var/lib/postgres
      - postgresdb
    build: ./bezkoder-app
    restart: unless-stopped
    env_file: ./.env
      - DB_HOST=postgresdb
    stdin_open: true
    tty: true



  • image: official Docker image
  • restart: configure the restart policy
  • env_file: specify our .env path that we will create later
  • environment: provide setting using environment variables
  • ports: specify ports will be used
  • volumes: map volume folders


  • depends_on: dependency order, postgresdb is started before app
  • build: configuration options that are applied at build time that we defined in the Dockerfile with relative path
  • environment: environmental variables that Node application uses
  • stdin_open and tty: keep open the terminal after building container

You should note that the host port (LOCAL_PORT) and the container port (DOCKER_PORT) is different. Networked service-to-service communication uses the container port, and the outside uses the host port.

Docker Compose Environment variables with Postgres

In the service configuration, we used environmental variables defined inside the .env file. Now we start writing it.




Run Nodejs Postgres with Docker Compose

We can easily run the whole with only a single command:
docker compose up

Docker will pull the PostgreSQL and Node.js images (if our machine does not have it before).

The services can be run on the background with command:
docker compose up -d

$ docker compose up -d
[+] Running 14/14
 ✔ postgresdb 13 layers [⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿]      0B/0B      Pulled                                                                                                                                                              
   ✔ a378f10b3218 Pull complete                                                                                                                                                                                              
   ✔ 2ebc5690e391 Pull complete                                                                                                                                                                                              
   ✔ 8fe57f734687 Pull complete                                                                                                                                                                                              
   ✔ a2ddbb09cd9a Pull complete                                                                                                                                                                                             
   ✔ 5a2499e87ab8 Pull complete                                                                                                                                                                                             
   ✔ a45f5c4adf1b Pull complete                                                                                                                                                                                             
   ✔ 178017fd978e Pull complete                                                                                                                                                                                             
   ✔ 428dff1cb77d Pull complete                                                                                                                                                                                             
   ✔ 4667364adfc4 Pull complete                                                                                                                                                                                             
   ✔ 4eea1f5281a9 Pull complete                                                                                                                                                                                             
   ✔ 369467411787 Pull complete                                                                                                                                                                                             
   ✔ 51184495a2bc Pull complete                                                                                                                                                                                             
   ✔ d3e246f01410 Pull complete                                                                                                                                                                                             
[+] Building 77.4s (10/10) FINISHED                                                                                                                                                                                docker:default
 => [app internal] load build definition from Dockerfile                                                                                                                                                                     
 => => transferring dockerfile: 179B                                                                                                                                                                                         
 => [app internal] load .dockerignore                                                                                                                                                                                        
 => => transferring context: 2B                                                                                                                                                                                              
 => [app internal] load metadata for                                                                                                                                                              
 => [app 1/5] FROM                                                                                                        
 => => resolve                                                                                                             
 => => sha256:3d2201bd995cccf12851a50820de03d34a17011dcbb9ac9fdf3a50c952cbb131 10.00MB / 10.00MB                                                                                                                             
 => => sha256:2cafa3fbb0b6529ee4726b4f599ec27ee557ea3dea7019182323b3779959927f 2.21kB / 2.21kB                                                                                                                               ...
 => => extracting sha256:0c8cc2f24a4dcb64e602e086fc9446b0a541e8acd9ad72d2e90df3ba22f158b3                                                                                                                                    
 => => extracting sha256:0d27a8e861329007574c6766fba946d48e20d2c8e964e873de352603f22c4ceb                                                                                                                                    
 => [app internal] load build context                                                                                                                                                                                        
 => => transferring context: 17.47kB                                                                                                                                                                                         
 => [app 2/5] WORKDIR /bezkoder-app                                                                                                                                                                                          
 => [app 3/5] COPY package.json .                                                                                                                                                                                            
 => [app 4/5] RUN npm install                                                                                                                                                                                               
 => [app 5/5] COPY . .                                                                                                                                                                                                       
 => [app] exporting to image                                                                                                                                                                                                 
 => => exporting layers                                                                                                                                                                                                      
 => => writing image sha256:4571b91ea16b395b5e00833cc5770695f07250627ebceee1d5125660b93abd00                                                                                                                                 
 => => naming to                                                                                                                                                                         
[+] Running 4/4
 ✔ Network node-postgres_default         Created                                                                                                                                                                             
 ✔ Volume "node-postgres_db"             Created                                                                                                                                                                             
 ✔ Container node-postgres-postgresdb-1  Started                                                                                                                                                                             
 ✔ Container node-postgres-app-1         Started     

Now you can check the current working containers:

$ docker ps
CONTAINER ID   IMAGE               COMMAND                  CREATED         STATUS         PORTS                                       NAMES
4b781fa774f6   node-postgres-app   "docker-entrypoint.s…"   2 minutes ago   Up 2 minutes>8080/tcp, :::6868->8080/tcp   node-postgres-app-1
d268e1be7e80   postgres            "docker-entrypoint.s…"   2 minutes ago   Up 2 minutes>5432/tcp, :::5433->5432/tcp   node-postgres-postgresdb-1

And Docker images:

$ docker images
REPOSITORY            TAG       IMAGE ID       CREATED         SIZE
node-postgres-app     latest    4571b91ea16b   3 minutes ago   943MB
postgres              latest    f7d9a0d4223b   4 weeks ago     417MB

Send a HTTP request to the Nodejs – Postgres application:


Check Postgres Database:

$ docker exec -ti node-postgres-postgresdb-1 /bin/bash
root@eba893d13a10:/# psql bezkoder_db postgres
psql (16.0 (Debian 16.0-1.pgdg120+1))
Type "help" for help.

bezkoder_db=# SELECT * FROM tutorials;
 id |          title          |    description    | published |         createdAt          |         updatedAt          
  1 | Docker Postgres Express | Tut#1 Description | f         | 2023-10-14 10:13:17.432+00 | 2023-10-14 10:13:17.432+00
(1 row)

Stop the Application

Stopping all the running containers is also simple with a single command:
docker compose down

$ docker compose down
 ✔ Container node-postgres-app-1         Removed                                                                                                                                                                  
 ✔ Container node-postgres-postgresdb-1  Removed                                                                                                                                                                   
 ✔ Network node-postgres_default         Removed     

If you need to stop and remove all containers, networks, and all images used by any service in docker-compose.yml file, use the command:
docker compose down --rmi all


Today we’ve successfully created Docker Compose file for Postgres and Nodejs application. Now we can deploy Nodejs Express and Postgres with Docker on a very simple way: docker-compose.yml.

You can apply this way to one of following project:
Node.js Express & PostgreSQL Rest APIs example
Node.js Express Pagination with PostgreSQL example
Node.js Typescript Rest API with Postgres example
Node.js JWT Authentication & Authorization with PostgreSQL example

Happy Learning! See you again.

Source Code

The source code for this tutorial can be found at Github.

If you want to add Comments for each Tutorial. It is the One-to-Many Relationship there is a tutorial:
Node.js Sequelize Associations: One-to-Many example
(the tutorial uses MySQL but you can easily change the configuration for PostgreSQL)

Or you can add Tags for each Tutorial and add Tutorials to Tag (Many-to-Many Relationship):
Node.js Sequelize Associations: Many-to-Many example

You can deploy the container on Digital Ocean with very small budget: 5$/month.
Using referral link below, you will have 200$ in credit over 60 days. After that, you can stop the VPS with no cost.

DigitalOcean Referral Badge