DEV Community

Cover image for MongoDB Docker setup — Running MongoDB in Docker containers complete guide
Piter Adyson
Piter Adyson

Posted on

MongoDB Docker setup — Running MongoDB in Docker containers complete guide

Running MongoDB in Docker simplifies deployment and makes environments reproducible across development, testing and production. You can spin up a database in seconds without dealing with complex installation procedures. This guide covers everything from basic container setup to production configurations with replica sets, persistence, custom settings and proper backup strategies.

MongoDB in Docker

Why run MongoDB in Docker

Traditional MongoDB installation requires adding repositories, managing versions, and cleaning up when things break. Docker containers provide isolation and consistency that native installations struggle to match.

Benefits of containerized MongoDB

Docker containers bundle MongoDB with all dependencies into a single package. You get identical behavior on your laptop, CI pipeline, and production servers. The classic "works on my machine" problem disappears.

Containers start fast. Launching a fresh MongoDB instance takes about 5-10 seconds versus several minutes for traditional installation. This matters for integration tests and rapid development cycles.

Cleanup is simple. Delete the container and it's gone completely. No leftover config files, no orphaned data directories cluttering your system.

When Docker makes sense for MongoDB

Docker works well for development environments where quick setup and teardown matters. It's also solid for microservices architectures where each service might need its own database instance. CI/CD pipelines benefit significantly from reproducible database containers.

For production use, Docker adds a bit of complexity but provides consistency across environments. The performance overhead is typically 1-3% for database workloads, which most applications can easily absorb.

Quick start with Docker run

The fastest way to get MongoDB running is a single Docker command. This approach works for testing and development scenarios.

Basic container setup

Start MongoDB with minimal configuration:

docker run -d \
  --name mongodb \
  mongo:8
Enter fullscreen mode Exit fullscreen mode

This starts MongoDB 8 in detached mode. The container runs until you stop it explicitly.

Check if it's running:

docker ps
Enter fullscreen mode Exit fullscreen mode

Connect to the database:

docker exec -it mongodb mongosh
Enter fullscreen mode Exit fullscreen mode

Environment variables for initial setup

MongoDB's Docker image supports environment variables for first-run configuration:

Variable Description Required
MONGO_INITDB_ROOT_USERNAME Admin username Optional
MONGO_INITDB_ROOT_PASSWORD Admin password Optional
MONGO_INITDB_DATABASE Initial database name Optional

Create an admin user on startup:

docker run -d \
  --name mongodb \
  -e MONGO_INITDB_ROOT_USERNAME=admin \
  -e MONGO_INITDB_ROOT_PASSWORD=secretpassword \
  mongo:8
Enter fullscreen mode Exit fullscreen mode

Connect with authentication:

docker exec -it mongodb mongosh -u admin -p secretpassword --authenticationDatabase admin
Enter fullscreen mode Exit fullscreen mode

Exposing ports

MongoDB runs on port 27017 inside the container by default. Map it to your host:

docker run -d \
  --name mongodb \
  -p 27017:27017 \
  -e MONGO_INITDB_ROOT_USERNAME=admin \
  -e MONGO_INITDB_ROOT_PASSWORD=secretpassword \
  mongo:8
Enter fullscreen mode Exit fullscreen mode

Now you can connect from your host machine:

mongosh "mongodb://admin:secretpassword@127.0.0.1:27017/admin"
Enter fullscreen mode Exit fullscreen mode

Use a different host port if 27017 is already in use:

docker run -d \
  --name mongodb \
  -p 27018:27017 \
  -e MONGO_INITDB_ROOT_USERNAME=admin \
  -e MONGO_INITDB_ROOT_PASSWORD=secretpassword \
  mongo:8
Enter fullscreen mode Exit fullscreen mode

Data persistence with volumes

Without volumes, your data vanishes when the container stops. That's acceptable for throwaway test databases, but anything beyond that needs persistence.

Named volumes

Docker named volumes are the simplest approach:

docker run -d \
  --name mongodb \
  -v mongodb-data:/data/db \
  -e MONGO_INITDB_ROOT_USERNAME=admin \
  -e MONGO_INITDB_ROOT_PASSWORD=secretpassword \
  mongo:8
Enter fullscreen mode Exit fullscreen mode

The volume mongodb-data persists even after you delete the container. List your volumes:

docker volume ls
Enter fullscreen mode Exit fullscreen mode

Inspect volume details:

docker volume inspect mongodb-data
Enter fullscreen mode Exit fullscreen mode

Bind mounts

Bind mounts map a host directory directly into the container. This is useful when you need direct access to data files:

docker run -d \
  --name mongodb \
  -v /path/to/data:/data/db \
  -e MONGO_INITDB_ROOT_USERNAME=admin \
  -e MONGO_INITDB_ROOT_PASSWORD=secretpassword \
  mongo:8
Enter fullscreen mode Exit fullscreen mode

Make sure the directory exists and has proper permissions. On Linux, the MongoDB user inside the container needs write access:

mkdir -p /path/to/data
chown -R 999:999 /path/to/data
Enter fullscreen mode Exit fullscreen mode

The UID 999 corresponds to the MongoDB user inside the container.

Volume backup

Back up a named volume by running a temporary container:

docker run --rm \
  -v mongodb-data:/source:ro \
  -v $(pwd):/backup \
  alpine tar czf /backup/mongodb-backup.tar.gz -C /source .
Enter fullscreen mode Exit fullscreen mode

This creates a compressed archive of the data directory. For proper database backups, use mongodump instead, which we'll cover later.

Docker Compose for MongoDB

Docker Compose makes multi-container setups manageable and keeps configurations under version control.

Basic compose file

Create a docker-compose.yml:

services:
  mongodb:
    image: mongo:8
    container_name: mongodb
    environment:
      MONGO_INITDB_ROOT_USERNAME: admin
      MONGO_INITDB_ROOT_PASSWORD: secretpassword
      MONGO_INITDB_DATABASE: myapp
    ports:
      - "27017:27017"
    volumes:
      - mongodb-data:/data/db
    restart: unless-stopped

volumes:
  mongodb-data:
Enter fullscreen mode Exit fullscreen mode

Start the service:

docker compose up -d
Enter fullscreen mode Exit fullscreen mode

Stop and remove:

docker compose down
Enter fullscreen mode Exit fullscreen mode

Remove including volumes:

docker compose down -v
Enter fullscreen mode Exit fullscreen mode

Application with MongoDB

A typical setup includes your application and MongoDB together:

services:
  app:
    build: .
    environment:
      MONGODB_URI: mongodb://appuser:apppassword@mongodb:27017/myapp?authSource=admin
    depends_on:
      mongodb:
        condition: service_healthy
    ports:
      - "8080:8080"

  mongodb:
    image: mongo:8
    container_name: mongodb
    environment:
      MONGO_INITDB_ROOT_USERNAME: admin
      MONGO_INITDB_ROOT_PASSWORD: secretpassword
    volumes:
      - mongodb-data:/data/db
    healthcheck:
      test: ["CMD", "mongosh", "--eval", "db.adminCommand('ping')"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 30s
    restart: unless-stopped

volumes:
  mongodb-data:
Enter fullscreen mode Exit fullscreen mode

The depends_on with condition: service_healthy ensures your application waits for MongoDB to be ready before starting.

Custom configuration

Default settings work for development but production workloads often need tuning.

Configuration file mount

Create a custom configuration file mongod.conf:

storage:
  dbPath: /data/db
  journal:
    enabled: true
  wiredTiger:
    engineConfig:
      cacheSizeGB: 2

systemLog:
  destination: file
  path: /var/log/mongodb/mongod.log
  logAppend: true

net:
  port: 27017
  bindIp: 0.0.0.0

security:
  authorization: enabled

operationProfiling:
  slowOpThresholdMs: 100
  mode: slowOp
Enter fullscreen mode Exit fullscreen mode

Mount it into the container:

docker run -d \
  --name mongodb \
  -v ./mongod.conf:/etc/mongod.conf:ro \
  -v mongodb-data:/data/db \
  -v mongodb-logs:/var/log/mongodb \
  -e MONGO_INITDB_ROOT_USERNAME=admin \
  -e MONGO_INITDB_ROOT_PASSWORD=secretpassword \
  mongo:8 --config /etc/mongod.conf
Enter fullscreen mode Exit fullscreen mode

Docker Compose with custom config

services:
  mongodb:
    image: mongo:8
    container_name: mongodb
    command: ["--config", "/etc/mongod.conf"]
    environment:
      MONGO_INITDB_ROOT_USERNAME: admin
      MONGO_INITDB_ROOT_PASSWORD: secretpassword
    volumes:
      - mongodb-data:/data/db
      - mongodb-logs:/var/log/mongodb
      - ./mongod.conf:/etc/mongod.conf:ro
    ports:
      - "27017:27017"
    restart: unless-stopped

volumes:
  mongodb-data:
  mongodb-logs:
Enter fullscreen mode Exit fullscreen mode

Common configuration options

Key settings to consider for production:

Setting Default Production recommendation
storage.wiredTiger.engineConfig.cacheSizeGB 50% of RAM - 1GB Set explicitly based on available memory
operationProfiling.slowOpThresholdMs 100 Tune based on your performance requirements
net.maxIncomingConnections 65536 Set based on expected concurrent connections
security.authorization disabled Always enable in production

Verify your configuration is applied:

docker exec mongodb mongosh -u admin -p secretpassword --authenticationDatabase admin --eval "db.adminCommand({getParameter: '*'})"
Enter fullscreen mode Exit fullscreen mode

Initialization scripts

The MongoDB Docker image can run scripts on first startup. This is useful for creating users, collections, and seed data.

JavaScript initialization

Place .js or .sh files in /docker-entrypoint-initdb.d/:

Create init/01-create-users.js:

db = db.getSiblingDB('myapp');

db.createUser({
  user: 'appuser',
  pwd: 'apppassword',
  roles: [
    { role: 'readWrite', db: 'myapp' }
  ]
});

db.createUser({
  user: 'readonly',
  pwd: 'readonlypassword',
  roles: [
    { role: 'read', db: 'myapp' }
  ]
});
Enter fullscreen mode Exit fullscreen mode

Create init/02-create-collections.js:

db = db.getSiblingDB('myapp');

db.createCollection('users', {
  validator: {
    $jsonSchema: {
      bsonType: 'object',
      required: ['email', 'createdAt'],
      properties: {
        email: {
          bsonType: 'string',
          description: 'must be a string and is required'
        },
        createdAt: {
          bsonType: 'date',
          description: 'must be a date and is required'
        }
      }
    }
  }
});

db.users.createIndex({ email: 1 }, { unique: true });
Enter fullscreen mode Exit fullscreen mode

Mount the init directory:

services:
  mongodb:
    image: mongo:8
    environment:
      MONGO_INITDB_ROOT_USERNAME: admin
      MONGO_INITDB_ROOT_PASSWORD: secretpassword
    volumes:
      - mongodb-data:/data/db
      - ./init:/docker-entrypoint-initdb.d:ro
    restart: unless-stopped

volumes:
  mongodb-data:
Enter fullscreen mode Exit fullscreen mode

Scripts run in alphabetical order, only on first container start when the data directory is empty.

Shell script initialization

For more complex setup, use shell scripts:

Create init/00-setup.sh:

#!/bin/bash
set -e

mongosh <<EOF
use admin
db.auth('$MONGO_INITDB_ROOT_USERNAME', '$MONGO_INITDB_ROOT_PASSWORD')

use myapp
db.createCollection('config')
db.config.insertOne({
  key: 'version',
  value: '1.0.0',
  createdAt: new Date()
})
EOF
Enter fullscreen mode Exit fullscreen mode

Make it executable:

chmod +x init/00-setup.sh
Enter fullscreen mode Exit fullscreen mode

Networking

Docker networking controls how containers communicate with each other and the outside world.

Default bridge network

Containers on the default bridge network can communicate via IP address but not hostname. For basic development this works fine:

docker run -d --name mongodb -e MONGO_INITDB_ROOT_USERNAME=admin -e MONGO_INITDB_ROOT_PASSWORD=pw mongo:8
docker run -it --rm mongo:8 mongosh "mongodb://admin:pw@$(docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' mongodb):27017/admin"
Enter fullscreen mode Exit fullscreen mode

Custom networks

Custom networks allow hostname-based communication:

docker network create myapp-network

docker run -d \
  --name mongodb \
  --network myapp-network \
  -e MONGO_INITDB_ROOT_USERNAME=admin \
  -e MONGO_INITDB_ROOT_PASSWORD=pw \
  mongo:8

docker run -it --rm \
  --network myapp-network \
  mongo:8 \
  mongosh "mongodb://admin:pw@mongodb:27017/admin"
Enter fullscreen mode Exit fullscreen mode

The second container can reach MongoDB using hostname mongodb.

Compose networking

Docker Compose creates a network automatically. Services communicate by service name:

services:
  app:
    image: myapp
    environment:
      MONGODB_URI: mongodb://admin:pw@mongodb:27017/myapp?authSource=admin

  mongodb:
    image: mongo:8
    environment:
      MONGO_INITDB_ROOT_USERNAME: admin
      MONGO_INITDB_ROOT_PASSWORD: pw
Enter fullscreen mode Exit fullscreen mode

Health checks and monitoring

Proper health checks ensure containers are actually ready to serve traffic, not just running.

Basic health check

services:
  mongodb:
    image: mongo:8
    environment:
      MONGO_INITDB_ROOT_USERNAME: admin
      MONGO_INITDB_ROOT_PASSWORD: secretpassword
    healthcheck:
      test: ["CMD", "mongosh", "--eval", "db.adminCommand('ping')"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 30s
Enter fullscreen mode Exit fullscreen mode

Check health status:

docker inspect --format='{{.State.Health.Status}}' mongodb
Enter fullscreen mode Exit fullscreen mode

Health check with authentication

When authentication is enabled, include credentials in the health check:

healthcheck:
  test: ["CMD", "mongosh", "-u", "admin", "-p", "secretpassword", "--authenticationDatabase", "admin", "--eval", "db.adminCommand('ping')"]
  interval: 10s
  timeout: 5s
  retries: 5
  start_period: 30s
Enter fullscreen mode Exit fullscreen mode

Monitoring with logs

View container logs:

docker logs mongodb
Enter fullscreen mode Exit fullscreen mode

Follow logs in real-time:

docker logs -f mongodb
Enter fullscreen mode Exit fullscreen mode

Limit output to recent entries:

docker logs --tail 100 mongodb
Enter fullscreen mode Exit fullscreen mode

Enable profiling in your configuration to catch slow operations:

operationProfiling:
  slowOpThresholdMs: 50
  mode: slowOp
Enter fullscreen mode Exit fullscreen mode

Mount a volume for logs:

volumes:
  - mongodb-data:/data/db
  - mongodb-logs:/var/log/mongodb
Enter fullscreen mode Exit fullscreen mode

Backup strategies for Docker MongoDB

Data in containers needs the same backup discipline as traditional installations. Docker adds some considerations but the fundamentals remain.

Using mongodump in Docker

Run mongodump inside the container:

docker exec mongodb mongodump -u admin -p secretpassword --authenticationDatabase admin --out /dump
docker cp mongodb:/dump ./backup
Enter fullscreen mode Exit fullscreen mode

For a specific database:

docker exec mongodb mongodump -u admin -p secretpassword --authenticationDatabase admin --db myapp --out /dump
Enter fullscreen mode Exit fullscreen mode

Compressed backup directly to host:

docker exec mongodb mongodump -u admin -p secretpassword --authenticationDatabase admin --archive --gzip > backup.gz
Enter fullscreen mode Exit fullscreen mode

Scheduled backups with cron

Create a backup script:

#!/bin/bash
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="/backups"
CONTAINER="mongodb"

docker exec $CONTAINER mongodump \
  -u admin \
  -p "$MONGO_ROOT_PASSWORD" \
  --authenticationDatabase admin \
  --archive \
  --gzip > "$BACKUP_DIR/mongodb_${TIMESTAMP}.gz"

# Keep only last 7 days
find $BACKUP_DIR -name "mongodb_*.gz" -mtime +7 -delete
Enter fullscreen mode Exit fullscreen mode

Add to crontab for daily 3 AM backups:

0 3 * * * /usr/local/bin/mongodb-backup.sh
Enter fullscreen mode Exit fullscreen mode

Using Databasus for automated backups

Manual backup scripts work but require ongoing maintenance and lack built-in monitoring. Databasus (an industry standard for MongoDB backup) provides automated backups with a web interface, scheduling and notifications.

Install Databasus on a separate server using Docker:

docker run -d \
  --name databasus \
  -p 4005:4005 \
  -v ./databasus-data:/databasus-data \
  --restart unless-stopped \
  databasus/databasus:latest
Enter fullscreen mode Exit fullscreen mode

Or with Docker Compose:

services:
  databasus:
    image: databasus/databasus:latest
    container_name: databasus
    ports:
      - "4005:4005"
    volumes:
      - databasus-data:/databasus-data
    restart: unless-stopped

volumes:
  databasus-data:
Enter fullscreen mode Exit fullscreen mode

Access the web interface at http://your-databasus-server:4005, then:

  1. Add your database — Click "New Database", select MongoDB, enter your MongoDB server's connection details (host, port, credentials)
  2. Select storage — Choose local storage, S3, Google Cloud Storage, or other supported destinations
  3. Select schedule — Set backup frequency: hourly, daily, weekly, or custom cron expression
  4. Click "Create backup" — Databasus handles backup execution, compression, retention and notifications

Databasus supports multiple notification channels including Slack, Discord, Telegram and email, so you know immediately when backups succeed or fail.

Replica sets in Docker

For production environments, running MongoDB as a replica set provides high availability and data redundancy.

Single-node replica set

Even a single-node replica set is useful because it enables change streams and transactions:

services:
  mongodb:
    image: mongo:8
    container_name: mongodb
    command: ["--replSet", "rs0", "--bind_ip_all"]
    environment:
      MONGO_INITDB_ROOT_USERNAME: admin
      MONGO_INITDB_ROOT_PASSWORD: secretpassword
    ports:
      - "27017:27017"
    volumes:
      - mongodb-data:/data/db
    restart: unless-stopped

volumes:
  mongodb-data:
Enter fullscreen mode Exit fullscreen mode

Initialize the replica set after starting:

docker exec -it mongodb mongosh -u admin -p secretpassword --authenticationDatabase admin --eval "rs.initiate()"
Enter fullscreen mode Exit fullscreen mode

Three-node replica set

For actual high availability, run three nodes:

services:
  mongodb-primary:
    image: mongo:8
    container_name: mongodb-primary
    command: ["--replSet", "rs0", "--bind_ip_all", "--keyFile", "/etc/mongodb/keyfile"]
    volumes:
      - mongodb-primary-data:/data/db
      - ./keyfile:/etc/mongodb/keyfile:ro
    networks:
      - mongodb-network
    restart: unless-stopped

  mongodb-secondary1:
    image: mongo:8
    container_name: mongodb-secondary1
    command: ["--replSet", "rs0", "--bind_ip_all", "--keyFile", "/etc/mongodb/keyfile"]
    volumes:
      - mongodb-secondary1-data:/data/db
      - ./keyfile:/etc/mongodb/keyfile:ro
    networks:
      - mongodb-network
    depends_on:
      - mongodb-primary
    restart: unless-stopped

  mongodb-secondary2:
    image: mongo:8
    container_name: mongodb-secondary2
    command: ["--replSet", "rs0", "--bind_ip_all", "--keyFile", "/etc/mongodb/keyfile"]
    volumes:
      - mongodb-secondary2-data:/data/db
      - ./keyfile:/etc/mongodb/keyfile:ro
    networks:
      - mongodb-network
    depends_on:
      - mongodb-primary
    restart: unless-stopped

networks:
  mongodb-network:

volumes:
  mongodb-primary-data:
  mongodb-secondary1-data:
  mongodb-secondary2-data:
Enter fullscreen mode Exit fullscreen mode

Generate the keyfile for internal authentication:

openssl rand -base64 756 > keyfile
chmod 400 keyfile
Enter fullscreen mode Exit fullscreen mode

Initialize the replica set:

docker exec -it mongodb-primary mongosh --eval "
rs.initiate({
  _id: 'rs0',
  members: [
    { _id: 0, host: 'mongodb-primary:27017', priority: 2 },
    { _id: 1, host: 'mongodb-secondary1:27017', priority: 1 },
    { _id: 2, host: 'mongodb-secondary2:27017', priority: 1 }
  ]
})
"
Enter fullscreen mode Exit fullscreen mode

Security considerations

Running databases in containers doesn't reduce security requirements. If anything, you need more attention to configuration details.

Enable authentication

Never run MongoDB without authentication in any environment beyond local development:

services:
  mongodb:
    image: mongo:8
    environment:
      MONGO_INITDB_ROOT_USERNAME: admin
      MONGO_INITDB_ROOT_PASSWORD: secretpassword
Enter fullscreen mode Exit fullscreen mode

Secure passwords with secrets

Use environment variables from secrets management:

services:
  mongodb:
    image: mongo:8
    environment:
      MONGO_INITDB_ROOT_USERNAME_FILE: /run/secrets/mongo_username
      MONGO_INITDB_ROOT_PASSWORD_FILE: /run/secrets/mongo_password
    secrets:
      - mongo_username
      - mongo_password

secrets:
  mongo_username:
    file: ./secrets/mongo_username.txt
  mongo_password:
    file: ./secrets/mongo_password.txt
Enter fullscreen mode Exit fullscreen mode

Network isolation

Don't expose database ports to the public internet. Use internal Docker networks:

services:
  app:
    networks:
      - frontend
      - backend

  mongodb:
    networks:
      - backend

networks:
  frontend:
  backend:
    internal: true
Enter fullscreen mode Exit fullscreen mode

Resource limits

Prevent runaway containers from consuming all system resources:

services:
  mongodb:
    image: mongo:8
    deploy:
      resources:
        limits:
          cpus: "2"
          memory: 4G
        reservations:
          cpus: "1"
          memory: 2G
Enter fullscreen mode Exit fullscreen mode

Production checklist

Before running MongoDB Docker containers in production, verify these items:

  • Data persistence configured with volumes
  • Authentication enabled with strong passwords
  • Custom configuration tuned for workload
  • Health checks enabled
  • Automated backup strategy in place
  • Secrets managed securely (not hardcoded)
  • Network properly isolated
  • Resource limits set
  • Monitoring and alerting configured
  • Restart policy set to unless-stopped or always
  • Container image version pinned (not using latest)

Troubleshooting common issues

Container exits immediately

Check logs for errors:

docker logs mongodb
Enter fullscreen mode Exit fullscreen mode

Common causes: permission issues on mounted volumes, corrupt data directory, or invalid configuration file syntax.

Permission denied on bind mount

Ensure the host directory has correct ownership:

sudo chown -R 999:999 /path/to/data
Enter fullscreen mode Exit fullscreen mode

Or run MongoDB with your user ID:

docker run -d --user $(id -u):$(id -g) ...
Enter fullscreen mode Exit fullscreen mode

Can't connect from host

Verify port mapping:

docker port mongodb
Enter fullscreen mode Exit fullscreen mode

Check if MongoDB is listening on all interfaces. The default bind address should be 0.0.0.0 in Docker, but verify with:

docker exec mongodb mongosh --eval "db.adminCommand({getCmdLineOpts: 1})"
Enter fullscreen mode Exit fullscreen mode

Replica set won't initialize

Ensure all nodes can resolve each other's hostnames. When using Docker Compose, services communicate by service name. If using custom hostnames, add them to /etc/hosts or use Docker's --add-host option.

Slow performance

Check if WiredTiger cache is sized correctly:

docker exec mongodb mongosh --eval "db.serverStatus().wiredTiger.cache"
Enter fullscreen mode Exit fullscreen mode

For Docker Desktop on macOS and Windows, file system performance through volumes can be slow. Use named volumes instead of bind mounts for better performance.

Conclusion

Running MongoDB in Docker provides consistent environments across development, testing and production. Start with simple docker run commands for quick setups, then move to Docker Compose for more complex configurations. Always configure data persistence with volumes, set up proper health checks, and implement automated backups. The overhead of containerization is minimal compared to the operational benefits of reproducibility and isolation. Pin your image versions, tune your configuration for your workload, and treat container security with the same rigor as traditional deployments.

Top comments (0)