Roman Pietrzak aka Yosh
Mongo in Docker(compose) - installation in few steps 2019
Last update: 2019-11-19


Intro

I needed to quickly setup MongoDB on my local Linux machine. I wanted:
  • to make it quick
    I needed Mongo as a dependency to Node.js application I'm helping with. I didn't really need the Mongo itself for anything - only to fill the dependency for node app.
  • to containerize it
    I didn't want to instal it "globally on the machine". I had to start MongoDB now, use it for development for a while and then stop it and have no trace of that instance of Mongo if no longer needed.
  • Peristency between runs
    The DB content should be persistent between runs.

TLDR

TLDR: It's very simple in 2019 to reach those goals - just use Docker, download Mongo image, configure it, run the image. Done!
If you know how to do it without digging too much in external resources, then stop reading this now.
This article explains how to do just that: use Docker Compose to run Mongo locally.

Docker Compose vs pure Docker

I don't like the imperative "command line Docker" approach to starting/configuring docker images if they are needed for anything more serious than 2 minutes work. When you do that, you end up with colosal commands, where editing is hard and it's also hard to keep trace of changes in them when testing.
I like using nice YAML config for Docker Compose and then just running "docker-compose up" to run it.

Prerequisites

  • Make sure you know what Docker is and what Docker compose is for.
  • Install docker and docker compose on your machine.
  • I'm using Ubuntu 18.04 LTS as a host for testing of content in this article.

Config for Docker Compose

Image

Let's get the newest image available at the moment: mongo:3.6.15-xenial
  • Why not just :latest ?
    As a general rule, I don't do :latest (like in mongo:latest) in those "persistent" configs.
    • You don't know what you're installing: what exact underlying platform ?
    • You don't have a control over time: when you wrote this config everything was fine. 2 days later you start work again and start your dockerized Mongo and everything crashes. After debugging you find that ":latest" was changed in a meanwhile, so your setup is not working anymore (API changed ? migration failed ? etc.)
    • You can't really share that config and be sure what's gonna happen for somebody else using your config - another version may be downloaded. It's like ignoring "package-lock" in Node.js projects.
  • How to find what versions are available ?
    On Docker Hub. Go to Docker Hub and search for Mongo.

Volumes

Let's expose 3 different volumes:
  • /etc/mongod.conf
    So we can easily configure mongo from outside of the container
  • /var/log/mongodb/
    So we can look at the logs of the Mongo itself if stuff goes wrong
  • /var/lib/mongodb
    The persistency: here mongoDB will keep the DB data.
    If you don't do that, then mongo can keep data inside of the container itself. But when you stop/restart the container the data will dissapear.

Exposed ports

Expose port 27017 - the default mongo server port

Full config file

docker-compose.yml should look like this:
db-mongo:
  image: mongo:3.6.15-xenial
  container_name: db-mongo
  volumes:
    - ./mongod.conf:/etc/mongod.conf
    - ./logs:/var/log/mongodb/
    - ./db:/var/lib/mongodb
  command: mongod --config /etc/mongod.conf
  ports:
    - 27017:27017

Config for Mongo

Find a default Mongod config, either by extracting it from Docker image (use "docker save") or by looking at Mongo website.
Then edit:
  • paths for database and logs
    those obviously should match paths in "volumes" section in "docker-compose.yml"
  • network binding to 0.0.0.0
    starting from MongoDB 3.6 the default bindIp is localhost (127.0.0.1), so we change it to 0.0.0.0
    • Important security warning:
      bindIp configured to localhost will not allow connections from outside of you docker image, so we change this to 0.0.0.0, however think twice about what you doing here in context of security.
      This config *MAY* be good for a local dev environment, but setting bindIp to 0.0.0.0 without further steps is insecure. Exposing your mongo to public network or cloud env without making connections secure is a big no no.
      Read Security section in mongo doc and find some additional advice if needed.
Example mongod.conf:
# mongod.conf

# for documentation of all options, see:
#   http://docs.mongodb.org/manual/reference/configuration-options/

# Where and how to store data.
storage:
  dbPath: /var/lib/mongodb
  journal:
    enabled: true

# where to write logging data.
systemLog:
  destination: file
  logAppend: true
  path: /var/log/mongodb/mongod.log

# network interfaces
net:
  port: 27017
  bindIp: 0.0.0.0

# how the process runs
processManagement:
  timeZoneInfo: /usr/share/zoneinfo

Run, stop, observe the docker container

All the commands below, should be invoked in the directory of your docker-compose.yml file.
Start it:
sudo docker-compose up
When you start it for the first time, docker will pull all the layers of Mongo image.
Also when you start it for the first time, docker will create all volume directories. However, mongo will complain about access rights to those directories - this is covered below in separate section.

Start it in detached mode:
sudo docker-compose up -d

Observe the containter logs:
sudo docker-compose logs -f
Note that "docker logs" are not the same as "Mongo logs". To see the mongo logs, observe your local ./logs/mongod.log file - you have mounted the ./logs directory as logs volume for a container:
tail -f ./logs/mongod.log

Stop it (when running in detached mode):
sudo docker-compose down

Last few bits - file permissions

When you do
sudo docker-compose up
for the first time, probably you'll see something like:
Failed global initialization: FileNotOpen: Failed to open "/var/log/mongodb/mongod.log"
You have to change the permissions, the easiest way:
sudo chmod 777 logs

Then, you may see container exiting (failing) right after initialization with something like that:
$ sudo docker-compose up
Starting db-mongo ... done
Attaching to db-mongo
db-mongo exited with code 14
You can take a look to mongo logs to see what's happening:
tail -f -n 100 ./logs/mongod.log
If there is something like:
exception in initAndListen: IllegalOperation: Attempted to create a lock file on a read-only directory: /var/lib/mongodb, terminating
in the middle of the log, then you have to change permissions on you data directory:
sudo chmod 777 db

Hopefully, that's it, all done... you have your MongoDB running by now. Your application code can now connect to Mongo on port 27017.

Troubleshooting, questions, updates etc.

Please let me know if you have some updates to this article - I'm happy to include them here.
Feel free to contact me if you have any questions or need help.
If you need commercial help - I provide consultancy services.

Thanks to

Big thanks to jeanlucpikachu for comments about mongo binding to 0.0.0.0 in context of security.
JavaScript failed !
So this is static version of this website.
This website works a lot better in JavaScript enabled browser.
Please enable JavaScript.