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

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.

πŸ“£
2023/03/14 Update: I have updated the guide below to include mentions of using the --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.

How to dump & restore a PostgreSQL database from a docker container
Sometimes you need to quickly dump and restore a PostgreSQL database, but what’s the easiest way to do this when your database is in a Docker container? How to dump & restore a MariaDB/MySQL database from a docker containerIn the same vein as my previous post on dumping and
How to dump & restore a MariaDB/MySQL database from a docker container
In the same vein as my previous post on dumping and restoring your PostgreSQL database, here are mostly copy/paste-able commands for when you’re using a MariaDB or MySQL database. How to dump & restore a PostgreSQL database from a docker containerSometimes you need to quickly dump and restore a

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
πŸ’‘
Keep in mind that in these examples, the ~/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
πŸ’‘
My guide originally used the --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>
πŸ’‘
When 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.