likes
comments
collection
share

MongoDB 云数据库太贵玩不起?来,教你如何用 Docker 轻松搭建!

作者站长头像
站长
· 阅读数 6

大家好,我是杨成功。

月初出版了一本书《前端开发实战派》,书中全栈开发的部分,使用 Express + MongoDB 编写接口,完成后部署在 Serverless 上。

我想既然接口跑在 Serverless 上,索性数据库也买一个 MongoDB 云数据库吧,这样大家完全不需要买服务器自己部署,对前端来说门槛更低。

然后我找到了云数据库,看到价格傻眼了:

MongoDB 云数据库太贵玩不起?来,教你如何用 Docker 轻松搭建!

确实买不起啊,还是我自己搭建吧。还好我有好基友 Docker,搭建一个 MongoDB 不费事。

目前 MongoDB 最新版本是 7.x,我们用上一个版本 6.x。

运行容器启动 MongoDB

安装 Docker 大家直接从 官网 下载安装就可以了,测试的话在本地装一个 Docker Desktop 很方便。

(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 命令查看容器列表:

MongoDB 云数据库太贵玩不起?来,教你如何用 Docker 轻松搭建!

图中圈住的地方就是容器ID,接着进入这个容器,并连接数据库:

$ docker exec -it <container_id>  /bin/bash
$ mongosh  # 进入数据库,不需要用户名

mongosh 是从 MongoDB 4.2 开始推出的 shell 工具,取代了之前的 mongo 命令,用于执行数据库的操作,这里要留意一下。

MongoDB 云数据库太贵玩不起?来,教你如何用 Docker 轻松搭建!

上图可以看到,默认连接到了 test 数据库。

现在切换到 admin 数据库(身份验证数据库),创建一个超级用户:

$ use admin # 切换数据库
$ db.createUser({
  user:'root',
  pwd:'mongo_root_pass',
  roles:[{
    role:'root',
    db:'admin'
  }]
})

接下来使用这个用户登录 MongoDB,就可以执行“创建数据库、创建用户”等操作了。

启动容器并创建用户

上一步我们先启动容器,然后再创建超级用户,实际上这两个步骤可以一次完成。

在运行容器时,如果传入下面的两个环境变量:

  • 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 启动之后,便自动创建了超级用户。

启动时自动执行脚本

默认的 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(),等同于 use 命令。

因此,在 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 指定脚本在某个数据库下执行。

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

客户端连接到 MongoDB

在启动 MongoDB 时,传入 --auth 参数表示开启授权验证,不传则不开启。

如果未开启授权验证,连接 MongoDB 不需要账号密码,连接 URL 如下:

mongodb://127.0.0.1:27017

如果开启授权验证,则连接 URL 中必须指定数据库、账号、密码,如下:

mongodb://user:pass@127.0.0.1:27017/dbname

在《前端开发实战派》的项目中使用 mongoose 连接数据库,有了上面的 url 和用户名密码,连接方法如下:

const mongoose = require('mongoose')

mongoose.connect('mongodb://127.0.0.1:27017/dbname', {
   user: 'username',
   pass: 'password',
}).then(() => {
   console.log('数据库连接成功:')
}).catch(err => {
   console.log('数据库连接失败:', err)
})

总结

前面我们从 MongoDB 的安装、运行配置、授权验证等方面,全面介绍了如何用 Docker 将 MongoDB 运行起来,并在项目中连接使用。

更多系列文章,请查看我的公众号 程序员成功