How to dump & restore a MongoDB database from a docker container

MongoDB is an interesting tool. Dead simple to create and modify records (or, "documents") that are basically pure JSON goodness, juxtaposed with tools or commands that at times make you scratch your head in utter confusion and/or disbelief.
--uri
flag when using a connection URL, another, more streamlined method that lets you directly pipe the database dump in and out of containers, and I have also included updates for MongoDB's newer requirement to use --nsInclude
with the restore command instead of the now considered to be deprecated --db
flag. The original method that relies on multiple (one per collection) json files that have to be copied in-and-out of containers is preserved too, as there are practical use-cases for that option.
To keep me from having to re-figure this out a few more times, here's a quick how-to on how to back up and restore a MongoDB database, all collections included. The process is unfortunately a little less elegant as compared to PostgreSQL or MariaDB, but hopefully you don't have to do it too often.


Create a database dump
We can use the following command to create a dump of your entire database, all collections included. This assumes your source database is (also) in a container, but the command should be roughly identical if you your source database is directly installed on your (virtual) machine.
Method one: Single file dump directly to your host machine
In more recent versions of mongodump
the --archive
option is available, which outputs everything to a single file or stdout. We can use this to directly pipe everything we need out of the container, directly into a file on our host machine β or indeed to any machine from where we are running these container commands. To do this, adapt and run the following command:
β― docker exec -i <container_name> /usr/bin/mongodump --username <username> --password <password> --authenticationDatabase admin --db <database_name> --archive > ~/Downloads/mongodb.dump
Or if you are using a connection URL, it would look something like this:
β― docker exec -i <container_name> /usr/bin/mongodump --uri "<your mongodb+srv link>" --archive > ~/Downloads/mongodb.dump
~/Downloads/mongodb.dump
file will be created on the host machine, or at least on whatever machine you are running these commands from, not within the container.That's it, we finally have our files. Now we can basically do the exact opposite in our new container. Let's do that next.
Method two: Mongodump's older/original individual collection dump files
By default a mongodump
export generates individual files, one for reach collection. If this is the method you'd like to use, we won't be able to rely on shell piping to get the files directly out of our database container. For this we can use an intermediary step of storing the dumped database files in a directory within the container, which we can then copy out to our host using docker cp
β or if you already have a host directory mounted as a volume, you can use that and skip the docker cp
step altogether of course.
Here's an example that dumps your entire database to the /dump
directory within your container:
β― docker exec -i <container_name> /usr/bin/mongodump --username <username> --password <password> --authenticationDatabase admin --db <database_name> --out /dump
Or if you use a mongodb+srv
or similar URL to connect to your database instead:
β― docker exec -i <container_name> /usr/bin/mongodump --uri "<your mongodb+srv link>" --out /dump
Now that we have the resulting files we can copy them out of the container and to our host. Here I am using the ~/Downloads
destination as an example:
β― docker cp <container_name>:/dump ~/Downloads/dump
Restoring
Now that we have the database dump files ready, let's go ahead and import (or, restore) them. Whether this is a fresh and new container or you're restoring a backup, the process is the same.
Ensure a user is created first
Before we continue, we should make sure we have a database user account ready with read and write access to the database you want to restore into. If you don't have one already, let's go ahead and create one now.
You can run the following in your mongodb (cli) client of choice to create a new user. A prompt will appear after running this command in which you can specify the user's password.
use admin
db.createUser({
user: "username",
pwd: passwordPrompt(),
roles:[{role: "readWrite" , db:"<database_name>"}]})
Why "use admin"
One part that seems somewhat confusing and that threw me off previously is that by default when you try to connect to a MongoDB server it expects that admin
is the database in which the user exists β even if said user has no access permissions for this database.
There are ways to change this behavior, but that is outside the scope of this guide. As you specify user roles that specify which database(s) the user has actual access to, even though the user might exist in the admin
database, it doesn't actually have any permissions to do anything there, so it seems to not be that big of a deal.
Slightly confusing, but that seems to be the Mongo way. Anyway, let's continue.
Method one: Single file dump directly from your host machine
If you used the --archive
method as described above, then we can use the same approach to import the dump by directly piping it into the container, like so:
β― docker exec -i <container_name> /usr/bin/mongorestore --username <username> --password <password> --authenticationDatabase admin --nsInclude="<database_name>.*" --archive < ~/Downloads/mongodb.dump
Or if you're using a URL to connect to your destination database:
β― docker exec -i <container_name> /usr/bin/mongorestore --uri "<your mongodb+srv link>" --archive < ~/Downloads/mongodb.dump
--db <database_name>
flag in the above restore commands, but these have since been marked as deprecated and --nsInclude
has be used instead. With it you provide the database name along with all names of the individual collections you wish to import, or a wildcard for all collections. It'll be convenient to wrap the entire value in quotation marks. If you don't you should at least escape the wildcard symbol (
\*
) if used, to ensure it is passed through to the command, and not read by bash
as an actual wildcard.Method two: Mongodump's older/original individual collection dump files
Copy files into the container
If you used this method to create a database dump and have multiple individual files, then we should first make the dumped database files available within the docker container by copying them into the container:
β― docker cp ~/Downloads/dump <container_name>:/dump
Restore
Now that the dump files are available within the container, run the following command to have everything be imported.
β― docker exec -i <container_name> /usr/bin/mongorestore --username <username> --password <password> --authenticationDatabase admin --nsInclude=<database_name>.\* /dump/<database_name>
Or if you use a URL to connect to your destination database:
β― docker exec -i <container_name> /usr/bin/mongorestore --uri "<your mongodb+srv link>" /dump/<database_name>
mongodump
creates a databasae dump, by default all files are placed in a sub-directory named after the database. That's why in the above example the path points to /dump/<database_name>
. You can leave this part off if you have a different folder structure.Cleaning up afterwards
If you'd like to delete the dump files from the container after importing, you can open a shell session within the docker container like so:
β― docker exec -it <container_name> /bin/bash
Now you can delete these files by running something like rm -rf /dump
.
That's it! While not as straight-forward as with some other database solutions, with these steps it's at least not too challenging to migrate or clone your MongoDB database.
I hope this guide was able to help you. I certainly will be re-visiting this myself as I inevitably forget the exact steps necessary.
Thank you.