Quick post after smashing my head off the desk for 5 hours trying to understand YTF I couldn’t get Mongo 3.2 running in a Docker container on my Mac. Hopefully this post spares others the elastoplasts 🙂
Pitfall #1 – Mongo cannot write data to the host OSX machine
There are three factors that cause this issue:
- A lot of mongo/docker docs tell you to mount a local volume
- By default docker-machine uses the virtualbox driver to create a local VM
- Mongo uses mmap to turbo-charge access to files on disk
These facts led me (by way of this issue) to the fact that there’s been an ancient known issue on VirtualBox that basically says docker ain’t going to be able to read/write files with mmap.
So it’s pointless trying to tell mongo, via docker, to mount a local data volume, as the above bug means mongo isn’t going to be able to access it. (careful reading of the Docker Hub mongo docs may allow you to divine this, but it’s not at all obvious)
Solution – Create a data volume in the container rather than the host.
Like always once you understand the problem, the solution is simple. We can tell docker to create a data volume in the container rather than the host, as follows:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
|docker run –name my-local-mongo -v mongo-data:/data/db -p 27017:27017 -d mongo|
In my (still) early days with docker I’d come across these cli commands which contained absolutely no description of WTF all the switches are doing, so a quick breakdown:
- –name my-local-mongo – This tells docker to give the container the name “my-local-mongo” rather than generating a name like tuftybeaver
- -v mongo-data:/data/db – This is the key switch, here we tell docker to create a new data volume called mongo-data and mount it as /data/db which is the default location mongo wants to write data to
- -p 27017:27017 – Here we tell docker to bind the container port 27017 to port 27017 on the host vm, allowing us to access docker locally.
- -d – This switch tells docker to run the process detached so we’re not running interactively.
If all has gone well docker should be running your mongo container successfully. A quick docker ps will show your running container.
docker logs -f my-local-mongo – will allow you to follow the log files
Pitfall #2 – I can’t connect to mongo from localhost
This is the classic docker school boy error, that everyone makes. The first time you do this you’ll be patting yourself on the back as you type localhost:27017 into your connection string and then wonder why the hell docker isn’t found.
This is because everything is actually running on your local docker virtual machine. To find the IP of the VM enter docker-machine ls
You should see the URL listed something like this tcp://192.168.99.100:2376 You need to snarf this IP for your connection string. The easiest way to sanity check that’s it all working is bash it into your browser, eg for this example:
The mongo database should helpfully respond with:
It looks like you are trying to access MongoDB over HTTP on the native driver port.
Demonstrating that your mongo db is running and responding to idiots trying to speak to it over HTTP 🙂
Pitfall #3 – No collections are displayed in RoboMongo
This was a real head scratcher, I was pretty sure everything was working, and yet RoboMongo wasn’t showing a damn thing. This was a classic case of me Sherlock Holmes style spending 2 hours eliminating the impossible, to find whatever remains, however improbable, must be the truth
So in a turn up for the books, there was no bug in my code!! It turns out by default Mongo 3.2 uses the WiredTiger storage engine, and RoboMongo can’t parse data stored in this format.
So instead if you’re using Mongo 3.2 you should use MongoChef to connect to your db. MongoChef will show you all your lovely collections, living within your containerised Mongo.
Hope the above helps, thanks 🙂