MongoDB 的 Docker 化部署同样便捷,但默认的无认证、无持久化启动方式对于生产环境无异于裸奔。
本文将从零开始,拆解 docker run 的每一个参数,再到 Compose 声明式编排,涵盖认证、权限、备份、调优等关键环节,让你的 MongoDB 既安全又高效。
1. 使用 docker run 部署
1.1 最简启动(仅供测试)
docker run –name mongo-test -d mongo:8
这会拉取最新 mongo:8 镜像并启动,但强烈不推荐生产使用:
-
没有认证,任何人可无密码连接。
-
数据未持久化,容器删除即丢失。
-
性能参数全为默认,不适合高负载。
1.2 生产级 docker run 命令及参数详解
一条面向生产的启动命令:
docker run -d \\
–name mongo-prod \\
–restart=unless-stopped \\
-p 27017:27017 \\
-v /etc/localtime:/etc/localtime:ro \\
-v mongo-data:/data/db \\
-v mongo-configdb:/data/configdb \\
-v /opt/mongo/mongod.conf:/etc/mongod.conf:ro \\
-e MONGO_INITDB_ROOT_USERNAME=root \\
-e MONGO_INITDB_ROOT_PASSWORD_FILE=/run/secrets/mongo_root_password \\
-e MONGO_INITDB_DATABASE=app_db \\
mongo:7 \\
–config /etc/mongod.conf
参数逐行解析:
-
-d:后台运行。
-
–name mongo-prod:指定容器名称,方便后续操作。
-
–restart=unless-stopped:Docker 服务重启或容器异常退出时自动重启,手动停止则不会。
-
-p 27017:27017:端口映射 宿主机:容器。可改为 127.0.0.1:27017:27017 仅限本地访问,或 37017:27017 避免端口冲突。生产环境不建议使用27017【默认端口】,容易被共计,同时也要为了更安全,注意禁止外部访问。
-
-v /etc/localtime:/etc/localtime:ro:同步宿主机时区,避免日志和函数时间偏差。
-
-v mongo-data:/data/db:数据持久化。mongo-data 是 Docker 命名卷,位于 /var/lib/docker/volumes/。也可用绑定挂载 -v /data/mongo:/data/db。
-
-v mongo-configdb:/data/configdb:存储副本集配置等元数据(即使单机也建议挂载)。
-
-v /opt/mongo/mongod.conf:/etc/mongod.conf:ro:挂载自定义配置文件。MongoDB 官方镜像会自动识别 /etc/mongod.conf 并作为配置启动(–config /etc/mongod.conf)。只读挂载更安全。
-
环境变量(镜像初始化入口):
-
MONGO_INITDB_ROOT_USERNAME:创建 root 用户名。
-
MONGO_INITDB_ROOT_PASSWORD_FILE:指向包含密码的文件,安全替代明文环境变量。容器内路径通常为 /run/secrets/<name>。若不用文件,可用 MONGO_INITDB_ROOT_PASSWORD 直接设密码,但会暴露在 docker inspect 中。
-
MONGO_INITDB_DATABASE:初始化时自动创建的数据库名(非必须,但如果创建了应用用户,该用户对该库有读写权限;这里仅创建库,不自动创建用户,需配合 /docker-entrypoint-initdb.d/ 脚本)。
-
-
–config /etc/mongod.conf:传递命令行参数给 mongod,明确使用我们挂载的配置文件。
1.3 连接 MongoDB 与修改密码
进入容器并使用 mongosh(新版官方 shell):
docker exec -it mongo-prod mongosh -u root
输入文件中的密码即可登录。若使用明文环境变量,也可直接在宿主机通过端口连接:
mongosh –host 127.0.0.1 –port 27017 -u root -p –authenticationDatabase admin
首次安全动作:若初期使用了随机密码等,登录后立即修改 root 密码:
use admin
db.changeUserPassword("root", "new_strong_password")
建议创建一个专用应用账户(见下一节),避免 root 滥用。
2. 认证与用户管理
2.1 启用认证
当设置了 MONGO_INITDB_ROOT_USERNAME 和密码变量时,镜像会自动以 –auth 模式启动,或等价地在配置中启用授权。生产环境必须确保 authorization: enabled。若使用自定义配置文件,请显式加入:
security:
authorization: enabled
否则,任何人不需密码即可访问。
2.2 创建应用用户并细粒度授权
登录 root 后,为应用创建独立账号并授予对应数据库的 readWrite 角色:
use app_db
db.createUser({
user: "app_user",
pwd: "AppStrongPassword",
roles: [{ role: "readWrite", db: "app_db" }]
})
如果应用只需要读取,应使用 read 角色。更细粒度的可自定义角色。
验证新用户连接:
mongosh -u app_user -p –authenticationDatabase app_db –host …
最佳实践:不要将 root 或具有 root 角色的账户提供给应用。
2.3 禁用匿名访问与测试数据库
官方镜像默认不会创建测试数据库,但为了加固,可在配置文件中设置:
net:
bindIp: 0.0.0.0 # 生产若只允许容器间通信,可设为具体IP或127.0.0.1
并确保 security.authorization: enabled 生效。
3. 自定义配置与性能调优
3.1 挂载配置文件
创建宿主文件 /opt/mongo/mongod.conf(权限 600),内容示例:
# mongod.conf
net:
port: 27017
bindIp: 0.0.0.0
maxIncomingConnections: 3000
security:
authorization: enabled
storage:
dbPath: /data/db
journal:
enabled: true
wiredTiger:
engineConfig:
cacheSizeGB: 1.5 # 物理内存的50%~70%,根据容器限制调整
collectionConfig:
blockCompressor: snappy
systemLog:
destination: file
path: /var/log/mongodb/mongod.log
logAppend: true
setParameter:
enableLocalhostAuthBypass: false # 禁止本地回环免密(提升安全性)
挂载到 /etc/mongod.conf 后,MongoDB 会自动加载(镜像入口点脚本逻辑)。启动后可在 mongosh 中验证:
db.serverCmdLineOpts().parsed
3.2 时区问题
MongoDB 本身存储为 UTC 时间,无需修改。但在日志或客户端驱动中展示本地时间,可通过挂载 /etc/localtime 和设置宿主机时区变量 TZ。如有需要,可在宿主机 Docker 启动脚本中设置 -e TZ=Asia/Shanghai。
3.3 日志持久化
配置文件中的 systemLog.path 路径如果不在数据卷内,日志会在容器内丢失。建议将 /var/log/mongodb 也挂载出来,或使用 Docker 的日志驱动。简单做法是让 MongoDB 将日志打到 stdout(不设定 destination: file),由 docker logs 集中收集,生产推荐后者。
4. Docker Compose 部署方案
4.1 生产级 docker-compose.yml
version: '3.8'
services:
mongo:
image: mongo:8
container_name: mongo-prod
restart: unless-stopped
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD_FILE: /run/secrets/mongo_root_password
MONGO_INITDB_DATABASE: app_db
ports:
– "27017:27017"
volumes:
– mongo-data:/data/db
– mongo-configdb:/data/configdb
– /etc/localtime:/etc/localtime:ro
– ./mongod.conf:/etc/mongod.conf:ro
– mongo-log:/var/log/mongodb
networks:
– backend
secrets:
– mongo_root_password
command: ["–config", "/etc/mongod.conf"]
healthcheck:
test: ["CMD-SHELL", "mongosh –quiet –eval 'db.adminCommand(\\"ping\\").ok' -u root -p \\"$$(cat /run/secrets/mongo_root_password)\\" –authenticationDatabase admin || exit 1"]
interval: 10s
timeout: 5s
retries: 5
start_period: 40s
volumes:
mongo-data:
mongo-configdb:
mongo-log:
networks:
backend:
secrets:
mongo_root_password:
file: ./secrets/mongo_root_password.txt
4.2 关键点说明
-
secrets:密码存入外部文件(权限 600),通过 /run/secrets/mongo_root_password 提供给容器,配合 MONGO_INITDB_ROOT_PASSWORD_FILE 使用,密码绝不出现于 docker-compose.yml 或环境变量检查中。
-
healthcheck:使用 mongosh 执行 ping 命令,通过读取密码文件进行认证。$$ 用于转义 Compose 变量。
-
日志卷:mongo-log:/var/log/mongodb 持久化 MongoDB 自身日志(若配置了文件日志)。
-
command:确保使用自定义配置文件。
启动:docker-compose up -d
停止:docker-compose down
4.3 .env 文件支持
创建 .env 文件:
MONGO_VERSION=7
HOST_PORT=27017
docker-compose.yml 中引用:
image: mongo:${MONGO_VERSION}
ports:
– "${HOST_PORT}:27017"
5. 安全加固实践
绝不用明文密码:使用 _FILE 环境变量 + Docker secrets / Kubernetes secrets。
强制认证:配置文件 security.authorization: enabled。
关闭 localhost 免密旁路:setParameter.enableLocalhostAuthBypass: false。
绑定内网 IP:如果 MongoDB 仅被应用容器访问,bindIp 可设为 Docker 网络内的具体 IP 或 127.0.0.1,外部通过反向代理或 SSH 隧道管理。
网络隔离:Compose 中创建独立 backend 网络,不暴露宿主机端口,仅让应用容器通过服务名 mongo 连接。
TLS/SSL:生产跨节点通信需启用 TLS,挂载证书文件并在配置中设置 net.tls.mode: requireTLS 及证书路径。
审计日志:开启审计可跟踪所有操作:
auditLog:
destination: file
format: JSON
path: /var/log/mongodb/audit.log
需确保该日志也持久化或收集。
6. 日常运维与问题排查
6.1 备份与恢复
逻辑备份(推荐):
docker exec mongo-prod mongodump –username root –password "$(cat ./secrets/mongo_root_password.txt)" –authenticationDatabase admin –out /backup
docker cp mongo-prod:/backup ./backup-$(date +%F)
恢复:
docker cp ./backup-2025-01-01 mongo-prod:/restore
docker exec mongo-prod mongorestore –username root –password "$(cat ./secrets/mongo_root_password.txt)" –authenticationDatabase admin /restore
物理备份:停止写入后直接打包 /data/db 卷(或用文件系统快照),但更复杂,通常逻辑备份足够。
6.2 日志查看
docker logs -f –tail 100 mongo-prod
若配置了文件日志,可进入容器查看或通过挂载卷查看。
6.3 升级镜像
-
小版本升级:拉取新镜像,重建容器(docker-compose up -d –force-recreate),数据卷不变。
-
大版本升级(如 6.0 → 7.0):务必查阅 MongoDB 升级文档,进行功能兼容性检查和逐步升级步骤,一般需要先设置 featureCompatibilityVersion。
6.4 常见问题速查
| 容器反复重启 | 检查 docker logs,常见为挂载卷权限问题(mongod 运行用户 uid=999),执行 chown -R 999:999 /data/mongo |
| 无法连接,Authentication failed | 确认认证数据库 (authSource) 正确,root 认证数据库为 admin;应用用户为自己建的数据库 |
| Cannot start server 配置错误 | 挂载的 mongod.conf 格式有误(YAML 缩进严格),或参数与版本不兼容 |
| 内存占用过高 | 设置 cacheSizeGB 限制 WiredTiger 缓存;同时注意 docker run -m 限制容器总内存 |
| 慢查询多 | 在配置中开启慢日志:operationProfiling.mode: slowOp 配合 slowOpThresholdMs |
| 时区显示偏差 | MongoDB 内部 UTC 不可变,应用层转换时区即可;/etc/localtime 仅影响系统日志 |
结语
MongoDB 在 Docker 中的部署起点很低,但生产落地需要兼顾认证、持久化、网络、备份和资源管控。通过 docker run 理解每个参数的意义,再迁移至 Docker Compose 进行声明式管理,最终配合密码文件、健康检查和自定义配置,我们便能在保持容器轻便的同时,获得一个稳固的数据库基座。每一个细节的打磨,都是系统可靠性的基石。
