Skip to content

MongoDB Docker 部署

Docker 基础知识

Docker 概念

容器化技术

  • Docker 是一种容器化平台,允许将应用程序及其依赖打包到容器中
  • 容器是轻量级、可移植的,提供隔离的运行环境
  • 支持跨平台部署,确保应用在不同环境中运行一致

核心组件

  • Docker 镜像:包含应用程序及其依赖的只读模板
  • Docker 容器:从镜像创建的可运行实例
  • Docker 仓库:存储和分发镜像的地方(如 Docker Hub)
  • Docker Compose:用于定义和运行多容器 Docker 应用的工具

MongoDB Docker 镜像

官方镜像

  • MongoDB 官方提供的 Docker 镜像:mongo
  • 支持多个版本标签,如 latest5.06.07.0
  • 基于 Alpine Linux 或 Debian,体积小,性能好
  • 定期更新,包含最新的安全补丁

镜像选择

  • 生产环境建议使用特定版本标签,避免自动更新导致的兼容性问题
  • 测试环境可以使用 latest 标签
  • 考虑镜像大小和性能需求选择基础镜像

单节点部署

基本部署

简单启动

bash
# 拉取 MongoDB 镜像
docker pull mongo:6.0

# 启动单节点 MongoDB
docker run -d \
  --name mongodb \
  -p 27017:27017 \
  -e MONGO_INITDB_ROOT_USERNAME=admin \
  -e MONGO_INITDB_ROOT_PASSWORD=password \
  mongo:6.0

参数说明

  • -d:后台运行容器
  • --name:指定容器名称
  • -p:端口映射,将容器内的 27017 端口映射到主机的 27017 端口
  • -e:设置环境变量,初始化 root 用户

数据持久化

挂载数据卷

bash
docker run -d \
  --name mongodb \
  -p 27017:27017 \
  -e MONGO_INITDB_ROOT_USERNAME=admin \
  -e MONGO_INITDB_ROOT_PASSWORD=password \
  -v mongodb_data:/data/db \
  -v mongodb_config:/data/configdb \
  mongo:6.0

使用主机目录

bash
docker run -d \
  --name mongodb \
  -p 27017:27017 \
  -e MONGO_INITDB_ROOT_USERNAME=admin \
  -e MONGO_INITDB_ROOT_PASSWORD=password \
  -v /host/path/data:/data/db \
  -v /host/path/config:/data/configdb \
  mongo:6.0

注意事项

  • 确保主机目录权限正确,MongoDB 容器内使用 mongod 用户(UID 999)
  • 使用数据卷比主机目录更安全,避免权限问题
  • 定期备份数据卷或主机目录

自定义配置

使用配置文件

bash
docker run -d \
  --name mongodb \
  -p 27017:27017 \
  -e MONGO_INITDB_ROOT_USERNAME=admin \
  -e MONGO_INITDB_ROOT_PASSWORD=password \
  -v /host/path/mongod.conf:/etc/mongod.conf \
  -v mongodb_data:/data/db \
  mongo:6.0 --config /etc/mongod.conf

mongod.conf 示例

yaml
storage:
  dbPath: /data/db
  journal:
    enabled: true

net:
  port: 27017
  bindIp: 0.0.0.0

security:
  authorization: enabled

replication:
  replSetName: rs0

副本集部署

基本副本集

步骤 1:创建网络

bash
docker network create mongodb-net

步骤 2:启动副本集节点

bash
# 主节点
docker run -d \
  --name mongodb-primary \
  --network mongodb-net \
  -p 27017:27017 \
  -e MONGO_INITDB_ROOT_USERNAME=admin \
  -e MONGO_INITDB_ROOT_PASSWORD=password \
  -v mongodb-primary:/data/db \
  mongo:6.0 --replSet rs0

# 从节点 1
docker run -d \
  --name mongodb-secondary1 \
  --network mongodb-net \
  -p 27018:27017 \
  -e MONGO_INITDB_ROOT_USERNAME=admin \
  -e MONGO_INITDB_ROOT_PASSWORD=password \
  -v mongodb-secondary1:/data/db \
  mongo:6.0 --replSet rs0

# 从节点 2
docker run -d \
  --name mongodb-secondary2 \
  --network mongodb-net \
  -p 27019:27017 \
  -e MONGO_INITDB_ROOT_USERNAME=admin \
  -e MONGO_INITDB_ROOT_PASSWORD=password \
  -v mongodb-secondary2:/data/db \
  mongo:6.0 --replSet rs0

步骤 3:初始化副本集

bash
# 连接到主节点
docker exec -it mongodb-primary mongosh -u admin -p password --authenticationDatabase admin

# 初始化副本集
rs.initiate({
  _id: "rs0",
  members: [
    { _id: 0, host: "mongodb-primary:27017" },
    { _id: 1, host: "mongodb-secondary1:27017" },
    { _id: 2, host: "mongodb-secondary2:27017" }
  ]
})

带仲裁节点的副本集

添加仲裁节点

bash
docker run -d \
  --name mongodb-arbiter \
  --network mongodb-net \
  -e MONGO_INITDB_ROOT_USERNAME=admin \
  -e MONGO_INITDB_ROOT_PASSWORD=password \
  -v mongodb-arbiter:/data/db \
  mongo:6.0 --replSet rs0 --smallfiles

# 连接到主节点并添加仲裁节点
docker exec -it mongodb-primary mongosh -u admin -p password --authenticationDatabase admin
rs.addArb("mongodb-arbiter:27017")

仲裁节点作用

  • 不存储数据,只参与选举
  • 用于偶数节点的副本集,确保能选出主节点
  • 降低硬件成本

Docker Compose 部署

单节点部署

docker-compose.yml 示例

yaml
version: '3.8'

services:
  mongodb:
    image: mongo:6.0
    container_name: mongodb
    ports:
      - "27017:27017"
    environment:
      MONGO_INITDB_ROOT_USERNAME: admin
      MONGO_INITDB_ROOT_PASSWORD: password
    volumes:
      - mongodb_data:/data/db
      - mongodb_config:/data/configdb
    restart: unless-stopped

volumes:
  mongodb_data:
  mongodb_config:

启动命令

bash
docker-compose up -d

副本集部署

docker-compose.yml 示例

yaml
version: '3.8'

services:
  mongodb-primary:
    image: mongo:6.0
    container_name: mongodb-primary
    ports:
      - "27017:27017"
    environment:
      MONGO_INITDB_ROOT_USERNAME: admin
      MONGO_INITDB_ROOT_PASSWORD: password
    volumes:
      - mongodb-primary:/data/db
      - ./mongod.conf:/etc/mongod.conf
    command: --config /etc/mongod.conf --replSet rs0
    restart: unless-stopped

  mongodb-secondary1:
    image: mongo:6.0
    container_name: mongodb-secondary1
    ports:
      - "27018:27017"
    environment:
      MONGO_INITDB_ROOT_USERNAME: admin
      MONGO_INITDB_ROOT_PASSWORD: password
    volumes:
      - mongodb-secondary1:/data/db
      - ./mongod.conf:/etc/mongod.conf
    command: --config /etc/mongod.conf --replSet rs0
    restart: unless-stopped
    depends_on:
      - mongodb-primary

  mongodb-secondary2:
    image: mongo:6.0
    container_name: mongodb-secondary2
    ports:
      - "27019:27017"
    environment:
      MONGO_INITDB_ROOT_USERNAME: admin
      MONGO_INITDB_ROOT_PASSWORD: password
    volumes:
      - mongodb-secondary2:/data/db
      - ./mongod.conf:/etc/mongod.conf
    command: --config /etc/mongod.conf --replSet rs0
    restart: unless-stopped
    depends_on:
      - mongodb-primary

  mongodb-arbiter:
    image: mongo:6.0
    container_name: mongodb-arbiter
    environment:
      MONGO_INITDB_ROOT_USERNAME: admin
      MONGO_INITDB_ROOT_PASSWORD: password
    volumes:
      - mongodb-arbiter:/data/db
      - ./mongod.conf:/etc/mongod.conf
    command: --config /etc/mongod.conf --replSet rs0 --smallfiles
    restart: unless-stopped
    depends_on:
      - mongodb-primary

volumes:
  mongodb-primary:
  mongodb-secondary1:
  mongodb-secondary2:
  mongodb-arbiter:

初始化脚本

bash
#!/bin/bash

echo "等待 MongoDB 启动..."
sleep 10

echo "初始化副本集..."
docker exec -i mongodb-primary mongosh -u admin -p password --authenticationDatabase admin <<EOF
rs.initiate({
  _id: "rs0",
  members: [
    { _id: 0, host: "mongodb-primary:27017" },
    { _id: 1, host: "mongodb-secondary1:27017" },
    { _id: 2, host: "mongodb-secondary2:27017" },
    { _id: 3, host: "mongodb-arbiter:27017", arbiterOnly: true }
  ]
})
EOF

echo "副本集初始化完成!"

分片集群部署

基本架构

分片集群组件

  • 配置服务器副本集:存储集群元数据
  • 分片副本集:存储实际数据
  • mongos 路由:处理客户端请求

docker-compose.yml 示例

yaml
version: '3.8'

services:
  # 配置服务器副本集
  configsvr01:
    image: mongo:6.0
    container_name: configsvr01
    command: --configsvr --replSet configReplSet --port 27019
    volumes:
      - configsvr01:/data/db
    ports:
      - "27019:27019"
    restart: unless-stopped

  configsvr02:
    image: mongo:6.0
    container_name: configsvr02
    command: --configsvr --replSet configReplSet --port 27019
    volumes:
      - configsvr02:/data/db
    ports:
      - "27020:27019"
    restart: unless-stopped

  configsvr03:
    image: mongo:6.0
    container_name: configsvr03
    command: --configsvr --replSet configReplSet --port 27019
    volumes:
      - configsvr03:/data/db
    ports:
      - "27021:27019"
    restart: unless-stopped

  # 分片 1 副本集
  shard1svr01:
    image: mongo:6.0
    container_name: shard1svr01
    command: --shardsvr --replSet shard1ReplSet --port 27018
    volumes:
      - shard1svr01:/data/db
    ports:
      - "27022:27018"
    restart: unless-stopped

  shard1svr02:
    image: mongo:6.0
    container_name: shard1svr02
    command: --shardsvr --replSet shard1ReplSet --port 27018
    volumes:
      - shard1svr02:/data/db
    ports:
      - "27023:27018"
    restart: unless-stopped

  shard1svr03:
    image: mongo:6.0
    container_name: shard1svr03
    command: --shardsvr --replSet shard1ReplSet --port 27018
    volumes:
      - shard1svr03:/data/db
    ports:
      - "27024:27018"
    restart: unless-stopped

  # mongos 路由
  mongos01:
    image: mongo:6.0
    container_name: mongos01
    command: mongos --configdb configReplSet/configsvr01:27019,configsvr02:27019,configsvr03:27019 --port 27017
    ports:
      - "27017:27017"
    restart: unless-stopped
    depends_on:
      - configsvr01
      - configsvr02
      - configsvr03

volumes:
  configsvr01:
  configsvr02:
  configsvr03:
  shard1svr01:
  shard1svr02:
  shard1svr03:

初始化步骤

  1. 启动所有容器
  2. 初始化配置服务器副本集
  3. 初始化分片副本集
  4. 将分片添加到集群
  5. 为集合启用分片

容器管理

基本操作

容器生命周期管理

bash
# 查看容器状态
docker ps

# 停止容器
docker stop mongodb

# 启动容器
docker start mongodb

# 重启容器
docker restart mongodb

# 删除容器
docker rm mongodb

# 查看容器日志
docker logs -f mongodb

# 进入容器
docker exec -it mongodb bash

数据管理

bash
# 备份数据
docker exec -it mongodb mongodump -u admin -p password --authenticationDatabase admin --out /backup

# 恢复数据
docker exec -it mongodb mongorestore -u admin -p password --authenticationDatabase admin /backup

# 复制文件到容器
docker cp /host/path/file mongodb:/container/path/

# 从容器复制文件
docker cp mongodb:/container/path/file /host/path/

监控与日志

Docker 监控

bash
# 查看容器资源使用情况
docker stats mongodb

# 查看容器详细信息
docker inspect mongodb

MongoDB 监控

bash
# 连接到 MongoDB
docker exec -it mongodb mongosh -u admin -p password --authenticationDatabase admin

# 查看状态
show dbs
use admin
db.runCommand({ serverStatus: 1 })

日志管理

  • MongoDB 日志默认输出到容器标准输出
  • 可以通过 docker logs 查看
  • 建议配置日志驱动,将日志发送到集中式日志管理系统

最佳实践

生产环境建议

安全配置

  • 启用认证和授权
  • 配置 TLS/SSL 加密
  • 限制容器网络访问
  • 定期更新镜像,应用安全补丁
  • 使用 secrets 管理敏感信息,避免在环境变量中明文存储密码

性能优化

  • 使用 SSD 存储
  • 配置适当的资源限制(CPU、内存)
  • 优化 MongoDB 配置参数
  • 合理设置索引
  • 监控性能指标,及时调整

高可用性

  • 使用副本集部署
  • 配置适当的副本集成员数(建议 3 个或 5 个节点)
  • 考虑跨可用区部署
  • 配置自动故障转移

备份与恢复

定期备份

  • 制定备份策略,包括全量备份和增量备份
  • 验证备份的完整性和可恢复性
  • 存储备份到安全的位置,考虑异地备份
  • 定期测试恢复流程

恢复测试

  • 定期在测试环境中测试恢复流程
  • 记录恢复时间,确保符合 RTO 要求
  • 验证恢复后的数据完整性

常见问题(FAQ)

Q1: Docker 部署的 MongoDB 性能如何?

A1: Docker 部署的 MongoDB 性能接近裸机部署,主要影响因素包括:

  • 存储驱动:建议使用 overlay2 或 zfs
  • 磁盘 I/O:使用 SSD 存储
  • 资源限制:合理配置 CPU 和内存限制
  • 网络:使用桥接网络或主机网络,避免容器网络开销

Q2: 如何在 Docker 中升级 MongoDB 版本?

A2: 升级步骤包括:

  1. 备份现有数据
  2. 拉取新版本镜像
  3. 停止旧容器
  4. 使用新版本镜像启动容器,挂载相同的数据卷
  5. 执行版本升级命令(如 db.adminCommand({ setFeatureCompatibilityVersion: "6.0" })
  6. 验证升级结果

Q3: 如何处理 Docker 容器中的 MongoDB 数据?

A3: 数据管理建议:

  • 使用 Docker 数据卷或绑定挂载持久化数据
  • 定期备份数据卷或挂载目录
  • 考虑使用外部存储系统,如 NFS 或 SAN
  • 避免在容器内直接修改数据文件

Q4: 如何配置 MongoDB 容器的资源限制?

A4: 可以使用 Docker 的资源限制参数:

bash
docker run -d \
  --name mongodb \
  --cpus 4 \
  --memory 16g \
  --memory-swap 32g \
  mongo:6.0

或在 Docker Compose 中配置:

yaml
services:
  mongodb:
    image: mongo:6.0
    deploy:
      resources:
        limits:
          cpus: '4'
          memory: 16g

Q5: 如何在 Docker 中部署 MongoDB Atlas?

A5: MongoDB Atlas 是云托管服务,不需要在 Docker 中部署。如果需要本地模拟 Atlas 环境,可以使用 MongoDB Enterprise 镜像,或考虑使用 MongoDB Atlas Local Development Environment。

Q6: 如何处理 Docker 容器重启后 MongoDB 无法启动的问题?

A6: 常见原因和解决方法:

  • 数据文件损坏:使用备份恢复
  • 配置错误:检查配置文件
  • 权限问题:确保数据目录权限正确
  • 端口冲突:检查端口占用情况
  • 资源不足:调整资源限制

Q7: 如何监控 Docker 中的 MongoDB 集群?

A7: 监控方案:

  • 使用 Docker stats 监控容器资源使用
  • 使用 MongoDB 内置的监控工具(如 mongostat、mongotop)
  • 集成第三方监控工具,如 Prometheus + Grafana
  • 使用 MongoDB Atlas 监控(如果使用 Atlas)

Q8: 如何实现 MongoDB Docker 容器的自动扩展?

A8: 自动扩展方案:

  • 使用 Kubernetes 部署 MongoDB,利用 Kubernetes 的自动扩缩容功能
  • 结合监控系统,当达到特定阈值时自动添加节点
  • 对于分片集群,可以自动添加新分片
  • 考虑使用 MongoDB Atlas,它提供自动扩展功能