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)