Applies to: the official mongo Docker image, tested with mongo:8 (MongoDB 8.3.11, mongosh 2.11.1, database tools 100.18.0) on Docker Engine 29.1.3 (arm64)
To run MongoDB in Docker, start the official mongo image with a root user, a named volume for the data and the port published only on the server itself:
docker volume create mongo-data docker run -d --name mongo --restart unless-stopped \ -p 127.0.0.1:27017:27017 \ -v mongo-data:/data/db \ -e MONGO_INITDB_ROOT_USERNAME=admin \ -e MONGO_INITDB_ROOT_PASSWORD='S3cret-Pass' \ mongo:8
Then check that it answers:
$ docker exec mongo mongosh --quiet -u admin -p 'S3cret-Pass' --eval 'db.runCommand({ping:1})'
{ ok: 1 }
The image includes the mongosh shell and the database tools (mongodump, mongorestore), so you don’t need to install anything else on the server. If Docker isn’t installed yet, see how to install Docker on Debian and Ubuntu.
Which tag to use
At the time of writing, mongo:8 and mongo:latest point to MongoDB 8.3.11, mongo:8.0 to 8.0.32 and mongo:7 to 7.0.43. Pin the version your application supports (for example mongo:8.0) so that pulling a new image never jumps to another release series by surprise. The image is available for amd64 and arm64.
Three things to know before you start
- Without the two
MONGO_INITDB_ROOT_variables there is no password at all. The image documentation says the default configuration “requires no authentication for access”. In our test, a container started without them listed its databases to anyone who connected. - Publish the port on 127.0.0.1.
-p 27017:27017alone publishes it on every address (docker portshowed0.0.0.0:27017and[::]:27017). Docker also notes that traffic to published ports is diverted before it reaches UFW rules, so a UFW firewall won’t protect it. Applications in containers on the same user-defined network (for example, services in the same Compose project) reach MongoDB by its name without any published port. On Docker’s default network the name doesn’t resolve: we gotgetaddrinfo ENOTFOUND. - The variables only work on the first start. They create the root user when
/data/dbis empty. We recreated the container on the same volume with a newMONGO_INITDB_ROOT_PASSWORD: the new password failed withMongoServerError: Authentication failed.and the old one still worked. Change passwords inside MongoDB instead.
Create a user for your application
Don’t let the application use the root account. Create a user that can only read and write its own database:
$ docker exec mongo mongosh --quiet -u admin -p 'S3cret-Pass' --eval \
'db.getSiblingDB("shop").createUser({user:"shopapp", pwd:"App-Pass-1", roles:[{role:"readWrite", db:"shop"}]})'
{ ok: 1 }
The application then connects with:
mongodb://shopapp:App-Pass-1@127.0.0.1:27017/shop
A user is stored in the database where you created it. The root user lives in admin, so when you connect as root to another database, add ?authSource=admin. Without it we got Authentication failed. even with the right password:
mongodb://admin:S3cret-Pass@127.0.0.1:27017/shop?authSource=admin
The same with Docker Compose
This keeps the root password in a file instead of the command line, using the image’s _FILE variant, and adds a health check:
services:
mongo:
image: mongo:8
restart: unless-stopped
ports:
- "127.0.0.1:27017:27017"
environment:
MONGO_INITDB_ROOT_USERNAME: admin
MONGO_INITDB_ROOT_PASSWORD_FILE: /run/secrets/mongo_root_password
secrets:
- mongo_root_password
volumes:
- mongo-data:/data/db
healthcheck:
test: ["CMD", "mongosh", "--quiet", "--eval", "db.adminCommand('ping').ok"]
interval: 10s
timeout: 5s
retries: 5
volumes:
mongo-data:
secrets:
mongo_root_password:
file: ./mongo_root_password.txt
Put the password in mongo_root_password.txt, run chmod 600 on it and start with docker compose up -d. After about 15 seconds docker compose ps showed the service as Up (healthy). If it doesn’t start, read the Compose logs. Note that docker compose down -v deletes the volume and all data.
Back up and restore
Stream a compressed dump out of the container into a file on the server:
docker exec mongo mongodump -u admin -p 'S3cret-Pass' --authenticationDatabase admin \ --db shop --archive --gzip > shop.archive.gz
Restore it the same way, with -i so the file reaches the container:
$ docker exec -i mongo mongorestore -u admin -p 'S3cret-Pass' --authenticationDatabase admin \ --archive --gzip < shop.archive.gz 1 document(s) restored successfully. 0 document(s) failed to restore.
Copy the dump to another machine as well.
Memory
According to MongoDB, its WiredTiger cache uses by default the larger of 50% of (RAM minus 1 GB) or 256 MB, and it may not notice a container memory limit. If you limit the container with --memory, set the cache size yourself by adding the option after the image name:
docker run -d --name mongo --memory 1g ... mongo:8 --wiredTigerCacheSizeGB 0.25
In our test, db.serverStatus().wiredTiger.cache then reported a maximum of 256 MB. On a KVM VPS you have full root access, so you can size Docker and MongoDB to the plan’s RAM.
Official documentation: mongo image documentation and Docker packet filtering and firewalls.