CodeRoadMap
首页路线题库资源库文章社区
CodeRoadMap

程序员的学习成长路线图。内容免费开放,登录后可同步路线图与课时进度。

由 程序员柏风 独立维护 · 关于作者

学习

  • 路线图
  • 课程
  • 面试题
  • 文章
  • 我

更多

  • 资源
  • 社区
  • 关于作者
  • 内容说明

© 2026 CodeRoadMap

津ICP备2026012044号-1·津公网安备12011002026155号·coderoadmap@126.com
MongoDB 入门/课时/Docker 运行 MongoDB
RawBlame
课时目录12 节

MongoDB 入门

  1. 01MongoDB 是什么
  2. 02安装与 mongosh
  3. 03文档与 BSON
  4. 04CRUD 操作
  5. 05查询与投影
  6. 06索引
  7. 07聚合管道
  8. 08Spring Data MongoDB
  9. 09何时用 Mongo vs SQL
  10. 10Docker 运行 MongoDB
  11. 11Node.js 驱动与 Mongoose
  12. 12综合练习

Docker 运行 MongoDB

官方镜像、卷、compose 片段。

25 分钟

Docker 运行 MongoDB

这一课你将能做到

  1. 用官方 mongo:7 镜像启动带数据卷与 root 用户的容器,验证「重建容器数据仍在」
  2. 编写可与 backend 服务并列的 docker-compose 片段,说明端口、环境变量、卷与 healthcheck 的含义
  3. 严格区分 MySQL 与 Mongo 的配置键与初始化机制,说清 /docker-entrypoint-initdb.d 的生效时机

为什么要学

安装课用一次性容器跑通了连通性,但「删容器就丢数据」显然不能接受。本课补齐生产习惯的三块拼图:数据卷(数据活过容器生命周期)、compose 编排(团队一键复现环境)、初始化机制(首次建库自动化)。这些同样是 Docker 面试里数据库类容器的标准考点。

人话:容器随时可以扔,卷里的 /data/db 不能丢;compose 把「MongoDB 7 + root 用户 + 数据卷」写成一份可提交的 YAML。

先建立图像

docker compose
  └─ mongo 服务
       image: mongo:7
       ports:   本机 27017 → 容器 27017
       env:     MONGO_INITDB_ROOT_USERNAME / PASSWORD(仅首次初始化生效)
       volume:  mongo_data → /data/db(数据真正的家)
       healthcheck: ping 探活
              ↑
   mongosh / Spring Boot / Node 全部通过 URI 连进来
MongoDB 容器MySQL 容器
镜像mongo:7mysql:8
默认端口270173306
数据目录/data/db/var/lib/mysql
初始化目录/docker-entrypoint-initdb.d同名机制
客户端mongoshmysql

跟着做

步骤 1:单容器 + 命名卷

# 若安装课已有同名容器:docker rm -f mongo-dev
docker run -d --name mongo-dev \
  -p 27017:27017 \
  -e MONGO_INITDB_ROOT_USERNAME=admin \
  -e MONGO_INITDB_ROOT_PASSWORD=secret \
  -v mongo_data:/data/db \
  mongo:7

docker volume ls        # 应看到 mongo_data(或带项目前缀)
docker inspect mongo-dev --format '{{ .Mounts }}'   # 确认挂载

步骤 2:写入数据,验证「重建容器数据仍在」

docker exec -it mongo-dev mongosh -u admin -p secret --authenticationDatabase admin
use coderoadmap_lab
db.persist_demo.insertOne({ ok: true, note: "重启也不应丢" })
exit

删容器、用同一卷重建:

docker rm -f mongo-dev
docker run -d --name mongo-dev \
  -p 27017:27017 \
  -e MONGO_INITDB_ROOT_USERNAME=admin \
  -e MONGO_INITDB_ROOT_PASSWORD=secret \
  -v mongo_data:/data/db \
  mongo:7

docker exec -it mongo-dev mongosh -u admin -p secret --authenticationDatabase admin \
  --eval "db.getSiblingDB('coderoadmap_lab').persist_demo.find()"

应看到:文档还在。这就是「容器可弃、卷长存」的核心实验——没挂卷的安装课容器做这个实验,数据必丢。

步骤 3:编写 compose 文件

项目根目录建 docker-compose.mongo.yml(密码建议从 .env 注入,勿提交明文):

services:
  mongo:
    image: mongo:7                    # 钉版本,不用 latest
    container_name: mongo-dev
    ports:
      - "27017:27017"
    environment:
      MONGO_INITDB_ROOT_USERNAME: admin
      MONGO_INITDB_ROOT_PASSWORD: secret
    volumes:
      - mongo_data:/data/db
      # - ./mongo-init:/docker-entrypoint-initdb.d:ro   # 可选:初始化脚本
    healthcheck:                      # 探活,编排依赖与 CI 判定都靠它
      test: ["CMD", "mongosh", "--quiet", "--eval", "db.runCommand({ ping: 1 }).ok"]
      interval: 10s
      timeout: 5s
      retries: 5

volumes:
  mongo_data:
docker compose -f docker-compose.mongo.yml up -d
docker compose -f docker-compose.mongo.yml ps   # 状态 healthy

用安装课的 URI 连接验证即可。日常停止用 docker compose stop(保卷保容器);down -v 会删卷 = 删库,只在故意重来时用。

步骤 4:理解初始化脚本机制

把 .js / .sh 放进 /docker-entrypoint-initdb.d(如挂载 ./mongo-init 目录),容器首次初始化(数据目录为空)时按文件名顺序执行一次:

// mongo-init/01-create-app-user.js
db = db.getSiblingDB("coderoadmap_lab");
db.createUser({
  user: "app",
  pwd: "app123",
  roles: [{ role: "readWrite", db: "coderoadmap_lab" }]
});

关键规则写进笔记:卷里已有数据则脚本不会重跑;改了脚本想生效,要么删卷重建(清空数据),要么进容器手动执行。业务用户 app 比 root 更贴近生产习惯——应用连接串应换成最小权限用户。

步骤 5:对照 Spring 配置键

spring:
  data:
    mongodb:
      uri: mongodb://app:app123@127.0.0.1:27017/coderoadmap_lab?authSource=coderoadmap_lab

绝不改动 spring.datasource.url(那是 MySQL)。如果步骤 4 建了 app 用户,authSource 改为业务库名。

步骤 6:生产化清单(自查)

  • 镜像钉版本(mongo:7.x),不用 latest
  • 数据在命名卷或宿主机目录,且纳入备份策略
  • 应用用最小权限用户,不用 root
  • 密码走环境变量 / 密钥管理,不进 git
  • 端口仅本机或内网可达,不暴露公网
  • 生产高可用走副本集(单容器只是开发环境形态)

讲清楚要点

  1. 容器可写层随容器删除而消失:数据必须挂卷到 /data/db——开发环境也要挂,否则「昨晚的数据呢」每周上演。
  2. MONGO_INITDB_ROOT_* 只在首次初始化生效:数据目录非空时被忽略;改密码要么删卷重来,要么进 shell db.updateUser。
  3. init 目录是「一次性种子」不是「同步机制」:按文件名顺序执行一次;理解这个前提才不会「改了脚本怎么没生效」。
  4. compose 是团队的复现契约:版本、端口、卷、healthcheck 全部声明式,比口头 docker run 稳定得多。
  5. healthcheck 让「活着」可验证:depends_on: condition: service_healthy、CI 冒烟测试都依赖它。
  6. 单容器 ≠ 生产架构:生产是副本集(1 主 2 从 + 仲裁),提供高可用与故障转移,也是启用多文档事务的前提——面试常考。

你可能会懵的地方

  • docker restart、compose down、down -v 差在哪? restart 保容器保卷;down 删容器保命名卷;down -v 连卷一起删 = 清库。日常用 stop/down,-v 只在明确要重来时用。

  • Apple Silicon / Windows 上卷性能异常? 文件系统跨虚拟化有开销,开发可接受;数据库镜像的数据卷走 Docker 管理的命名卷(而非 bind mount 到宿主目录)性能更好——本课用的就是命名卷。

  • 容器里改了密码,应用连不上了? INITDB 环境变量不再生效。进 mongosh 用 db.updateUser 改密码,或评估数据可弃后删卷重建;改完同步更新所有客户端 URI。

  • 和 MongoDB Atlas 什么关系? Atlas 是官方托管云(本质是帮你运维的副本集/集群)。本地 Docker 管开发与学习;连接串形态相同,仅主机与认证细节不同——本地练的技能可平移。

错法对照

错法问题正解
不挂 -v 直接跑删容器数据全丢mongo_data:/data/db
down -v 当日常停机误删数据卷日常 stop / down;-v 仅重来时
镜像用 mongo:latest环境不可复现钉大版本 mongo:7
把 Mongo 端口写进 MySQL datasource协议错配连不上库spring.data.mongodb.uri
改 init 脚本期待重跑卷非空时不执行删卷重建或手动执行
应用连 root 用户权限过大init 建最小权限业务用户

卡点急救

  1. 现象:docker ps 里容器一直 restarting 查日志 docker logs mongo-dev。高频原因:卷里残留了与当前环境变量不一致的旧数据(密码对不上)——确认卷归属,必要时换新卷名重建。
  2. 现象:27017 端口被占用 本机可能还装着原生 MongoDB 服务。Windows 用 netstat -ano | findstr 27017 找到占用者停掉,或 compose 改映射 27018:27017 并同步改 URI。
  3. 现象:healthcheck 一直 unhealthy 进容器手动跑 mongosh --quiet --eval "db.runCommand({ping:1})" 复现;多为认证参数缺失(healthcheck 命令里认证可省略 ping,但路径或引号错误会直接失败),逐字符核对 test 命令数组。

面试常问

  • 容器里的 MongoDB 怎么保证数据不丢? 数据目录 /data/db 挂载到命名卷或宿主目录,容器删除重建后数据仍在卷里;再配合定期备份(mongodump 或云快照)。生产环境则部署副本集,故障转移由集群层保证——分清「持久化」与「高可用」两层。

  • MONGO_INITDB_ROOT_USERNAME 什么时候生效? 仅在数据目录为空的首次初始化时生效:创建 root 用户并执行 /docker-entrypoint-initdb.d 下的脚本;之后重启、重建容器都不会重跑。要重置就得删卷重建,或手动维护用户。

  • 生产环境部署 MongoDB 要注意什么? 钉镜像版本、数据卷 + 备份策略、最小权限用户与网络隔离、副本集高可用(也是事务前提)、资源限制与监控(mongostat/$indexStats)。答出「副本集提供高可用 + 故障转移」是及格线,能提备份与权限是加分。

自测三问

  1. 为什么要挂载 /data/db?不挂会怎样?
  2. MONGO_INITDB_ROOT_* 与 init 目录脚本分别在什么时机生效?
  3. down 与 down -v 的区别是什么?哪个等价于删库?

小结一句话

mongo:7 + 命名卷 + compose(含 healthcheck)是本地 MongoDB 的标准姿势:容器可弃、数据长存、环境可复现;与 MySQL 主库的配置严格分开。

延伸

  • 官方 Docker 安装 MongoDB 教程
  • Docker Hub mongo 镜像页
  • 下一课:Node.js 驱动与 Mongoose——从脚本视角再打通一条客户端路径。
加载本节练习…
← 上一课何时用 Mongo vs SQL下一课 →Node.js 驱动与 Mongoose