Docker and Node.js: Simplifying Development with MongoDB
The development and deployment of applications can be greatly simplified with Docker. Docker containers offer several advantages for developers:
- Consistent environments: You can select the languages and dependencies you want without worrying about system conflicts.
- Isolated environments: This makes debugging and onboarding new team members easier.
- Portability: The code can be packaged and easily shared.
In this article, I will show you how to set up a development environment for a Node.js application using Docker. We will create two containers: one for the Node.js application and another for the MongoDB database. Among other things, you will:
- Synchronize the application code with the code in the container to facilitate changes during development.
- Ensure that changes are applied without restarting the application.
- Create a password-protected database that is persistent.
By the end of this tutorial, a shark information application will be running in Docker containers.
Prerequisites
To follow this tutorial, you will need:
- A development server running Ubuntu 18.04 and a non-root user with sudo privileges.
- Docker and Docker Compose installed.
Step 1 – Clone the project and modify dependencies
The first step is to clone the sample code and modify the package.json
file. We will add nodemon
to the development dependencies so the application automatically restarts when you make changes.
First, clone the repository:
git clone https://github.com/do-community/nodejs-mongo-mongoose.git node_project
cd node_project
Open the package.json
file:
nano package.json
Add nodemon
under the dependencies:
"devDependencies": {
"nodemon": "^1.18.10"
}
Save and close the file.
Step 2 – Adapt the application for containers
Now we will modify the code so that it works better with containers. We will use Node.js’s process.env
property to dynamically work with environment variables.
Open app.js
and modify the port as follows:
const port = process.env.PORT || 8080;
app.listen(port, function () {
console.log(`App is listening on port ${port}`);
});
Also, modify the database connection in db.js
to avoid hardcoding sensitive information:
const {
MONGO_USERNAME,
MONGO_PASSWORD,
MONGO_HOSTNAME,
MONGO_PORT,
MONGO_DB
} = process.env;
Create a .env
file with the necessary environment variables:
nano .env
And add the following content (with your values):
MONGO_USERNAME=username
MONGO_PASSWORD=password
MONGO_PORT=27017
MONGO_DB=sharkinfo
Ensure that .env
is included in both .gitignore
and .dockerignore
to prevent sensitive data from being uploaded.
Step 3 – Modify database connection settings
Add additional options in db.js
to handle connection failures:
const options = {
useNewUrlParser: true,
reconnectTries: Number.MAX_VALUE,
reconnectInterval: 500,
connectTimeoutMS: 10000,
};
mongoose.connect(url, options).then(() => {
console.log('MongoDB is connected');
}).catch(err => {
console.log(err);
});
Step 4 – Define services with Docker Compose
Now we create the docker-compose.yml
file to define the services. The first service is for the Node.js application:
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=db
- MONGO_PORT=$MONGO_PORT
- MONGO_DB=$MONGO_DB
ports:
- "80:8080"
volumes:
- .:/home/node/app
- node_modules:/home/node/app/node_modules
networks:
- app-network
command: ./wait-for.sh db:27017 -- /home/node/app/node_modules/.bin/nodemon app.js
The second service is for the MongoDB database:
db:
image: mongo:4.1.8-xenial
container_name: db
restart: unless-stopped
env_file: .env
environment:
- MONGO_INITDB_ROOT_USERNAME=$MONGO_USERNAME
- MONGO_INITDB_ROOT_PASSWORD=$MONGO_PASSWORD
volumes:
- dbdata:/data/db
networks:
- app-network
Finally, add the network and volume definitions:
networks:
app-network:
driver: bridge
volumes:
dbdata:
node_modules:
Step 5 – Test the application
Start the application with:
docker-compose up -d
Check the logs with:
docker-compose logs
If everything runs correctly, you should be able to see your application on your server’s URL.
Conclusion
By following this guide, you have learned how to develop and run a Node.js application with MongoDB in a Docker environment. Docker makes it easier to isolate your environment, secure your data, and seamlessly share your applications.