In this blog post, we'll walk through the process of dockerizing an Express.js application with a MongoDB database. We'll create Docker images, set up a Docker Compose file, and run the application using Docker Compose.
Step 1: Set Up the Project Files
-
Create Project Structure
In the root of your project directory,
express-mongo-docker
, create the following files:
express-mongo-docker/
├── Dockerfile
├── .dockerignore
├── package.json
├── server.js
├── docker-compose.yml
└── config/
├── mongodb.js
└── config.env
- Express App Code
Add the Express server code in file index.js
const express = require('express');
const app = express();
const dotenv = require('dotenv');
const cors = require('cors');
const bodyParser = require('body-parser');
const connectDatabase = require('./config/mongoDb');
const port = process.env.PORT || 5000;
//setting up config file
dotenv.config({ path: 'config/config.env' });
// middleware
app.use(cors());
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(bodyParser.urlencoded({ extended: true }));
// handle uncaught excepion
process.on('uncaughtException', (err) => {
console.log(`ERROR: ${err.message} \n ${err.stack}`);
console.log('Shutting down the server due to uncaught exception');
process.exit(1);
});
// console.log(a); // reference error: uncaught error
// connecting to Database
connectDatabase();
// Api routes
app.get('/', (req, res) => {
res.json({
message: 'API is running',
docker: 'Docker is running'
});
});
const server = app.listen(port, () => {
console.log(
`Server is running at port ${port} in ${process.env.NODE_ENV} mode`
);
});
// Handle unhandle Promise rejection
process.on('unhandledRejection', (err) => {
console.log(`ERROR : ${err.message}`);
console.log('Shutting down the server due to unhandle promise rejection');
server.close(() => {
process.exit(1);
});
});
-
Connection To Mongodb
Connecting to Mongodb database from file
./config/mongoDb
const mongoose = require('mongoose');
const connectDatabase = async () => {
console.log('db uri', process.env.DB_LOCAL_URI);
try {
await mongoose.connect(process.env.DB_LOCAL_URI).then((con) => {
console.log(
`MongoDb database connected with host: ${con.connection.host}`
);
});
console.log('MongoDB is connected');
} catch (error) {
console.log('MongoDB connection failed', error);
}
};
module.exports = connectDatabase;
-
Add env file
Create
.env
file from file:./config/config.env
DB_LOCAL_URI=mongodb://<your-username>:<your-password>@mongo:27017/test-app?authSource=admin
MONGO_INITDB_ROOT_USERNAME=<your-username>
MONGO_INITDB_ROOT_PASSWORD=<your-password>
Step 2. Creating Docker Images
First, let's create a Dockerfile
for our Express application:
# Use the official Node.js image as the base image
FROM node:18-alpine
# Set the working directory
WORKDIR /app
COPY package*.json ./
RUN npm install
# Copy the rest of the application code
COPY . .
# Expose the port the app runs on
EXPOSE 5000
# Command to run the application
CMD ["npm", "run", "dev"]
Next, create a .dockerignore
file to exclude unnecessary files and directories:
node_modules
npm-debug.log
.git
.gitignore
.dockerignore
Dockerfile
docker-compose.yml
Modify package.json
scripts with Express and Mongoose:
"scripts": {
"start": "node index.js",
"dev": "SET NODE_ENV=DEVELOPMENT& nodemon -L index.js --host",
"prod": "SET NODE_ENV=PRODUCTION& nodemon index.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
Step 3. Creating a Docker Compose File
Now, let's create a docker-compose.yml
file to define and run our multi-container Docker application:
version: '3.8'
services:
# MongoDB service
mongo:
image: mongo:latest
container_name: mongo-container
ports:
- '27017:27017'
volumes:
- mongotestData:/data/db
networks:
- app-network
# For environment variable it'll be beter if you use env file path here
environment:
- MONGO_INITDB_ROOT_USERNAME=<your-username>
- MONGO_INITDB_ROOT_PASSWORD=<your-password>
# Backend service
backend:
build:
context: .
dockerfile: Dockerfile
image: mern-backend-image
container_name: mern-backend-container
ports:
- '5000:5000'
depends_on:
- mongo
env_file:
- ./config/config.env
stdin_open: true
volumes:
- .:/app
- /app/node_modules
networks:
- app-network
# Define volumes
volumes:
mongotestData:
# Define networks
networks:
app-network:
This Docker Compose file defines two services:
- backend: Our Express application
- mongo: MongoDB database
The backend service builds from our Dockerfile
, maps port 5000, and depends on the mongo service. We also set an environment variable for the MongoDB connection string.
The mongo service uses the official MongoDB image, maps port 27017, and uses a named volume to persist data.( you can also bind local file path to store mongo data)
Step 4. Running the Application
To run the application using Docker Compose, follow these steps:
- Open a terminal and navigate to your project directory.
- Build and start the containers:
docker-compose up --build
- Your application should now be running. Access it at http://localhost:5000.
- To stop the application, use:
docker-compose down
Congratulations !!!
We've successfully dockerized an Express application with a MongoDB database. This setup allows for easy deployment and scaling of your application. Remember to adjust the configuration as needed for your specific project requirements.
Happy coding!
Top comments (0)