MongoDB is a document-oriented database built for agility and scale. Instead of rigid rows and columns, it stores JSON-like documents (BSON) with dynamic schemas. That flexibility shines for content systems, event logs, product catalogs, user profiles, and IoT telemetry—anywhere the data shape evolves quickly or varies record-to-record. MongoDB emphasizes horizontal scaling (sharding), high availability (replica sets), and developer ergonomics (rich drivers, expressive queries, and aggregation pipelines).
On a Plesk server, the cleanest way to run MongoDB is in Docker. You isolate the database from the host OS, get reproducible deployments, and upgrade by swapping images. Below are three approaches—choose based on your workflow:
- Option A (Plesk GUI) – Use the Docker extension UI.
- Option B (CLI) – Full control from the shell.
- Option C (Compose/Stacks) – One YAML per instance, ideal for multi-instance hosts with host-only access.
We’ll use the official
mongo:8image throughout.
What you’ll need
Storage convention used in this guide
Plesk’s Docker UI naturally favors bind mounts. While bind mounts aren’t ideal for every scenario (named volumes can be more portable and safer against path typos), we’ll use bind mounts for consistency across all three options in this article.
We’ll create a Plesk subscription (domain) named mongodb.acme.com and store data/config here:
- Data:
/var/www/vhosts/mongodb.acme.com/mongodb/data - Config:
/var/www/vhosts/mongodb.acme.com/mongodb/config
You can adapt these paths to your own subscription/domain structure.
- Plesk Obsidian with administrator/root access
- Docker (Plesk Docker extension)
- ~2–4 GB RAM minimum for a small dev instance (more for production)
- Optional: Plesk Firewall (or OS firewall) if you expose MongoDB (most apps don’t need this)
Production tip: Only expose MongoDB publicly if you absolutely must. Prefer no published port or bind to loopback (127.0.0.1) when the app is on the same host.
Architecture choices (decide these up front)
- Persistence → Mount a host path or Docker volume to
/data/db. - Auth → Always set
MONGO_INITDB_ROOT_USERNAMEandMONGO_INITDB_ROOT_PASSWORD. - Networking →
- Plesk GUI: relies on Docker’s default bridge.
- CLI/Compose: create a user-defined bridge per app for private DNS (
mongo:27017).
- Exposure → Prefer not publishing
27017. If host access is required, bind to127.0.0.1:<unique-port>. - Multi-instance → Use unique names, data volumes/paths, networks, and ports per instance.
Option A — Plesk GUI (Docker extension)
Prepare the subscription and directories (once)
- In Plesk, create a subscription (domain) named
mongodb.acme.com(or use an existing subscription). - On the server (SSH):
|
1 2 3 4 |
sudo mkdir -p /var/www/vhosts/mongodb.acme.com/mongodb/{data,config} sudo chown root:root /var/www/vhosts/mongodb.acme.com/mongodb/{data,config} sudo chmod 700 /var/www/vhosts/mongodb.acme.com/mongodb/{data,config} |
Recent Plesk Obsidian builds don’t have global “Docker → Volumes/Networks.” You configure volume mappings inside the container’s settings; networking defaults to Docker’s bridge.
A1) Single instance (GUI)
Deploy container:
- Extensions → Catalog → Docker (install/enable if needed).
- Docker → Add Container (or search
mongoin Images) → choosemongo:8. - Container Settings:
- Container name:
mongo - Env:
MONGO_INITDB_ROOT_USERNAME=rp_admin
MONGO_INITDB_ROOT_PASSWORD=ChangeMe-Use-A-Strong-One - Volume mapping (bind mounts):
/var/www/vhosts/mongodb.acme.com/mongodb/data→/data/db/var/www/vhosts/mongodb.acme.com/mongodb/config→/data/configdb
- Ports:
- Prefer none (private), or
- Host access:
127.0.0.1:27017 → 27017
- Automatic start: enabled
- Run.
- Container name:
Connect from host (if port bound):
|
1 2 |
mongodb://appuser:another-strong-pass@127.0.0.1:27017/myapp?authSource=myapp |
A2) Multiple instances (GUI)
Create instance-specific directories:
|
1 2 3 4 |
sudo mkdir -p /var/www/vhosts/mongodb.acme.com/mongodb/store/{data,config} sudo mkdir -p /var/www/vhosts/mongodb.acme.com/mongodb/auth/{data,config} sudo chmod 700 /var/www/vhosts/mongodb.acme.com/mongodb/*/{data,config} |
Repeat the deploy with unique settings per instance:
- Names:
mongo-store,mongo-auth - Volume mappings:
- Store:
/var/www/vhosts/mongodb.acme.com/mongodb/store/data→/data/db/var/www/vhosts/mongodb.acme.com/mongodb/store/config→/data/configdb
- Auth:
/var/www/vhosts/mongodb.acme.com/mongodb/auth/data→/data/db/var/www/vhosts/mongodb.acme.com/mongodb/auth/config→/data/configdb
- Store:
- Ports (host-only):
127.0.0.1:27018 → 27017(store)127.0.0.1:27019 → 27017(auth)
Host connection strings:
|
1 2 3 |
mongodb://appuser:strongpass@127.0.0.1:27018/store?authSource=store mongodb://appuser:strongpass@127.0.0.1:27019/auth?authSource=auth |
Option B — CLI (fine-grained control)
Prepare the subscription and directories (once)
|
1 2 3 4 |
sudo mkdir -p /var/www/vhosts/mongodb.acme.com/mongodb/{data,config} sudo chown root:root /var/www/vhosts/mongodb.acme.com/mongodb/{data,config} sudo chmod 700 /var/www/vhosts/mongodb.acme.com/mongodb/{data,config} |
B1) Single instance (CLI)
Run container (bind mounts, private, no published port):
|
1 2 3 4 5 6 7 8 9 10 11 12 |
docker network create rp-mongo-net || true docker run -d \ --name mongo \ --restart unless-stopped \ --network rp-mongo-net \ -v /var/www/vhosts/mongodb.acme.com/mongodb/data:/data/db \ -v /var/www/vhosts/mongodb.acme.com/mongodb/config:/data/configdb \ -e MONGO_INITDB_ROOT_USERNAME='rp_admin' \ -e MONGO_INITDB_ROOT_PASSWORD='ChangeMe-Use-A-Strong-One' \ mongo:8 --auth |
(If host access needed) bind loopback:
|
1 2 3 4 5 6 7 8 9 10 11 |
docker run -d \ --name mongo \ --restart unless-stopped \ --network rp-mongo-net \ -p 127.0.0.1:27017:27017 \ -v /var/www/vhosts/mongodb.acme.com/mongodb/data:/data/db \ -v /var/www/vhosts/mongodb.acme.com/mongodb/config:/data/configdb \ -e MONGO_INITDB_ROOT_USERNAME='rp_admin' \ -e MONGO_INITDB_ROOT_PASSWORD='ChangeMe-Use-A-Strong-One' \ mongo:8 --auth |
Create app user (inside container):
|
1 2 3 |
docker exec -it mongo mongosh -u rp_admin -p 'ChangeMe-Use-A-Strong-One' --authenticationDatabase admin \ --eval 'db.getSiblingDB("myapp").createUser({user:"appuser",pwd:"another-strong-pass",roles:[{role:"readWrite",db:"myapp"}]})' |
App container (same network):
|
1 2 |
mongodb://appuser:another-strong-pass@mongo:27017/myapp?authSource=myapp |
B2) Multiple instances (CLI)
Per instance directories:
|
1 2 3 4 |
sudo mkdir -p /var/www/vhosts/mongodb.acme.com/mongodb/store/{data,config} sudo mkdir -p /var/www/vhosts/mongodb.acme.com/mongodb/auth/{data,config} sudo chmod 700 /var/www/vhosts/mongodb.acme.com/mongodb/*/{data,config} |
Per instance networks:
|
1 2 3 |
docker network create appnet-store || true docker network create appnet-auth || true |
Mongo containers (bind mounts, no public ports):
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
# STORE docker run -d --name mongo-store --restart unless-stopped \ --network appnet-store \ -v /var/www/vhosts/mongodb.acme.com/mongodb/store/data:/data/db \ -v /var/www/vhosts/mongodb.acme.com/mongodb/store/config:/data/configdb \ -e MONGO_INITDB_ROOT_USERNAME='store_root' \ -e MONGO_INITDB_ROOT_PASSWORD='S3cure-Store!' \ mongo:8 --auth # AUTH docker run -d --name mongo-auth --restart unless-stopped \ --network appnet-auth \ -v /var/www/vhosts/mongodb.acme.com/mongodb/auth/data:/data/db \ -v /var/www/vhosts/mongodb.acme.com/mongodb/auth/config:/data/configdb \ -e MONGO_INITDB_ROOT_USERNAME='auth_root' \ -e MONGO_INITDB_ROOT_PASSWORD='S3cure-Auth!' \ mongo:8 --auth |
(If host access needed) bind unique loopback ports:
|
1 2 3 |
127.0.0.1:27018→27017 (store) 127.0.0.1:27019→27017 (auth) |
Optional hard limits to avoid noisy neighbors: add
--cpus="1.5" --memory="2g" --memory-swap="2g".
Optional cache tuning:--wiredTigerCacheSizeGB 1.
Option C – Docker Compose (Plesk Stacks)
Goal: Multiple independent MongoDB 8 instances, each with its own docker-compose.yml directory, each bound to a unique loopback port for host-only access, using bind mounts under the mongodb.acme.com subscription.
Prepare the subscription and directories (once)
|
1 2 3 4 |
sudo mkdir -p /var/www/vhosts/mongodb.acme.com/mongodb/{data,config} sudo chown root:root /var/www/vhosts/mongodb.acme.com/mongodb/{data,config} sudo chmod 700 /var/www/vhosts/mongodb.acme.com/mongodb/{data,config} |
C1) Single instance (Compose)
Directory layout
|
1 2 3 |
/var/www/vhosts/mongodb.acme.com/mongodb/auth/docker-compose.yml /var/www/vhosts/mongodb.acme.com/mongodb/auth/.env |
.env
|
1 2 3 4 |
MONGO_ROOT_USER=rp_admin MONGO_ROOT_PASS=ChangeMe-Use-A-Strong-One HOST_DB_PORT=27017 |
docker-compose.yml
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
services: mongo: image: mongo:8 container_name: mongo restart: unless-stopped command: ["--auth"] environment: MONGO_INITDB_ROOT_USERNAME: ${MONGO_ROOT_USER} MONGO_INITDB_ROOT_PASSWORD: ${MONGO_ROOT_PASS} volumes: - /var/www/vhosts/mongodb.acme.com/mongodb/data:/data/db - /var/www/vhosts/mongodb.acme.com/mongodb/config:/data/configdb ports: - "127.0.0.1:${HOST_DB_PORT}:27017" # port from .env healthcheck: test: ["CMD", "mongosh", "--eval", "db.adminCommand('ping')"] interval: 30s timeout: 5s retries: 5 # env_file: # - .env |
Create the stack in Plesk
- Extensions → Docker → Stacks → Add Stack, point to
/var/www/vhosts/mongodb.acme.com/mongodb/auth/docker-compose.yml. - If
.envwasn’t auto-loaded, set variables in the Stack UI or addenv_file.
Start via CLI (alternative to Plesk Stacks)
|
1 2 3 4 5 6 7 8 9 |
cd /var/www/vhosts/mongodb.acme.com/mongodb/auth # first run / update docker compose pull docker compose up -d # status & logs docker compose ps docker compose logs -f |
Host connection
|
1 2 |
mongodb://appuser:another-strong-pass@127.0.0.1:${HOST_DB_PORT}/myapp?authSource=myapp |
C2) Multiple instances (Compose)
Directories
|
1 2 3 4 5 6 |
/var/www/vhosts/mongodb.acme.com/mongodb/store/docker-compose.yml /var/www/vhosts/mongodb.acme.com/mongodb/store/.env /var/www/vhosts/mongodb.acme.com/mongodb/auth/docker-compose.yml /var/www/vhosts/mongodb.acme.com/mongodb/auth/.env |
/var/www/vhosts/mongodb.acme.com/mongodb/store/.env
|
1 2 3 4 |
MONGO_ROOT_USER=store_root MONGO_ROOT_PASS=S3cure-Store! HOST_DB_PORT=27018 |
/var/www/vhosts/mongodb.acme.com/mongodb/store/docker-compose.yml
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
services: mongo_store: image: mongo:8 container_name: mongo-store restart: unless-stopped command: ["--auth"] environment: MONGO_INITDB_ROOT_USERNAME: ${MONGO_ROOT_USER} MONGO_INITDB_ROOT_PASSWORD: ${MONGO_ROOT_PASS} volumes: - /var/www/vhosts/mongodb.acme.com/mongodb/store/data:/data/db - /var/www/vhosts/mongodb.acme.com/mongodb/store/config:/data/configdb ports: - "127.0.0.1:${HOST_DB_PORT}:27017" healthcheck: test: ["CMD", "mongosh", "--eval", "db.adminCommand('ping')"] interval: 30s timeout: 5s retries: 5 |
/var/www/vhosts/mongodb.acme.com/mongodb/auth/.env
|
1 2 3 4 |
MONGO_ROOT_USER=auth_root MONGO_ROOT_PASS=S3cure-Auth! HOST_DB_PORT=27019 |
/var/www/vhosts/mongodb.acme.com/mongodb/auth/docker-compose.yml
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
services: mongo_auth: image: mongo:8 container_name: mongo-auth restart: unless-stopped command: ["--auth"] environment: MONGO_INITDB_ROOT_USERNAME: ${MONGO_ROOT_USER} MONGO_INITDB_ROOT_PASSWORD: ${MONGO_ROOT_PASS} volumes: - /var/www/vhosts/mongodb.acme.com/mongodb/auth/data:/data/db - /var/www/vhosts/mongodb.acme.com/mongodb/auth/config:/data/configdb ports: - "127.0.0.1:${HOST_DB_PORT}:27017" healthcheck: test: ["CMD", "mongosh", "--eval", "db.adminCommand('ping')"] interval: 30s timeout: 5s retries: 5 |
Start via CLI (per instance)
|
1 2 3 4 5 6 7 8 |
# STORE cd /var/www/vhosts/mongodb.acme.com/mongodb/store docker compose pull && docker compose up -d # AUTH cd /var/www/vhosts/mongodb.acme.com/mongodb/auth docker compose pull && docker compose up -d |
Host connection strings
|
1 2 3 |
mongodb://appuser:strongpass@127.0.0.1:27018/store?authSource=store mongodb://appuser:strongpass@127.0.0.1:27019/auth?authSource=auth |
Backups (all options)
Logical dumps with mongodump
- Networked (B/C without host ports): run a throwaway
mongo:8container on the same Docker network as the DB and targetmongo:27017. - Host-bound (A/C multi-instance): run the backup container with
--network hostand target127.0.0.1:<port>.
Examples (host-bound, multi-instance):
|
1 2 3 4 5 6 7 8 9 10 |
mkdir -p /var/backups/mongo/store/$(date +%F) docker run --rm --network host -v /var/backups/mongo:/backup mongo:8 \ bash -lc 'mongodump -h 127.0.0.1:27018 -u appuser -p "strongpass" \ --authenticationDatabase store -d store -o /backup/store/$(date +%F)' mkdir -p /var/backups/mongo/auth/$(date +%F) docker run --rm --network host -v /var/backups/mongo:/backup mongo:8 \ bash -lc 'mongodump -h 127.0.0.1:27019 -u appuser -p "strongpass" \ --authenticationDatabase auth -d auth -o /backup/auth/$(date +%F)' |
Restore test (monthly)
Spin up a temporary Mongo, create a root user, and mongorestore from one of the dated folders.
Upgrades & maintenance
- Minor updates
- A: Stop/remove container in UI, re-run with same settings after
mongo:8is pulled (or recreate via UI). - B:
docker pull mongo:8 && docker stop mongo && docker rm mongothen recreate with the same flags. - C: Per instance dir:
docker compose pull && docker compose up -d.
- A: Stop/remove container in UI, re-run with same settings after
- Major upgrades: Read release notes and test on a copy of data.
- Logs:
docker logs -f <container> - Resources: Monitor disk and memory; WiredTiger needs headroom.
Troubleshooting quick hits
- “Authentication failed” → Ensure
authSourcematches the DB that holds the user (often notadmin). - “Connection refused” → Same network (B/C) and use container name (
mongo,mongo-store) or correct host port. - High CPU at idle → Investigate unindexed queries; create indexes with
db.collection.createIndex(...). - Permission denied on data path → If bind-mounting, ensure the host directory is writable by MongoDB’s UID/GID inside the container (UID 999).
Which option should I use?
| Need / Constraint | Option A (GUI) | Option B (CLI) | Option C (Compose per instance) |
|---|---|---|---|
| Fastest single instance | ✅ | ✅ | — |
| Private app↔DB without exposing ports | ⚠️ (awkward) | ✅ user-defined networks | ✅ if you also define the app service/network |
| Many isolated instances on one host | 😬 manual UI work | ✅ straightforward per network/volume/name | ✅ best: one compose dir (YAML + .env) each |
| Host-only access (loopback) per instance | ✅ per-container mapping | ✅ -p 127.0.0.1:PORT:27017 |
✅ best via ports: "127.0.0.1:${PORT}:27017" |
| Source control & repeatability | ❌ | ⚠️ scripts | ✅ commit each instance’s YAML & .env |
Wrap-up
You now have three clean paths to run MongoDB 8 in Docker on a Plesk server—each showing the single-instance flow first and the multi-instance pattern second. For multi-instance hosts with host-only access, Option C (one compose per instance with the port in .env) is tidy, repeatable, and easy to operate.




