In this blog post, I will guide you through Dockerizing a Node.js application that uses MongoDB. We will cover setting up the Node.js app, creating a MongoDB database, and using Docker to containerize both services. By the end of this tutorial, you'll have a working application running in Docker containers.
Prerequisites
- Basic knowledge of Node.js and Express
- Basic understanding of Docker and Docker Compose
- Node.js and Docker installed on your machine
Project Structure
Step 1: Setting Up the Node.js Application
First, let's set up our Node.js application. We'll create a simple product management API using Express and MongoDB. We'll use the src folder for this in our project.
ProductController.js
This file contains the controller logic for handling requests related to products.
import Product from '../models/Product.js';
async function index(req, res, next) {
try {
const products = await Product.find();
return res.status(200).json({
status: 200,
data: products
});
} catch (e) {
console.log(e);
return res.status(500).json({
message: e
});
}
}
async function save(req, res, next) {
try {
const product = new Product();
product.title = req.body.title;
product.description = req.body.description;
product.price = req.body.price;
await product.save();
return res.status(201).json({
status: 201
});
} catch (e) {
console.log(e);
return res.status(500).json({
message: e
});
}
}
export default {
index,
save
};
Product.js
This file defines the Mongoose schema for our product model.
import mongoose from 'mongoose';
const ProductSchema = new mongoose.Schema({
title: {
type: String,
required: true
},
description: {
type: String,
required: true
},
price: {
type: String,
required: true
}
});
export default mongoose.model('Product', ProductSchema);
products.js
This file defines the routes for our product API.
import express from 'express';
import productsController from '../controllers/ProductController.js';
const router = express.Router();
router.get('/', productsController.index);
router.post('/', productsController.save);
export default router;
app.js
This file sets up our Express application and connects to MongoDB.
import express from 'express';
import productRoutes from './routes/products.js';
import mongoose from 'mongoose';
import config from '../config.js';
import bodyParser from 'body-parser';
const connectToDB = async () => {
try {
await mongoose.connect(config.db_uri, {});
} catch (e) {
console.log(e);
process.exit(1);
}
};
const app = express();
// middleware
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use('/products', productRoutes);
await connectToDB();
export default app;
index.js
This file starts the Express application.
import app from './app.js';
import config from '../config.js';
app.listen(3000, () => {
console.log(config.app_name + ' Started on Port 3000');
});
config.js
import dotenv from 'dotenv';
import mongoose from "mongoose";
dotenv.config();
const config = {
app_name: process.env['APP_NAME'],
port: process.env['PORT'] ?? 3000,
db_uri: process.env['DB_URI'] ?? 'mongodb://localhost:27017/docker',
db_options: {
useNewUrlParser: true,
useUnifiedTopology: true
}
}
export default config;
env
APP_NAME=LearnDocker
PORT=3000
DB_URI=mongodb://127.0.0.1:27017/dockerlearn #This is a local Mongo database
Step 2: Dockerizing the Application
Now, let's create a Dockerfile to containerize our Node.js application.
Dockerfile
# Use the official Node.js image based on Alpine Linux, which is a lightweight distribution
FROM node:alpine
# Set the working directory inside the container
WORKDIR /usr/src/app
# Copy package.json and package-lock.json to the working directory
COPY ./package.json ./
COPY ./package-lock.json ./
# Install the Node.js dependencies
RUN npm install
# Copy the application source code to the working directory
COPY ./src ./src
# Copy the environment configuration file
COPY ./.env ./
# Copy the configuration file
COPY ./config.js ./
# Define the command to run the application
CMD ["npm", "start"]
Docker Compose
We'll use Docker Compose to set up our Node.js application and MongoDB as separate services.
docker-compose.yml
version: "3"
services:
# Define the MongoDB service
mongo_db:
container_name: database_container # Set a custom name for the MongoDB container
image: mongo:latest # Use the latest version of the MongoDB image
restart: always # Always restart the container if it stops or fails
volumes:
- mongo_db:/data/db # Map the mongo_db volume to /data/db inside the container to persist data
# Define the Node.js application service
app:
build: . # Build the image from the Dockerfile in the current directory
ports:
- 4000:3000 # Map port 4000 on the host to port 3000 in the container
environment:
APP_NAME: LearnDocker # Set the application name environment variable
PORT: 3000 # Set the application port environment variable
DB_URI: mongodb://mongo_db:27017/dockerlearn # Set the MongoDB URI to connect to the MongoDB container
depends_on:
- mongo_db # Ensure the mongo_db service is started before this service
volumes:
mongo_db: {} # Define a named volume for MongoDB data
Step 3: Running the Application
To run the application, follow these steps:
- Build the Docker images:
docker-compose build
- Start the services:
docker-compose up
You can test the application on Postman at the endpoint localhost:4000/products
You should now see the product management API in action.
Conclusion
Congratulations! You've successfully Dockerized a Node.js application with MongoDB. This setup provides a clean and efficient way to manage your application and its dependencies. Feel free to expand this project further and explore more features of Docker and Node.js.
Top comments (0)