Set up MongoDB Docker image

By: (plus.google.com) +David Herron; Date: March 4, 2018

Tags: Docker » Docker MAMP

MongoDB, as one of the popular NoSQL databases, is part of many software development projects. Hence, one must know how to configure and setup MongoDB in a Docker environment.

Quick start

Docker's MongoDB image ( (hub.docker.com) https://hub.docker.com/_/mongo/) is fairly easy to setup and deploy.

For a quick win, let's start up a MongoDB container, run a mongo client, and generally poke around to see what's there.

$ docker pull mongo
Unable to find image 'mongo:latest' locally
latest: Pulling from library/mongo
d2ca7eff5948: Pull complete 
ebb958661291: Pull complete 
cdfa71d101a9: Pull complete 
88a286579fc2: Pull complete 
9441b8e1ae36: Pull complete 
0e6fe40bb4bd: Pull complete 
fca9be9954eb: Pull complete 
9d3de1a5bb82: Pull complete 
2e423513a19e: Pull complete 
2fcd12f78f7c: Pull complete 
Digest: sha256:05fd4fd3710a84dcf12e5880a5fc225a245792d2d9b6156722c5f4c0fab74d86
Status: Downloaded newer image for mongo:latest
$ docker run --name some-mongo  mongo
2018-03-05T06:23:52.002+0000 I CONTROL  [initandlisten] MongoDB starting : pid=1 port=27017 dbpath=/data/db 64-bit host=84e5705ac41f
2018-03-05T06:23:52.002+0000 I CONTROL  [initandlisten] db version v3.6.3
...

This starts the MongoDB container, which you can see here

$ docker ps -a
CONTAINER ID        IMAGE                          COMMAND                  CREATED             STATUS                     PORTS                    NAMES
84e5705ac41f        mongo                          "docker-entrypoint.s…"   4 minutes ago       Up 4 minutes               27017/tcp                some-mongo

A TCP port, 27017, is exposed but is not publicly visible. The Docker Hub page says this allows for easy linking between containers as that's the standard MongoDB port.

It's not recommended, but if you did want to publicly expose this port add -p 27017:27017 to the docker run command.

$ docker exec -it some-mongo bash
root@84e5705ac41f:/# mongo
MongoDB shell version v3.6.3
connecting to: mongodb://127.0.0.1:27017
MongoDB server version: 3.6.3
Welcome to the MongoDB shell.
For interactive help, type "help".

We can get into the container, and run the Mongo client as so. Notice the client connects to that TCP port on localhost.

> db.foo.find()
> db.foo.save({ a: 1});
WriteResult({ "nInserted" : 1 })
> db.foo.find()
{ "_id" : ObjectId("5a9ce2ec3f7f33d53a61b357"), "a" : 1 }

And we can run a couple MongoDB commands.

Connecting to MongoDB container from another

The MongoDB container would be installed alongside another container (or three) running an application that uses the MongoDB container. Therefore we need to see how to get one container to talk with the MongoDB container. To do that we'll run a second MongoDB container, but use only the MongoDB client program to connect to the MongoDB instance in the other container.

$ docker network create mnet
d7d0c678626407eb2b9de733d1ec7ef4243833cc8f64f59a77218e5bd1be3b8f

First, we need a Docker bridge network. Bridge networks are used to connect containers together. In the Docker universe you'll find old documentation suggesting to use the --link option to connect two containers together. In the Docker documentation today, you'll see --link described as a deprecated feature and that we're supposed to use bridge networks instead.

A Docker bridge network is a virtual subnet you create within your computer.

$ docker network inspect mnet
...
            "Config": [
                {
                    "Subnet": "172.18.0.0/16",
                    "Gateway": "172.18.0.1"
                }
            ]
...
        "Containers": {
            "b142745a2ba9f91fbbbcde6531505baa1e0cb98c5f7a6192fb6255e910f38aca": {
                "Name": "some-mongo",
                "EndpointID": "09071f4634dca571eb737f72a1413d757d97680b49bccd906999d231a82afcc5",
                "MacAddress": "02:42:ac:12:00:02",
                "IPv4Address": "172.18.0.2/16",
                "IPv6Address": ""
            },
            "ddc3ebc4cf9e7d735ed6c8cd8611f441723639c37bdaf556f7a04abff69ca0f2": {
                "Name": "sharp_bohr",
                "EndpointID": "af496257345b0a1724bc9082bded48b09cf4d2e3c4cf331dcc0270b747a1a93c",
                "MacAddress": "02:42:ac:12:00:03",
                "IPv4Address": "172.18.0.3/16",
                "IPv6Address": ""
            }
        },

You can inspect a bridge network as so. First we see the subnet is assigned the 172.18.0.0 network, and second we see that two containers are connected to the network. I haven't shown you that connection yet, but you see that each container has its own IP address.

Docker has a built-in DNS server, and each container has a host name determined by its container name. Meaning that from a container on a given subnet, your software can attach to software in another container on that bridge network using the container name as the host name.

$ docker rm some-mongo
$ docker run --name some-mongo --net mnet  mongo
2018-03-05T06:33:59.202+0000 I CONTROL  [initandlisten] MongoDB starting : pid=1 port=27017 dbpath=/data/db 64-bit host=b142745a2ba9
2018-03-05T06:33:59.202+0000 I CONTROL  [initandlisten] db version v3.6.3

We delete the old some-mongo instance, and start a new one, this time connecting it to mnet.

Then in another window we can run this:

$ docker run -it --rm --net mnet mongo sh -c 'exec mongo --host some-mongo'
MongoDB shell version v3.6.3
connecting to: mongodb://some-mongo:27017/
MongoDB server version: 3.6.3
Welcome to the MongoDB shell.
For interactive help, type "help".
...
> db.foo.find()
> db.foo.save({ a: 1});
WriteResult({ "nInserted" : 1 })
> db.foo.find()
{ "_id" : ObjectId("5a9ce5a60c4a3cbeda2ca453"), "a" : 1 }
> 

Run this way, we start a Docker instance with interactive terminal session (the -it option), attached to mnet, using the mongo image. This time we run a shell command mongo --host some-mongo, and that starts a Mongo client connecting to the MongoDB server in the some-mongo container. And we can prove the database works by running the test commands.

$ docker ps -a
CONTAINER ID        IMAGE                          COMMAND                  CREATED             STATUS                     PORTS                    NAMES
ddc3ebc4cf9e        mongo                          "docker-entrypoint.s…"   10 minutes ago      Up 10 minutes              27017/tcp                sharp_bohr
b142745a2ba9        mongo                          "docker-entrypoint.s…"   13 minutes ago      Up 13 minutes              27017/tcp                some-mongo

By the way this is an expensive way to get a MongoDB client running, because it also starts up a second MongoDB server. But, it proved that indeed we can easily have a Mongo client of some kind connect to a MongoDB server in another container.

Configuration file

root@ddc3ebc4cf9e:/# ls -l /etc/mongod.conf.orig 
-rw-r--r-- 1 root root 626 Feb 22 20:24 /etc/mongod.conf.orig

There is a default MongoDB configuration file in the container, but the file is not enabled.

Documentation on the MongoDB configuration file: (docs.mongodb.com) https://docs.mongodb.com/manual/reference/configuration-options/

One could mount a configuration file into the container by adding this option to the command line: -v ./mongod.conf:/etc/mongod.conf

Or, in a docker-compose.yml:

db-mongo:
  image: mongo:3.6-jessie
  container_name: db-mongo
  networks:
    - _network name_
  volumes:
    - ./mongod.conf:/etc/mongod.conf

The documentation suggests that using the configuration file then requires that mongod be launched as mongod --config /etc/mongod.conf. To do this requires overriding the CMD command in the Dockerfile. The docker run command doesn't allow overriding the CMD command, but you can do it from docker-compose.yml

db-mongo:
  image: mongo:3.6-jessie
  container_name: db-mongo
  networks:
    - _network name_
  volumes:
    - ./mongod.conf:/etc/mongod.conf
  command: mongod --config /etc/mongod.conf

That isn't tested, but this documentation suggests that's what would work: (docs.docker.com) https://docs.docker.com/compose/compose-file/#command

Persisting the database

So far the database used by the MongoDB instance has lived solely within the container. Therefore the database was deleted as soon as the container was deleted.

Docker container lifecycle's are incompatible with database lifecycles. We expect a database to potentially have a useable lifetime measuring in decades, while a container's lifetime can be measured in minutes. Therefore we need to store the MongoDB database outside the container.

Fortunately that's simple, and simply requires using an option we just saw.

$ docker rm some-mongo
$ docker run --name some-mongo --net mnet -v ./data-directory:/data/db  mongo

Or

db-mongo:
  image: mongo:3.6-jessie
  container_name: db-mongo
  networks:
    - _network name_
  volumes:
    - ./db-notes-mongo:/data/db
    - ./mongod.conf:/etc/mongod.conf
  command: mongod --config /etc/mongod.conf

Mongo Express

This is a web-based MongoDB administrative service. (hub.docker.com) https://hub.docker.com/_/mongo-express/

This is rather easy to set up:

$ docker run -it --rm  \
   --name mongo-express \
   --net mnet -p 8081:8081 \
   -e ME_CONFIG_OPTIONS_EDITORTHEME="ambiance" \
   -e ME_CONFIG_BASICAUTH_USERNAME="user" \
   -e ME_CONFIG_BASICAUTH_PASSWORD="fairly long password" \
   -e ME_CONFIG_MONGODB_SERVER="some-mongo" \
   mongo-express
Mongo Express in action

As a Docker Compose setup, it might look like this:

db-mongo:
  image: mongo:3.6-jessie
  container_name: db-mongo
  networks:
    - _network name_
  volumes:
    - ./db-notes-mongo:/data/db
    - ./mongod.conf:/etc/mongod.conf
  command: mongod --config /etc/mongod.conf

db-mongo-admin:
    image: mongo-express
    container_name: db-mongo-admin
    networks:
        - _network name_
    environment:
        ME_CONFIG_OPTIONS_EDITORTHEME: ambiance
        ME_CONFIG_BASICAUTH_USERNAME: user
        ME_CONFIG_BASICAUTH_PASSWORD: fairlylongpassword
        ME_CONFIG_MONGODB_SERVER: some-mongo

This is untested but a straight-forward translation of the command-line.

« YouTube video recommendation algorithm reportedly preferences conspiracy videos Raspberry Pi board and accessories buying guide. »
2016 Election Acer C720 Ad block AkashaCMS Amazon Amazon Kindle Amazon Web Services America Amiga and Jon Pertwee Android Anti-Fascism AntiVirus Software Apple Apple Hardware History Apple iPhone Apple iPhone Hardware April 1st Arduino ARM Compilation Artificial Intelligence Astronomy Astrophotography Asynchronous Programming Authoritarianism Automated Social Posting AWS DynamoDB AWS Lambda Ayo.JS Bells Law Big Brother Big Finish Bitcoin Mining Black Holes Blade Runner Blockchain Blogger Blogging Books Botnets Cassette Tapes Cellphones China China Manufacturing Christopher Eccleston Chrome Chrome Apps Chromebook Chromebox ChromeOS CIA CitiCards Citizen Journalism Civil Liberties Clinton Cluster Computing Command Line Tools Comment Systems Computer Accessories Computer Hardware Computer Repair Computers Cross Compilation Crouton Cryptocurrency Curiosity Rover Currencies Cyber Security Cybermen Daleks Darth Vader Data backup Data Storage Database Database Backup Databases David Tenant DDoS Botnet Detect Adblocker Developers Editors Digital Photography Diskless Booting Disqus DIY DIY Repair DNP3 Do it yourself Docker Docker MAMP Docker Swarm Doctor Who Doctor Who Paradox Doctor Who Review Drobo Drupal Drupal Themes DVD E-Books E-Readers Early Computers Election Hacks Electric Bicycles Electric Vehicles Electron Emdebian Encabulators Energy Efficiency Enterprise Node EPUB ESP8266 Ethical Curation Eurovision Event Driven Asynchronous Express Face Recognition Facebook Fake News Fedora VirtualBox File transfer without iTunes FireFly Flickr Fraud Freedom of Speech Front-end Development Gallifrey git Github GitKraken Gitlab GMAIL Google Google Chrome Google Gnome Google+ Government Spying Great Britain Heat Loss Hibernate Hoax Science Home Automation HTTP Security HTTPS Human ID I2C Protocol Image Analysis Image Conversion Image Processing ImageMagick In-memory Computing InfluxDB Infrared Thermometers Insulation Internet Internet Advertising Internet Law Internet of Things Internet Policy Internet Privacy iOS Devices iPad iPhone iPhone hacking Iron Man iTunes Java JavaScript JavaScript Injection JDBC John Simms Journalism Joyent Kaspersky Labs Kindle Kindle Marketplace Lets Encrypt LibreOffice Linux Linux Hints Linux Single Board Computers Logging Mac Mini Mac OS Mac OS X Machine Learning Machine Readable ID macOS MacOS X setup Make Money Online March For Our Lives MariaDB Mars Mass Violence Matt Lucas MEADS Anti-Missile Mercurial MERN Stack Michele Gomez Micro Apartments Microsoft Military AI Military Hardware Minification Minimized CSS Minimized HTML Minimized JavaScript Missy Mobile Applications Mobile Computers MODBUS Mondas Monetary System MongoDB Mongoose Monty Python MQTT Music Player Music Streaming MySQL NanoPi Nardole NASA Net Neutrality Network Attached Storage Node Web Development Node.js Node.js Database Node.js Testing Node.JS Web Development Node.x North Korea npm NVIDIA NY Times Online advertising Online Community Online Fraud Online Journalism Online Photography Online Video Open Media Vault Open Source Open Source Governance Open Source Licenses Open Source Software OpenAPI OpenVPN Palmtop PDA Patrick Troughton Paywalls Personal Flight Peter Capaldi Phishing Photography PHP Plex Plex Media Server Political Protest Postal Service Power Control Privacy Production use Public Violence Raspberry Pi Raspberry Pi 3 Raspberry Pi Zero ReactJS Recaptcha Recycling Refurbished Computers Remote Desktop Removable Storage Republicans Retro Computing Retro-Technology Reviews RFID Right to Repair River Song Robotics Rocket Ships RSS News Readers rsync Russia Russia Troll Factory Russian Hacking Rust SCADA Scheme Science Fiction SD Cards Search Engine Ranking Season 1 Season 10 Season 11 Security Security Cameras Server-side JavaScript Serverless Framework Servers Shell Scripts Silence Simsimi Skype SmugMug Social Media Social Media Warfare Social Network Management Social Networks Software Development Space Flight Space Ship Reuse Space Ships SpaceX Spear Phishing Spring Spring Boot Spy Satellites SQLite3 SSD Drives SSD upgrade SSH SSH Key SSL Stand For Truth Strange Parts Swagger Synchronizing Files Telescopes Terrorism The Cybermen The Daleks The Master Time-Series Database Tom Baker Torchwood Total Information Awareness Trump Trump Administration Trump Campaign Twitter Ubuntu Udemy UDOO US Department of Defense Virtual Private Networks VirtualBox VLC VNC VOIP Vue.js Web Applications Web Developer Resources Web Development Web Development Tools Web Marketing Webpack Website Advertising Weeping Angels WhatsApp William Hartnell Window Insulation Windows Windows Alternatives Wordpress World Wide Web Yahoo YouTube YouTube Monetization