Docker Compose Nodejs Express – Part 2

This is in continuation of our previous blog, where we deployed a simple app using docker. In this blog, we will see how to use docker-compose and whats the purpose of the same.

To continue from the previous blog, let’s assume we need to add a database like MongoDB to our Node.js app.

To setup mongo, we need a separate image

Just to clarify, there is another option you can think of that is to install MongoDB using apt-get in our previous container itself. But this a very bad practice in docker. Docker images should be as small as possible, and one image should only have one process.

So the first task is to install docker-compose

Once you have installed, create a docker-compose.yml file. This file has various instructions which, you can see here

version: '3.7'

        image: api
        build: .
            - 5000:3000
            - ./src:/workspace/src

        image: mongo
        restart: always

Here we define two services; the first is API, which is our app, and the second one is MongoDB, which is the mongo image.

We also define the ports and volume in this.

Next, in our Dockerfile we add mongo to our Node.js app.

FROM  node:13

WORKDIR /workspace

COPY package.json /workspace
#COPY index.js /workspace

VOLUME [ "/workspace/src" ]

RUN npm install

RUN npm install -g nodemon

RUN npm install mongodb --save


CMD [ "nodemon" ,"src/index.js" ]

const express = require('express')
const app = express()
const port = 3000

const MongoClient = require('mongodb').MongoClient;
const assert = require('assert');
// Connection URL
const url = 'mongodb://mongodb:27017';
// Database Name
const dbName = 'myproject';
// Use connect method to connect to the server
MongoClient.connect(url, function(err, client) {
  assert.equal(null, err);
  console.log("Connected successfully to server");
  const db = client.db(dbName);

app.get('/', (req, res) => res.send('Hello World!'))

app.listen(port, () => console.log(`Example app listening at http://localhost:${port}`))

P.S right now, I am installing packages directly via Dockerfile, but this not a proper practice at all. It would be best if you do this via package.json only.

Once you have completed the above procedure you are now ready to build.

sudo docker-compose build

This will build your image and also fetch MongoDB.


sudo docker-compose up

If you notice the logs.

You can also run the container in background using

sudo docker-compose up -d
sudo docker-compose logs api

Sometime you can get this error

This is because your Node.js app started before mongo got started. To fix this using “depends_on” in docker-compose.yml.

version: '3.7'

        image: api
        build: .
            - 5000:3000
            - ./src:/workspace/src
            - mongodb

        image: mongo
        restart: always

So as you can see, you can very easily manage multiple images via docker-compose and use this for development as well as production.

There are many other advanced configurations possible with docker-compose like using a password for MongoDB, how to expose a port for MongoDB, and access it via UI tools, etc. You can pass environment variables using docker-compose.yml as well.

Also, it is to note that in the above docker-compose, we never exposed MongoDB port to an external system. So the MongoDB is local only in the apps internal network!