Background
In this article, we are going to learn, how to use MongoDB in production along with user login credentials for a particular database. Running a MongoDB instance along with an application (Eg: Node.js app) is quite easy. But, accessing MongoDB inside container, doing backup/restore from the container to the host machine is not plain simple.
Furthermore, MongoDB does not enforce not just schema design but also the login credentials for setup. So, it's very usual to setup without credentials, more common in beginners which is vulnerable to use in production.So lets get started!
*Note: This article is more deviated towards using MongoDB in production with Docker rather than exploring, Docker/Docker Compose or Node.js app. Thus, having basic knowledge of docker would help. Here is an article on getting started with docker
What will we learn?
- Dockerize Node App with MongoDB
- Access MongoDB inside docker container
- Create mongo user login credentials
- Database backup and recovery
Dockerize Node App with MongoDB
Here is the very basic sample of our node app to demonstrate MongoDB connection using Docker. Prepare your project root having following files.
├── app.js
├── docker-compose.yml
├── Dockerfile
└── package.json
Now, go to the project root directory and add .env
file with the environment variables as follows:
MONGO_USERNAME=binod
MONGO_HOSTNAME=db
MONGO_PASSWORD=devcolumn
MONGO_PORT=27017
MONGO_DB=sample_db
PORT=5000
And your app.js file should be something like this. Pay close attention to MONGO_URI, where we configure USERNAME, PASSWORD, and MONGO_HOSTNAME for MongoDB. Rest of the code would be your application specific.
const express = require("express");
const mongoose = require("mongoose");
require("dotenv").config();
const {
PORT,
MONGO_USERNAME,
MONGO_PASSWORD,
MONGO_HOSTNAME,
MONGO_PORT,
MONGO_DB,
} = process.env;
const app = express();
const MONGO_URI = `mongodb://${MONGO_USERNAME}:${MONGO_PASSWORD}@${MONGO_HOSTNAME}:${MONGO_PORT}/${MONGO_DB}?authSource=admin`;
mongoose
.connect(MONGO_URI, { useNewUrlParser: true, useUnifiedTopology: true })
.then(() => {
console.log({ MONGO_URI });
console.log("Connected to MongoDB");
})
.catch((err) => {
console.error("Error connecting to MongoDB:", err);
});
app.use(express.json());
// Define a schema
const Schema = mongoose.Schema;
const bookSchema = new Schema({
name: String,
author: String,
});
// Define a book model
const BookModel = mongoose.model("books", bookSchema);
app.get("/", (req, res) => {
res.send("Hello Worldy!");
});
app.post("/books", async (req, res) => {
try {
const doc = await BookModel.create(req.body);
res.json({ success: true, doc });
} catch (err) {
throw err;
}
});
app.get("/books", async (req, res) => {
try {
const d = await BookModel.find({});
res.json({ success: true, data: d });
} catch (err) {
throw err;
}
});
app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});
Also, our Dockerfile and docker-compose file would be something like this;
Dockerfile
FROM node:18-alpine
WORKDIR /app
COPY ./package.json ./package.json
RUN npm install --production;
COPY . .
EXPOSE 5000
docker-compose.yml
version: "3"
services:
nodejs:
build:
context: .
dockerfile: Dockerfile
image: nodejs
container_name: nodejs
restart: unless-stopped
env_file: .env
environment:
- MONGO_USERNAME=$MONGO_USERNAME
- MONGO_PASSWORD=$MONGO_PASSWORD
- MONGO_HOSTNAME=$MONGO_HOSTNAME
- MONGO_PORT=$MONGO_PORT
- MONGO_DB=$MONGO_DB
ports:
- "7000:5000"
command: node app.js
depends_on:
- db
db: #DB SERVICE
image: mongo:latest
restart: unless-stopped
env_file: .env
ports:
- "27018:27017"
environment:
- MONGO_INITDB_ROOT_USERNAME=$MONGO_USERNAME
- MONGO_INITDB_ROOT_PASSWORD=$MONGO_PASSWORD
volumes:
- mydata:/data/db
volumes:
mydata:
From docker-compose.yml
, look at the db
service section; we have initialized MONGO_INITDB_ROOT_USERNAME
and MONGO_INITDB_ROOT_PASSWORD
which is a credential for MongoDB admin. We will use this credential later to access the database from the console as well.
*Note: MONGO_HOSTNAME must be the exact service name i.e. 'db' in our case. (You can rename it to any valid name)
So far, we setup a basic Node.js application with Docker and docker-compose file ready to run using docker command.
Now, let's jump into the terminal and go to the project root directory to run our application with the following command:
docker compose up -d --build
If you run docker ps
command, you should see two containers running in i.e. Node and MongoDB containers as follows:

Alright! So far so good. Our application is up and running using docker and next step is to login into the MongoDB console but, before that we need to enter inside MongoDB container using docker exec command.
Access MongoDB inside docker container
Run docker exec -it f67 sh
inside the terminal and you will have a MongoDB console ready for authentication. So, let's login using admin credential setup from docker compose file.
Enter mongosh -u binod -p --authenticationDatabase admin
inside the console followed by a password . Now you should be logged in as an Admin and can use mongo commands inside the terminal. Let's create a database with the command use sample_db
and all set! Our application should be running smoothly.
*TIP: You can create a database specific user credential. Please follow docs for more details.
Backup Database
In the latest iterations of mongodump, the --archive choice is now accessible, enabling the consolidation of all data into a single file. This can be leveraged to efficiently transfer all required information out of the container directly into a file on the host machine. Run the following command inside the terminal to backup:
docker exec -i <container_name or ID> /usr/bin/mongodump --username <username> --password <password> --authenticationDatabase admin --db <database_name> --archive > ~/Downloads/mongodb.dump
For connection URL:
docker exec -i <container_name or ID> /usr/bin/mongodump --uri "<your mongodb+srv link>" --archive > ~/Downloads/mongodb.dump
Again! Login to the MongoDB and delete the database sample_db
and before that make sure you have a backup dump file inside your Downloads
directory.
Restore Database
To restore database, user must have a database write access. Since we are using a Admin account it won't be a problem for us. But, if you are using database specific user, make sure the user has a database write access.
After that, go to the terminal and enter:
docker exec -i <container_name or ID> /usr/bin/mongorestore --username <username> --password <password> --authenticationDatabase admin --nsInclude="<database_name>.*" --archive < ~/Downloads/mongodb.dump
For connection URL:
docker exec -i <container_name or ID> /usr/bin/mongorestore --uri "<your mongodb+srv link>" --archive < ~/Downloads/mongodb.dump
Summary
In conclusion, ensuring the security of our data is paramount when using MongoDB in a production environment. Implementing strict login credentials, prioritizing data backup and recovery, are fundamental steps in bolstering database security, yet they are often overlooked by developers. Additionally, incorporating automated daily backups can significantly mitigate the risk of unforeseen data loss. Happy Learning ;)
Binod Chaudhary

Software Engineer | Full-Stack Developer