oldme 博客

毛血日益衰,志气日益微,几何不从汝而死也

MongoDb 的基础概念和部署(基于Docker)

oldme create: 2023-06-19

本文主打一个超详细的介绍,跟着做一定 ok。MongoDb 是非关系数据库中最像关系数据库的,MongoDb 是面向文档储存的数据库,操作起来较为简单。刚开始学习 MongoDb 的地方在于它的用户权限认证,我会在此文尽量简单的说明它,并且使用 Dokcer 来部署和使用它。

本文需要你掌握:Dokcer,Docker-compose,Navicat

舞台布置

在下的舞台环境如下:

  • Ubuntu 22.04.2-Server
  • Docker 24.0.2
  • Docker-compose 2.18.1
  • MongoDB 5.0.5 (基于 mongo 最新镜像)

安装 mongo

在 /home/docker/mongo 下建立 docker-compose.yml:

version: "3.7"

services:
  mongo:
    container_name: mongo
    image: mongo
    restart: always
    ports:
      - 27017:27017
    environment:
      # 设置时区
      TZ: CST-8

进入 /home/docker/mongo 目录,执行命令:

docker-compose up -d

执行命令成功后即可安装成功:

使用 navicat 连接它:

这个时候打开连接,会发现其中有三个数据库:

如果你的 navicat 没有显示这三个数据库,那有可能是隐藏了,在菜单栏->查看->显示隐藏项目打开就行:

这三个数据库是 mongo 内置的,运行所必须的,他们的作用如下:

  • admin:是 MongoDB 的默认管理数据库,它用于管理 MongoDB 实例和执行一些系统级别的操作。在 admin 数据库中,可以进行用户管理、权限设置、备份和恢复操作以及监控数据库状态等管理任务。
  • local:主要用于存储与单个 MongoDB 实例相关的本地数据。它通常包含复制集中的操作日志(oplog),用于支持数据复制和故障恢复。此外,一些临时数据也可以存储在 local 数据库中。
  • config:是MongoDB的分片配置数据库,用于存储与分片集群相关的元数据信息。当 MongoDB 部署为分片集群时,config 数据库记录了分片集群的配置信息,包括分片键、分片的位置、副本集配置等。

这个时候或许你会抛出一个疑问:连接 mongo 不需要用户认证吗?还真就是,mongo 和 redis 一样,默认是不需要用户认证的。但在实际的业务中,mongo 还是要设置用户认证的,不然岂不是知道了 IP 和端口就能为所欲为了。当然,这里有句题外话,数据库的端口最好不要暴露在公网上,否则将带来巨大的安全隐患。

用户权限和角色权限

在正式使用 mongo 之前,我们先来认识一下它如何开启用户认证、如何创建用户。mongo 的用户权限较为复杂,笔者这里会尽量的简化它,等到对 mongo 整体有了清晰的认识后,再回来高屋建瓴的学习它,将会轻松许多。

创建超级管理员

要管理和使用 mongo,前提条件是有一个超级管理员用户,这个用户可以管理其他用户,其所在的数据库必须是 admin。进入 mongo 容器创建超级管理员:

# 进入 mongo 容器
docker exec -it mongo bash
# 进入 mongo 命令行模式
mongo

此时你会看到这样的信息:

接着输入如下命令:

# 使用 admin 数据库
use admin
# 显示结果:switched to db admin
# 创建超级管理员用户
db.createUser({user: "root", pwd: "123456", roles:[{role: "root", db: "admin"}]})
# 显示结果:
Successfully added user: {
	"user" : "root",
	"roles" : [
		{
			"role" : "root",
			"db" : "admin"
		}
	]
}

db.createUser 后面的参数是一个 json:

  • user: 用户名
  • pws: 密码
  • roles.role: 指定用户的角色
  • roles.db: 角色授予的数据库,通俗的说,该用户能管理那个数据库就写哪个

内置的常用的 roles.role 如下:

角色 权限描述
read 允许用户读取指定数据库
readWrite 允许用户读写指定数据库
dbAdmin 允许用户在指定数据库中执行管理函数,如索引创建、删除,查看统计或访问system.profile
userAdmin 允许用户向system.users集合写入,可以找指定数据库里创建、删除和管理用户
clusterAdmin 只在admin数据库中可用,赋予用户所有分片和复制集相关函数的管理权限
readAnyDatabase 只在admin数据库中可用,赋予用户所有数据库的读权限
readWriteAnyDatabase 只在admin数据库中可用,赋予用户所有数据库的读写权限
userAdminAnyDatabase 只在admin数据库中可用,赋予用户所有数据库的userAdmin权限
dbAdminAnyDatabase 只在admin数据库中可用,赋予用户所有数据库的dbAdmin权限
backup 允许用户执行备份操作,包括创建和还原数据库备份
restore 允许用户执行还原操作,用于还原数据库备份
root 只在admin数据库中可用。超级权限,是readWriteAnyDatabase、dbAdminAnyDatabase、userAdminAnyDatabase、clusterAdmin、restore和backup联合之后所有的权限

超级管理员创建好之后,就可以使用它登录了,但是你先别急着尝试,我们还有更优雅的做法。

优雅的创建超级管理员

对于这种搭建环境后还要啪啪的输入一堆命令的操作,想必看着都烦,Docker 在这个时候的作用就体现出来了:一次打包,处处运行。修改我们的 docker-compose.yml:

version: "3.7"

services:
  mongo:
    container_name: mongo
    image: mongo
    restart: always
    ports:
      - 27017:27017
    # 必要,强制权限认证
    command: [--auth]
    environment:
      TZ: CST-8
      # 超级管理员用户名
      MONGO_INITDB_ROOT_USERNAME: root
      # 超级管理员密码
      MONGO_INITDB_ROOT_PASSWORD: 123456

MONGO_INITDB_ROOT_USERNAMEMONGO_INITDB_ROOT_PASSWORD 这两个环境变量用于辅助我们建立一个超级管理员。重新建立容器,再登录就需要验证了:

如果这里的验证还选择 none 时,尝试打开连接,将会抛出一个需要权限的错误提示:

创建一个普通的数据库

admin 数据库和超级管理员一般不用做实际业务上的数据存储,我们需要建立一个普通的数据库和用户来操作数据。进入 mongo 容器来建立一个普通用户:

# 进入 mongo 容器
docker exec -it mongo bash
# 进入 mongo 命令行模式
mongo

先进入 admin 数据库完成超级管理员的认证:

创建一个名为 oldme 的数据库:

# use 命令可以切换数据库,如果切换的数据库不存在会自动创建它
use oldme

创建一个具有读写权限的普通用户 newton:

db.createUser({ user: "newton", pwd: "123456", roles: [ { role: "readWrite", db: "oldme" } ]})

navicat 测试:

数据库里面没有集合在 navicat 中打开连接是什么都不显示的,所以看见 navicat 中什么都不显示不要慌张,它不是部署失败了奥。想要看到具体的效果,回到 ssh 执行命令创建一个集合即可:

db.createCollection("user")

优雅的创建的普通管理员

创建超级管理员在 docker-compose.yml 中里面配置一下就好了,很优雅。那普通管理员有没有类似的方法呢,虽然 mongo 镜像没有我们准备,但是我们还是可以曲线救国的。怎么做呢,由于MongoDb 除了能使用 shell 管理外,还可以使用 javascript 脚本来管理,我们预先准备一个 sh 脚本,然后用它来执行 js 脚本,就可以达到我们的目的。做法如下:创建一个名为 mongo-init.sh 的文件,放在宿主机的任意目录下,键入以下固定内容:

mongo -- "admin" <<EOF
db.auth("$MONGO_INITDB_ROOT_USERNAME", "$MONGO_INITDB_ROOT_PASSWORD")
db = db.getSiblingDB("$MONGO_INITDB_DATABASE")
db.createUser({
  user: "$MONGO_USERNAME",
  pwd: "$MONGO_PASSWORD",
  roles: [
  { role: "readWrite", db: "$MONGO_INITDB_DATABASE" }
  ]
})
EOF

然后在 docker-compose.yml 中把所需的环境变量赋值并且配置数据卷:

version: "3.7"

services:
  mongo:
    container_name: mongo
    image: mongo
    restart: always
    ports:
      - 27017:27017
    # 加上权限认证
    command: [--auth]
    environment:
      TZ: CST-8
      MONGO_INITDB_ROOT_USERNAME: root
      MONGO_INITDB_ROOT_PASSWORD: 123456
      MONGO_INITDB_DATABASE: oldme
      MONGO_USERNAME: newton
      MONGO_PASSWORD: 123456
    volumes:
     # 将sh脚本映射到/docker-entrypoint-initdb.d目录下,容器初始化时会自动执行
      - /home/docker/mongo/mongo-init.sh:/docker-entrypoint-initdb.d/mongo-init.sh

使用新的 docker-compose.yml 文件重建容器,重建的 MongoDb 里面会有一个已经创建好的数据库:oldme,这个数据库会有一个具备读写权限的管理员:newton。

数据映射

在容器销毁时,mongo 容器的数据会丢失,我们可以配置数据卷映射,将 mongo 容器中的数据文件映射到宿主机上,修改 docker-compose.yml,增加一个数据卷映射:

version: "3.7"

services:
  mongo:
    container_name: mongo
    image: mongo
    restart: always
    ports:
      - 27017:27017
    # 加上权限认证
    command: [--auth]
    environment:
      TZ: CST-8
      MONGO_INITDB_ROOT_USERNAME: root
      MONGO_INITDB_ROOT_PASSWORD: 123456
      MONGO_INITDB_DATABASE: oldme
      MONGO_USERNAME: newton
      MONGO_PASSWORD: 123456
    volumes:
      - /home/docker/mongo/mongo-init.sh:/docker-entrypoint-initdb.d/mongo-init.sh
      # 将数据放在宿主机的/home/docker/mongo/data中
      - /home/docker/mongo/data:/data/db

重新创建容器,即可在宿主机中看见 mongo 的数据文件:

这样下次再销毁重建,所有的数据都会重新映射到容器中。

评论

欢迎您的回复 取消回复

您的邮箱不会显示出来,*必填

本文目录