11.5 安装 MongoDB
上一节介绍了 MongoDB 基础,如果你有一台 MongoDB 云数据库,可以绕过本节搭建的步骤。
如果没有,在电脑本地借助 Docker 搭建也不费事。请确保本地有 Docker 环境。
安装 Docker 大家直接从 官网 下载安装就可以了,测试的话在本地装一个 Docker Desktop 很方便。
MongoDB 目前最新版本是 7.x,我们用上一个更稳定的版本 6.x。
11.5.1 启动 MongoDB 容器
(1)拉取 MongoDB 的官方镜像:
$ docker pull mongo:6
(2)在宿主环境中创建两个目录,作为容器数据卷:
/docker/mongodb/data/ #数据库数据目录
/docker/mongodb/dump/ #备份数据目录
(3)执行命令,把 MongoDB 容器运行起来::
$ docker run --name mongodb \
--restart=always \
-p 27017:27017 \
-v /docker/mongodb/data:/data/db \
-v /docker/mongodb/dump:/var/dump \
-d mongo:6 --auth
上面的几个重要参数说明一下:
--restart=always
:容器退出时自动重启,这个很有用。27017
:用于连接 MongoDB 的端口。--auth
:开启授权验证。-d
:后台运行,必须加上。
运行成功后,使用 docker ps
命令查看容器列表:
图中圈住的地方就是容器 ID,是容器的唯一标识,后面会用到。
(4)进入这个容器,并连接数据库:
$ docker exec -it <container_id> /bin/bash
$ mongosh # 进入数据库,不需要用户名
mongosh 是从 MongoDB 4.2 开始推出的 shell 工具,取代了之前的 mongo 命令,用于执行数据库的操作,这里要留意一下。
上图可以看到,默认连接到了 test 数据库。
(5)切换到 admin 数据库(身份验证数据库),创建一个超级用户:
$ use admin
$ db.createUser({
user:'root',
pwd:'mongo_root_pass',
roles:[{
role:'root',
db:'admin'
}]
})
后面使用这个用户登录 MongoDB,就可以执行“创建数据库、创建用户”等操作了。
11.5.2 启动容器并创建用户
上一步我们先启动容器,然后再创建超级用户,实际上这两个步骤可以一次完成。
在运行容器时,如果传入下面的两个环境变量:
MONGO_INITDB_ROOT_USERNAME
:用户名。MONGO_INITDB_ROOT_PASSWORD
:密码。
MongoDB 会自动在 admin 数据库中创建该用户,指定角色为 root,并自动启用身份验证(--auth)。
所以上面的运行容器命令可以优化为这样:
$ docker run --name mongodb \
--restart=always \
-p 27017:27017 \
-v /docker/mongodb/data:/data/db \
-v /docker/mongodb/dump:/var/dump \
-e MONGO_INITDB_ROOT_USERNAME=root \
-e MONGO_INITDB_ROOT_PASSWORD=mongo_root_pass \
-d mongo:6
这样 MongoDB 启动之后,便自动创建了超级用户。
11.5.3 启动时初始化
默认的 admin 数据库用于身份验证。当真正存储数据时,需要创建一个新的数据库。
创建数据库和用户需要权限,一般我们会用超级用户登录到 admin 数据库,然后再创建其他数据库和用户,如下:
$ docker exec -it <container_id> /bin/bash # 进入容器
$ mongosh admin --username root --password mongo_root_pass # 登录 admin 数据库
$ use test_db # 创建/切换数据库
然而如果是在 CI(自动化部署)环境中,我们希望 MongoDB 启动后自动创建需要的数据库和用户,而不是每次都要手动创建,这时应该怎么办呢?
这时候要借助一个 Docker 下的特殊目录:docker-entrypoint-init.d
。
该目录下可以自定义脚本文件,在容器第一次启动时自动执行。mongo
镜像可以识别该目录下的 .sh
和 .js
文件,并按照顺序执行。
那么我们就在 /docker/mongodb 目录下创建一个 mongo-init.js
文件,并在运行容器时挂载:
-v /docker/mongodb/mongo-init.js:/docker-entrypoint-initdb.d/mongo-init.js
现在在该文件中编写初始化逻辑,比如创建一个用户:
// mongo-init.js
db.createUser({
user: "test_user",
pwd: "test_pass",
roles: [
{
role: "dbOwner",
db: "test_db",
},
],
});
提示:docker-entrypoint-init.d 目录下的脚本只会在第一次运行容器的时候执行。如果通过 -v 挂载过数据,那么就不是第一次。可以去掉 -v 模拟第一次运行。
上面的 JS 文件中可以访问 db
对象,因为它在 mongosh
环境下执行。默认情况下,db 代表 “test” 数据库。
如果我们要切换数据库,命令是 use <db_name>
。然而在 JS 文件中,显然这种语法是不支持的。
关于如何在 JS 文件中切换数据库,我找了很多方法,最终发现可以用 db.getSiblingDB()
方法替代。
因此,在 test_db 数据库中创建/切换用户,可以修改如下:
db = db.getSiblingDB("test_db");
db.createUser({
user: "test_user",
pwd: "test_pass",
roles: [
{
role: "dbOwner",
db: "test_db",
},
],
});
通过 db.getSiblingDB()
方法,我们可以在 JS 脚本中创建多个数据库和用户。
如果你不想在 JS 代码中创建/切换数据库,也可以用环境变量 MONGO_INITDB_DATABASE
指定脚本在某个数据库下执行。
11.5.4 Docker Compose 运行
如果你觉得运行容器的命令太长,那么使用 Docker Compose 也是一个不错的选择。
首先创建 compose.yml
配置文件如下:
version: "3.1"
services:
mongodb:
image: mongo:6
restart: always
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: mongo_root_pass
MONGO_INITDB_DATABASE: test_db
volumes:
- "/docker/mongodb/data:/data/db"
- "/docker/mongodb/dump:/var/dump"
- "/docker/mongodb/mongo-init.js:/docker-entrypoint-initdb.d/mongo-init.js"
然后运行启动命令:
$ docker compose up -d
11.5.5 客户端连接到 MongoDB
在启动 MongoDB 时,传入 --auth
参数表示开启授权验证,不传则不开启。
如果未开启授权验证,连接 MongoDB 不需要账号密码,连接 URL 如下:
mongodb://127.0.0.1:27017
如果开启授权验证,则连接 URL 中必须指定数据库、账号、密码,如下:
mongodb://user:pass@127.0.0.1:27017/dbname
有了上面的 url 和用户名密码,下一节我们介绍具体连接该数据库的方法。