Docker 部署 MongoDB:从零搭建到生产环境配置详解
1. 引言
在容器化技术日益普及的今天,使用 Docker 部署 MongoDB 已经成为开发和生产环境的标配方案。通过容器化部署,我们可以快速创建隔离的数据库环境,确保在不同系统间的一致性和可移植性。MongoDB 官方在 Docker Hub 上维护了官方镜像,拉取即用,大大简化了安装配置流程。
本文将从基础到进阶,带你全面掌握 Docker 部署 MongoDB 的核心技能:
- ✅ 单节点 MongoDB 快速部署
- ✅ 数据持久化与用户认证配置
- ✅ 使用 Docker Compose 编排完整服务栈
- ✅ 生产环境性能优化与安全管理
- ✅ 副本集(Replica Set)集群搭建
无论你是开发环境搭建,还是准备将 MongoDB 容器化上生产,本文都能提供实用的参考。
2. 环境准备
开始之前,请确保 Docker 已正确安装并运行:
bash
# 检查 Docker 服务状态
sudo service docker status
# 确认 Docker 已安装
docker --version
如果 Docker 尚未安装,请参考官方文档进行安装(Ubuntu/CentOS 等主流发行版均有详细指南)。
3. 快速部署:单节点 MongoDB
3.1 拉取镜像
bash
# 拉取最新官方镜像
docker pull mongo
# 拉取指定版本(如 7.0.14)
docker pull mongo:7.0.14
3.2 运行容器(基础版)
bash
docker run -d --name mongodb -p 27017:27017 mongo
参数说明:
-d:后台运行容器--name mongodb:指定容器名称-p 27017:27017:将宿主机的 27017 端口映射到容器的 MongoDB 默认端口
3.3 连接验证
bash
# 进入容器交互式 Shell
docker exec -it mongodb mongosh
如果成功进入 MongoDB Shell,说明部署已完成。
4. 数据持久化:让数据不丢失
容器默认将数据存储在容器内部的 /data/db 目录中,容器一旦删除,所有数据都会丢失。Docker 提供了两种数据持久化方式:
| 方式 | 说明 | 适用场景 |
|---|---|---|
| 绑定挂载(Bind Mount) | 将宿主机目录直接映射到容器 | 需要直接访问宿主机文件 |
| 命名卷(Named Volume) | Docker 管理的独立存储空间 | 生产环境推荐,便于备份迁移 |
4.1 绑定挂载(Bind Mount)
bash
# 创建宿主机数据目录
mkdir -p /data/mongodb
# 启动容器并挂载目录
docker run -d --name mongodb \
-p 27017:27017 \
-v /data/mongodb:/data/db \
mongo
关键点:宿主机目录必须存在且有正确权限,否则 MongoDB 容器可能因权限不足而启动失败。
4.2 命名卷(Named Volume)
bash
# 创建命名卷
docker volume create mongodb_data
# 挂载卷启动容器
docker run -d --name mongodb \
-p 27017:27017 \
-v mongodb_data:/data/db \
mongo
为什么推荐命名卷? 命名卷完全由 Docker 管理,不依赖宿主机目录结构,更易于备份、迁移和多容器共享。
5. 用户认证与安全配置
生产环境必须启用身份认证,确保数据库不被未授权访问。
5.1 环境变量初始化(推荐方式)
MongoDB 官方镜像支持通过环境变量在首次启动时自动创建 Root 用户:
bash
docker run -d --name mongodb \
-p 27017:27017 \
-v mongodb_data:/data/db \
-e MONGO_INITDB_ROOT_USERNAME=admin \
-e MONGO_INITDB_ROOT_PASSWORD=your_secure_password \
mongo
⚠️ 重要提醒:
- 两个变量必须同时设置,缺一不可,否则镜像不会启用鉴权。
- 变量名是固定的 :
MONGO_INITDB_ROOT_USERNAME和MONGO_INITDB_ROOT_PASSWORD是 MongoDB 官方镜像定义的标准变量,不能改名。 - 仅在首次启动生效:如果数据目录已有数据,环境变量不会触发初始化。如需重新初始化,必须删除数据卷后再重启。
5.2 验证鉴权是否生效
bash
# 使用管理员凭证连接
docker exec -it mongodb mongosh -u admin -p your_secure_password --authenticationDatabase admin
连接后执行以下命令验证权限:
bash
# 切换至测试库
use test
# 尝试写入 - 应报错 "not authorized"(普通用户无权限)
db.test.insertOne({x:1})
如果鉴权未生效,show dbs 等命令会直接列出所有数据库,说明容器没有启用 --auth 模式。
6. Docker Compose 高级配置
使用 Docker Compose 可以更优雅地管理多容器服务。以下是一个完整的 docker-compose.yml 示例,包含 MongoDB 数据库和 Mongo Express 可视化管理界面:
yaml
version: '3.8'
services:
mongodb:
image: mongo:7.0.14
container_name: mongodb
restart: always
environment:
MONGO_INITDB_ROOT_USERNAME: admin
MONGO_INITDB_ROOT_PASSWORD: your_secure_password
MONGO_INITDB_DATABASE: app_db
TZ: Asia/Shanghai
ports:
- "27017:27017"
volumes:
- mongodb_data:/data/db
- ./init-mongo.js:/docker-entrypoint-initdb.d/init-mongo.js:ro
networks:
- mongodb_network
healthcheck:
test: ["CMD", "mongosh", "--eval", "db.adminCommand('ping')"]
interval: 10s
timeout: 5s
retries: 5
mongo-express:
image: mongo-express:latest
container_name: mongo-express
restart: always
environment:
ME_CONFIG_MONGODB_ADMINUSERNAME: admin
ME_CONFIG_MONGODB_ADMINPASSWORD: your_secure_password
ME_CONFIG_MONGODB_SERVER: mongodb
ports:
- "8081:8081"
depends_on:
- mongodb
networks:
- mongodb_network
networks:
mongodb_network:
driver: bridge
volumes:
mongodb_data:
6.1 自动初始化脚本
上述配置中挂载了 init-mongo.js 脚本,该脚本会在 MongoDB 初始化时自动执行,可用于创建额外的数据库和业务用户:
javascript
// init-mongo.js
db = db.getSiblingDB('app_db');
db.createUser({
user: 'app_user',
pwd: 'app_user_password',
roles: [{ role: 'readWrite', db: 'app_db' }]
});
// 可选:创建集合或索引
db.createCollection('users');
6.2 启动服务
bash
# 后台启动所有服务
docker-compose up -d
# 查看服务状态
docker-compose ps
# 查看实时日志
docker-compose logs -f mongodb
启动成功后:
- MongoDB 服务监听
27017端口 - Mongo Express 管理界面访问
http://localhost:8081,使用配置的管理员账号登录
7. 生产环境优化与安全加固
7.1 内存管理优化
MongoDB 默认使用 WiredTiger 存储引擎,其缓存大小默认为系统内存的 50%--70%。在 Docker 容器中运行时,需要同时限制容器内存和 WiredTiger 缓存。
容器级限制:
bash
docker run -d --name mongodb \
-m 4g \ # 限制容器最大内存 4GB
--memory-swap 4g \ # 禁用 swap(可选)
-v mongodb_data:/data/db \
mongo --wiredTigerCacheSizeGB 2 # 限制 WT 缓存为 2GB
核心原则 :WiredTiger 缓存大小应始终小于 容器的内存上限,并为操作系统和其他进程预留 10%--20% 的空间。在 Docker 或 Kubernetes 环境中,建议按可用内存比例的 50%--60% 配置 cacheSizeGB。
Docker Compose 中的配置:
yaml
services:
mongodb:
image: mongo:7.0.14
deploy:
resources:
limits:
memory: 4G
command: ["--wiredTigerCacheSizeGB", "2"]
7.2 常见性能问题定位
| 现象 | 可能原因 | 排查方法 |
|---|---|---|
| 内存占用持续增长 | WiredTiger 缓存未限制 | db.serverStatus().wiredTiger.cache 查看 bytes currently in the cache |
| 写入延迟抖动 | 脏页过多,检查点卡顿 | bytes dirty in the cache 持续偏高,可调低 vm.dirty_ratio |
| 高并发下连接失败 | 连接池耗尽 | db.serverStatus().connections 查看连接数,应用端优化连接复用 |
7.3 跨服务依赖与健康检查
当 MongoDB 作为依赖服务(如与 Spring Boot、Node.js 等应用共享网络)时,需要在 docker-compose.yml 中配置健康检查,确保依赖容器在数据库完全就绪后才启动。
yaml
services:
mongodb:
image: mongo:7.0.14
healthcheck:
test: ["CMD", "mongosh", "--eval", "db.adminCommand('ping')"]
interval: 10s
timeout: 5s
retries: 5
myapp:
image: myapp:latest
depends_on:
mongodb:
condition: service_healthy # 等待 MongoDB 健康后再启动
7.4 安全加固清单
- ✅ 启用身份认证(设置 Root 用户密码)
- ✅ 使用非默认端口(通过
-p映射) - ✅ 将密码通过环境变量或 Docker Secrets 注入,避免写死在镜像中
- ✅ 定期执行
docker exec <container> mongodump备份数据 - ✅ 考虑使用 TLS/SSL 加密客户端与服务端通信(需挂载证书文件)
8. 备份与恢复
8.1 数据备份(mongodump)
bash
# 进入容器执行备份
docker exec mongodb mongodump --out /data/db/backup
# 将备份文件复制到宿主机
docker cp mongodb:/data/db/backup ./mongodb_backup
备份文件默认生成在 dump 目录下,包含 BSON 格式的数据文件。
8.2 数据恢复(mongorestore)
bash
# 将备份文件复制到容器
docker cp ./mongodb_backup mongodb:/data/db/backup
# 进入容器执行恢复
docker exec mongodb mongorestore /data/db/backup
💡 定期备份脚本:可将上述命令写成定时任务(cron job),每日自动备份,并将备份文件同步到远程存储。
9. 副本集(Replica Set)集群搭建(进阶)
对于需要高可用的生产环境,单节点 MongoDB 存在单点故障风险。副本集(Replica Set)是有自动故障恢复功能的主从集群,包含一个 Primary 节点和一个或多个 Secondary 节点,主节点故障时集群会自动选举新主节点。
使用 Docker Compose 搭建一主两从副本集的完整配置如下:
yaml
version: '3.8'
services:
mongo-primary:
image: mongo:7.0
container_name: mongo-primary
command: ["--replSet", "rs0", "--bind_ip_all"]
ports:
- "27017:27017"
volumes:
- mongo_primary_data:/data/db
networks:
- mongo_cluster
mongo-secondary-1:
image: mongo:7.0
container_name: mongo-secondary-1
command: ["--replSet", "rs0", "--bind_ip_all"]
ports:
- "27018:27017"
volumes:
- mongo_secondary1_data:/data/db
networks:
- mongo_cluster
depends_on:
- mongo-primary
mongo-secondary-2:
image: mongo:7.0
container_name: mongo-secondary-2
command: ["--replSet", "rs0", "--bind_ip_all"]
ports:
- "27019:27017"]
volumes:
- mongo_secondary2_data:/data/db
networks:
- mongo_cluster
depends_on:
- mongo-primary
networks:
mongo_cluster:
driver: bridge
volumes:
mongo_primary_data:
mongo_secondary1_data:
mongo_secondary2_data:
9.1 初始化副本集
容器启动后,需要手动执行初始化命令:
bash
# 进入主节点容器
docker exec -it mongo-primary mongosh
# 在 MongoDB Shell 中执行
rs.initiate({
_id: "rs0",
members: [
{ _id: 0, host: "mongo-primary:27017" },
{ _id: 1, host: "mongo-secondary-1:27017" },
{ _id: 2, host: "mongo-secondary-2:27017" }
]
})
初始化后,可通过 rs.status() 查看集群状态。当主节点故障时,剩余节点会自动选举新的 Primary,实现高可用。
10. 常见问题排查
| 问题 | 原因 | 解决方案 |
|---|---|---|
容器启动失败,日志显示 permission denied |
宿主机挂载目录权限不足 | 使用命名卷而非绑定挂载,或手动设置目录权限 |
MONGO_INITDB_ROOT_USERNAME 环境变量不生效 |
数据目录非空时不会触发初始化 | 删除数据卷后重新创建:docker-compose down -v |
| MongoDB 连接超时或拒绝连接 | 端口映射错误或容器未就绪 | 检查 docker ps 确认容器状态,配合健康检查确保服务完全启动 |
| 副本集节点无法加入集群 | 容器间网络不通或 bind_ip 配置错误 |
确保所有容器在同一 Docker 网络,且 command 中设置了 --bind_ip_all |
11. 总结
单节点开发
多容器编排
是
否
拉取 MongoDB 镜像
选择部署方式
docker run 快速启动
编写 docker-compose.yml
配置数据持久化卷
配置用户认证环境变量
集成 Mongo Express 管理界面
生产环境优化
内存限制 + 健康检查
是否需要高可用
部署副本集集群
单节点 + 定期备份
完成部署
通过本文,你应该已经掌握了 Docker 部署 MongoDB 的核心技能。核心回顾:
- 数据持久化:区分绑定挂载(Bind Mount)和命名卷(Named Volume),生产环境优先选择命名卷
- 用户认证 :务必同时设置
MONGO_INITDB_ROOT_USERNAME和MONGO_INITDB_ROOT_PASSWORD,两个变量缺一不可 - 资源管理:同时限制容器内存和 WiredTiger 缓存,缓存大小建议为容器内存的 50%--60%
- 自动化部署:使用 Docker Compose + 初始化脚本,实现一键启动和数据库初始化
- 高可用:副本集(Replica Set)主从集群实现自动故障转移
Docker 容器化部署让 MongoDB 变得前所未有的轻量和可移植,无论是开发测试环境还是生产环境,都能快速交付一致可靠的数据库服务。