Chapter 01 · MongoDB Foundations, Editions, Deployment Models, mongosh, and Lab Setup

Build a Reproducible Lab with Sample Data, Configuration, Logging, and Safe Administrative Accounts

Assemble a safe, reproducible AtlasMart lab with explicit configuration, logs, authorization bootstrap, scoped users, deterministic sample data, and a complete reset path.

Beginner120–150 minutesAuthenticated configuration + sample-data capstone labMongoDB Community Server 8.3.8 · mongosh 2.10.0Last reviewed: September 2026

Learning outcomes

The chapter ends by replacing ad-hoc startup commands with a repeatable AtlasMart learning environment. The lab deliberately keeps the blast radius small: one Docker container, one named data volume, one configuration file, a host port bound to loopback, MongoDB authorization enabled, one administrative identity, one scoped application identity, synthetic data, inspectable logs, and a complete reset procedure.

01

Write a minimal self-managed mongod configuration with explicit storage, logging, port, bind, and authorization settings.

02

Use the localhost exception correctly to create the first administrative identity after access control is enabled.

03

Create a separate least-privilege application user instead of giving application code administrative credentials.

04

Load deterministic AtlasMart sample data and verify both authorized and unauthorized behavior.

05

Collect config, log, server-build, collection, and authentication evidence and reset the lab completely.

Security boundary for this lab

Inside the container, mongod binds to 0.0.0.0 so Docker port forwarding can reach it. The host publication is restricted to 127.0.0.1:27018, and MongoDB authorization is enabled. This is a local learning design, not a production network architecture.

Localhost exception

MongoDB’s localhost exception applies only while no users or roles exist and access control is enabled. It permits creating the first user or role from localhost, then ends. In this container lab, the first user is created by running mongosh inside the container so the connection is truly local to mongod.

1. Create an explicit configuration file

Create a new empty working directory—for example mongodb-ch01-lab—and save the following file as atlasmart-mongod.conf. The configuration chooses a predictable container data path, writes logs into the same disposable named volume, listens on MongoDB's default internal port, accepts container-network traffic, and enables authorization.

yaml · atlasmart-mongod.conf
storage:  dbPath: /data/dbsystemLog:  destination: file  path: /data/db/mongod.log  logAppend: truenet:  port: 27017  bindIp: 0.0.0.0security:  authorization: enabled

bindIp: 0.0.0.0 would be unsafe if the host published the container to an untrusted network without additional controls. Here the host mapping is explicitly loopback-only. The configuration is teaching two independent boundaries: server listener scope inside its network namespace and host exposure outside it.

2. Start the pinned server with persistent disposable data

bash · start authenticated lab
# Bash / Git Bash / macOS / Linuxdocker run --name atlasmart-mongo-auth \  -p 127.0.0.1:27018:27017 \  -v "$PWD/atlasmart-mongod.conf:/etc/mongod.conf:ro" \  -v atlasmart-mongo-data:/data/db \  -d mongodb/mongodb-community-server:8.3.8-ubuntu2204-slim \  --config /etc/mongod.confdocker ps --filter name=atlasmart-mongo-auth
PowerShell · same lab with an absolute config path
# Windows PowerShell$cfg = (Resolve-Path .\atlasmart-mongod.conf).Pathdocker run --name atlasmart-mongo-auth `  -p 127.0.0.1:27018:27017 `  -v "${cfg}:/etc/mongod.conf:ro" `  -v atlasmart-mongo-data:/data/db `  -d mongodb/mongodb-community-server:8.3.8-ubuntu2204-slim `  --config /etc/mongod.confdocker ps --filter name=atlasmart-mongo-auth

If the container exits, do not add random flags. Read the log/exit state first:

bash · startup diagnosis
docker ps -a --filter name=atlasmart-mongo-authdocker logs atlasmart-mongo-auth

3. Bootstrap the first administrative identity safely

Because authorization is enabled and there are no users yet, MongoDB's localhost exception allows creation of the first user from localhost. Execute mongosh inside the container. The following local-only password is intentionally marked as a disposable course secret; choose a different strong secret if the lab is shared.

bash · use localhost exception exactly once
docker exec atlasmart-mongo-auth mongosh --host 127.0.0.1 --quiet --eval 'const admin = db.getSiblingDB("admin");admin.createUser({  user: "atlasUserAdmin",  pwd: "LocalLab-ChangeMe-Admin-01!",  roles: [    { role: "userAdminAnyDatabase", db: "admin" },    { role: "clusterAdmin", db: "admin" }  ]});print("first user created");' 

After that user exists, the localhost exception no longer grants unauthenticated creation privileges. Verify that a host connection without credentials cannot perform normal database operations:

bash · prove unauthenticated access is not sufficient
# Expected to fail with an authorization error for protected operationsmongosh "mongodb://127.0.0.1:27018/atlasmart?directConnection=true" --quiet --eval 'db.products.findOne()' 

4. Create a scoped application user, not another administrator

Authenticate as the administrative identity, then create an AtlasMart application user inside the atlasmart database. The readWrite role is intentionally scoped to one database. Real production services may need even narrower custom roles; that is taught in Chapter 22.

bash · create database-scoped application identity
mongosh "mongodb://atlasUserAdmin@127.0.0.1:27018/admin?authSource=admin&directConnection=true" --password   --quiet --eval 'const appdb = db.getSiblingDB("atlasmart");appdb.createUser({  user: "atlasApp",  pwd: "LocalLab-ChangeMe-App-01!",  roles: [{ role: "readWrite", db: "atlasmart" }]});printjson(appdb.getUser("atlasApp"));' 
Why use --password without a value?

mongosh prompts interactively instead of placing the administrative password directly in the command line. The application password is still visible in the JavaScript example because this is a disposable local lab; in real automation use a protected secret source and never commit real credentials.

5. Load deterministic AtlasMart sample data as the application identity

bash · seed deterministic AtlasMart products
mongosh "mongodb://atlasApp@127.0.0.1:27018/atlasmart?authSource=atlasmart&directConnection=true" --password   --quiet --eval 'db.products.deleteMany({ lab: "ch01" });db.products.insertMany([  { lab:"ch01", sku:"sku-laptop-13", name:"AtlasBook 13", category:"laptops", price:{amount:899,currency:"USD"}, tags:["portable","usb-c"] },  { lab:"ch01", sku:"sku-mug-blue", name:"Atlas Mug", category:"kitchen", price:{amount:18,currency:"USD"}, tags:["ceramic","blue"] },  { lab:"ch01", sku:"sku-sensor-a1", name:"Warehouse Sensor A1", category:"iot", attributes:{protocol:"BLE", battery:"CR2477"}, tags:["telemetry"] }]);printjson(db.products.find({lab:"ch01"},{_id:0,sku:1,category:1,tags:1}).sort({sku:1}).toArray());' 

The delete-before-insert makes the seed rerunnable for this lesson's documents. It is intentionally scoped by lab: "ch01"; never turn a tutorial reset into an unqualified deleteMany({}) against an unknown database.

6. Collect configuration, build, metadata, authorization, and log evidence

A reproducible lab is not complete until you can prove how it is configured and who can do what.

bash · evidence packet
# Server/config evidence (admin prompt)mongosh "mongodb://atlasUserAdmin@127.0.0.1:27018/admin?authSource=admin&directConnection=true" --password --quiet --eval 'printjson({build: db.serverBuildInfo().version});printjson(db.adminCommand({getParameter:1,featureCompatibilityVersion:1}));printjson(db.adminCommand({getCmdLineOpts:1}));printjson(db.runCommand({connectionStatus:1}));printjson(db.getSiblingDB("atlasmart").runCommand({listCollections:1,nameOnly:true}));' 
bash · endpoint, volume, and server-log evidence
# Container and log evidencedocker port atlasmart-mongo-auth 27017docker inspect atlasmart-mongo-auth --format "{{json .Mounts}}"docker exec atlasmart-mongo-auth sh -lc 'tail -n 40 /data/db/mongod.log' 

Log text varies by exact patch and environment. Search for startup completion, listener address/port, authentication events, and errors rather than expecting identical line numbers. Protect logs because they can contain operational metadata and, depending on configuration/workload, potentially sensitive context.

7. Deliberately wrong approach: one admin account for the application

A common “it works” shortcut is to give the web service the same administrative identity used for user management and cluster operations. That turns one application compromise into a database-control-plane compromise. Another shortcut is to leave authorization disabled because the port is “internal,” ignoring lateral movement and accidental network exposure.

The repair is layered: bind/publish only where required, enable authentication, separate administrative and service identities, grant the least privilege needed, rotate secrets, add TLS for non-local traffic, and keep application-level tenant authorization separate from database roles. Chapter 22 expands each control.

8. Reset path, verification checklist, and production judgment

This lab must be disposable. Stopping the container without deleting the named volume intentionally preserves data. Full reset removes both.

bash · full reset
docker rm -f atlasmart-mongo-authdocker volume rm atlasmart-mongo-data# Then delete atlasmart-mongod.conf from the disposable lab directory if desired.

Verification checklist

  • The container uses the pinned 8.3.8 Community image and host port 27018 is bound only to 127.0.0.1.
  • getCmdLineOpts shows the mounted configuration was parsed, including authorization.
  • The first user was created from inside the container through the localhost exception, then unauthenticated protected operations fail.
  • The application identity is scoped to atlasmart and is not used for cluster/user administration.
  • Sample data can be reseeded deterministically and is tagged lab: "ch01".
  • You can inspect the server log and named volume without editing WiredTiger files directly.
  • docker rm plus docker volume rm returns the lab to a clean state.

In production, replace disposable passwords with managed secrets, local-only networking with an explicit private/TLS architecture, a single standalone with a replica set or sharded topology as required, ad-hoc backup assumptions with tested recovery, and broad built-in roles with reviewed least privilege. Keep this Chapter 01 configuration as a learning artifact, not a production template.

Chapter 02 now has a stable environment in which to study BSON, _id/ObjectId, exact type fidelity, arrays/embedded documents, flexible-schema contracts, and document limits.

Check your understanding

  1. When does the localhost exception apply on mongod?
  2. Why create atlasApp separately from atlasUserAdmin?
  3. Why does the lab bind mongod to 0.0.0.0 inside the container but still call the host exposure local-only?
  4. Why is deleteMany({lab:"ch01"}) safer than deleteMany({}) in a tutorial reset?
  5. What makes a backup or security control production-ready?
Review the answers

Only when access control is enabled and there are no users or roles in the instance. It exists to bootstrap the first user or role (and certain replica-set setup actions), then ends.

Applications should not inherit user-management or cluster-administration power. Separating identities limits blast radius and makes authorization evidence clearer.

The container listener must accept traffic arriving through Docker networking, while Docker publishes that port only on host loopback 127.0.0.1. These are different network namespaces/boundaries.

It scopes cleanup to deterministic lesson-owned documents rather than deleting every document in a collection that might contain unrelated data.

Not merely enabling a feature: it needs defined ownership, least privilege/threat model, monitoring, tested failure/recovery behavior, and evidence that it meets the application’s requirements.

Authoritative references

Keep knowledge open

Help the academy stay free and grow.

If these tutorials save you time, a small donation supports new lessons, technical review, diagrams, examples, and long-term maintenance.

ETHEthereum / ERC-20 only
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0

Send only Ethereum or ERC-20 compatible assets to this address.