MongoDB
Docker Compose
Docker Machine
External Volume
Data Persistence

How to mount external volume for mongoDB using docker-compose and docker-machine

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

When MongoDB runs in a container, its data directory must live outside the container filesystem or you will lose the database when the container is removed. With docker-compose and docker-machine, the important detail is that mounts are resolved on the Docker daemon host, not on the machine where you type the command. Once you understand that distinction, MongoDB persistence becomes straightforward.

Understand Where the Volume Actually Lives

docker-machine talks to a remote Docker daemon, often a small VM created with VirtualBox or another driver. That means a path in your Compose file is interpreted on that remote machine.

If you write a bind mount like this:

yaml
1services:
2  mongo:
3    image: mongo:7
4    volumes:
5      - /data/mongo:/data/db

the left side refers to /data/mongo on the docker-machine host, not on your laptop shell session. This is the source of most confusion.

Choose Between a Named Volume and a Host Bind Mount

You have two persistence options:

  • a named Docker volume managed by the remote Docker daemon
  • a bind mount to a specific directory on the remote machine

A named volume is simpler:

yaml
1services:
2  mongo:
3    image: mongo:7
4    restart: unless-stopped
5    ports:
6      - "27017:27017"
7    volumes:
8      - mongo_data:/data/db
9
10volumes:
11  mongo_data:

This is often enough if you only care that the data survives container recreation. If you want the data in a known host path for inspection, backup, or migration, use a bind mount instead.

Prepare the Remote Directory on the Docker Machine

For a bind mount, create the directory on the remote machine first. The exact path depends on the machine driver, but with the old VirtualBox-based default machine, /mnt/sda1 was commonly used for persistent storage.

bash
docker-machine ssh default "sudo mkdir -p /mnt/sda1/data/mongo"
docker-machine ssh default "sudo chown 999:999 /mnt/sda1/data/mongo"

MongoDB in the official container typically runs as user ID 999, so setting ownership avoids permission errors at startup.

You can verify the directory exists:

bash
docker-machine ssh default "ls -ld /mnt/sda1/data/mongo"

Mount the Directory in docker-compose

Once the remote directory exists, reference it in the Compose file:

yaml
1services:
2  mongo:
3    image: mongo:7
4    container_name: mongo
5    restart: unless-stopped
6    ports:
7      - "27017:27017"
8    volumes:
9      - /mnt/sda1/data/mongo:/data/db

Then start the service with the Docker environment pointed at your machine:

bash
eval "$(docker-machine env default)"
docker compose up -d

If you are using the older standalone Compose binary, the second command may be docker-compose up -d.

Verify That MongoDB Data Persists

It is worth testing persistence instead of assuming the mount worked. Insert a document, remove the container, and recreate it.

bash
1docker exec -it mongo mongosh --eval "db.test.insertOne({name: 'persistent'})"
2docker compose down
3docker compose up -d
4docker exec -it mongo mongosh --eval "db.test.find().toArray()"

If the document still exists, MongoDB is writing to the mounted storage rather than the ephemeral container layer.

When an External Named Volume Makes Sense

Sometimes "external volume" means a Docker volume created outside the Compose file. In that case, create it first on the remote daemon:

bash
eval "$(docker-machine env default)"
docker volume create mongo_data

Then declare it as external:

yaml
1services:
2  mongo:
3    image: mongo:7
4    volumes:
5      - mongo_data:/data/db
6
7volumes:
8  mongo_data:
9    external: true

This keeps Compose from trying to create or remove the volume itself. It is useful when multiple stacks share the same persistent storage or when infrastructure provisions volumes separately.

Common Pitfalls

The biggest mistake is assuming the host path in Compose refers to the local workstation rather than the docker-machine VM. Another common issue is creating the remote directory but forgetting the container user needs write access to it. Some setups also use paths that are not actually persistent on the machine driver, so data appears to work until the VM restarts. Developers also mix up named volumes and bind mounts, even though they solve slightly different problems. Finally, it is easy to trust the configuration without testing persistence by recreating the container, which is the fastest way to catch a bad mount.

Summary

  • MongoDB data must be mounted outside the container if you want persistence.
  • With docker-machine, bind-mount paths are resolved on the remote Docker host.
  • Use a named volume for simplicity or a bind mount when you need a specific host path.
  • Create and permission the remote directory before starting MongoDB.
  • Verify persistence by writing data, recreating the container, and reading it back.
  • If needed, declare a pre-created Docker volume as external: true.

Course illustration
Course illustration

All Rights Reserved.