MongoDB 云數(shù)據(jù)庫太貴了,試一下用 Docker 安裝,也不是很難
我想既然接口跑在 Serverless 上,索性數(shù)據(jù)庫也買一個(gè) MongoDB 云數(shù)據(jù)庫吧,這樣大家完全不需要買服務(wù)器自己部署,對(duì)前端來說門檻更低。
然后我找到了云數(shù)據(jù)庫,看到價(jià)格傻眼了:
確實(shí)買不起啊,還是我自己搭建吧。還好我有好基友 Docker,搭建一個(gè) MongoDB 不費(fèi)事。
目前 MongoDB 最新版本是 7.x,我們用上一個(gè)版本 6.x。
運(yùn)行容器啟動(dòng) MongoDB
安裝 Docker 大家直接從 官網(wǎng) 下載安裝就可以了,測(cè)試的話在本地裝一個(gè) Docker Desktop 很方便。
(1)拉取 MongoDB 的官方鏡像:
$ docker pull mongo:6
(2)在宿主環(huán)境中創(chuàng)建兩個(gè)目錄,作為容器數(shù)據(jù)卷:
/docker/mongodb/data/ #數(shù)據(jù)庫數(shù)據(jù)目錄
/docker/mongodb/dump/ #備份數(shù)據(jù)目錄
(3)執(zhí)行命令,把 MongoDB 容器運(yùn)行起來:
$ 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
上面的幾個(gè)重要參數(shù)說明一下:
- --restart=always:容器退出時(shí)自動(dòng)重啟,這個(gè)很有用。
- 27017:用于連接 MongoDB 的端口。
- --auth:開啟授權(quán)驗(yàn)證。
- -d:后臺(tái)運(yùn)行,要加。
運(yùn)行成功后,使用 docker ps 命令查看容器列表:
圖中圈住的地方就是容器ID,接著進(jìn)入這個(gè)容器,并連接數(shù)據(jù)庫:
$ docker exec -it <container_id> /bin/bash
$ mongosh # 進(jìn)入數(shù)據(jù)庫,不需要用戶名
mongosh 是從 MongoDB 4.2 開始推出的 shell 工具,取代了之前的 mongo 命令,用于執(zhí)行數(shù)據(jù)庫的操作,這里要留意一下。
上圖可以看到,默認(rèn)連接到了 test 數(shù)據(jù)庫。
現(xiàn)在切換到 admin 數(shù)據(jù)庫(身份驗(yàn)證數(shù)據(jù)庫),創(chuàng)建一個(gè)超級(jí)用戶:
$ use admin # 切換數(shù)據(jù)庫
$ db.createUser({
user:'root',
pwd:'mongo_root_pass',
roles:[{
role:'root',
db:'admin'
}]
})
接下來使用這個(gè)用戶登錄 MongoDB,就可以執(zhí)行“創(chuàng)建數(shù)據(jù)庫、創(chuàng)建用戶”等操作了。
啟動(dòng)容器并創(chuàng)建用戶
上一步我們先啟動(dòng)容器,然后再創(chuàng)建超級(jí)用戶,實(shí)際上這兩個(gè)步驟可以一次完成。
在運(yùn)行容器時(shí),如果傳入下面的兩個(gè)環(huán)境變量:
- MONGO_INITDB_ROOT_USERNAME:用戶名
- MONGO_INITDB_ROOT_PASSWORD:密碼
MongoDB 會(huì)自動(dòng)在 admin 數(shù)據(jù)庫中創(chuàng)建該用戶,指定角色為 root,并自動(dòng)啟用身份驗(yàn)證(--auth)。
所以上面的運(yùn)行容器命令可以優(yōu)化為這樣:
$ 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 啟動(dòng)之后,便自動(dòng)創(chuàng)建了超級(jí)用戶。
啟動(dòng)時(shí)自動(dòng)執(zhí)行腳本
默認(rèn)的 admin 數(shù)據(jù)庫用于身份驗(yàn)證。當(dāng)真正存儲(chǔ)數(shù)據(jù)時(shí),需要?jiǎng)?chuàng)建一個(gè)新的數(shù)據(jù)庫。
創(chuàng)建數(shù)據(jù)庫和用戶需要權(quán)限,一般我們會(huì)用超級(jí)用戶登錄到 admin 數(shù)據(jù)庫,然后再創(chuàng)建其他數(shù)據(jù)庫和用戶,如下:
$ docker exec -it <container_id> /bin/bash # 進(jìn)入容器
$ mongosh admin --username root --password mongo_root_pass # 登錄 admin 數(shù)據(jù)庫
$ use test_db # 創(chuàng)建/切換數(shù)據(jù)庫
然而如果是在 CI(自動(dòng)化部署)環(huán)境中,我們希望 MongoDB 啟動(dòng)后自動(dòng)創(chuàng)建需要的數(shù)據(jù)庫和用戶,而不是每次都要手動(dòng)創(chuàng)建,這時(shí)應(yīng)該怎么辦呢?
這時(shí)候要借助一個(gè) Docker 下的特殊目錄:docker-entrypoint-init.d。
該目錄下可以自定義腳本文件,在容器第一次啟動(dòng)時(shí)自動(dòng)執(zhí)行。mongo 鏡像可以識(shí)別該目錄下的 .sh 和 .js 文件,并按照順序執(zhí)行。
那么我們就在 /docker/mongodb 目錄下創(chuàng)建一個(gè) mongo-init.js 文件,并在運(yùn)行容器時(shí)掛載:
-v /docker/mongodb/mongo-init.js:/docker-entrypoint-initdb.d/mongo-init.js
現(xiàn)在在該文件中編寫初始化邏輯,比如創(chuàng)建一個(gè)用戶:
// mongo-init.js
db.createUser({
user: 'test_user',
pwd: 'test_pass',
roles: [
{
role: 'dbOwner',
db: 'test_db',
},
],
});
提示:docker-entrypoint-init.d 目錄下的腳本只會(huì)在第一次運(yùn)行容器的時(shí)候執(zhí)行。如果通過 -v 掛載過數(shù)據(jù),那么就不是第一次??梢匀サ?-v 模擬第一次運(yùn)行。
上面的 JS 文件中可以訪問 db 對(duì)象,因?yàn)樗?nbsp;mongosh 環(huán)境下執(zhí)行。默認(rèn)情況下,db 代表 “test” 數(shù)據(jù)庫。
如果我們要切換數(shù)據(jù)庫,命令是 use <db_name>。然而在 JS 文件中,顯然這種語法是不支持的。
關(guān)于如何在 JS 文件中切換數(shù)據(jù)庫,我找了很多方法,翻了一整天的文檔,終于找到了。
就是它:db.getSiblingDB(),等同于 use 命令。
因此,在 test_db 數(shù)據(jù)庫中創(chuàng)建/切換用戶,可以修改如下:
db = db.getSiblingDB('test_db');
db.createUser({
user: 'test_user',
pwd: 'test_pass',
roles: [
{
role: 'dbOwner',
db: 'test_db',
},
],
});
通過 db.getSiblingDB() 方法,我們可以在 JS 腳本中創(chuàng)建多個(gè)數(shù)據(jù)庫和用戶。
如果你不想在 JS 代碼中創(chuàng)建/切換數(shù)據(jù)庫,更簡單的方法是,用環(huán)境變量 MONGO_INITDB_DATABASE 指定腳本在某個(gè)數(shù)據(jù)庫下執(zhí)行。
Docker Compose 運(yùn)行
如果你覺得運(yùn)行容器的命令太長,那么使用 Docker Compose 也是一個(gè)不錯(cuò)的選擇。
首先創(chuàng)建 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'
然后運(yùn)行啟動(dòng)命令:
$ docker compose up -d
客戶端連接到 MongoDB
在啟動(dòng) MongoDB 時(shí),傳入 --auth 參數(shù)表示開啟授權(quán)驗(yàn)證,不傳則不開啟。
如果未開啟授權(quán)驗(yàn)證,連接 MongoDB 不需要賬號(hào)密碼,連接 URL 如下:
mongodb://127.0.0.1:27017
如果開啟授權(quán)驗(yàn)證,則連接 URL 中必須指定數(shù)據(jù)庫、賬號(hào)、密碼,如下:
mongodb://user:pass@127.0.0.1:27017/dbname
在《前端開發(fā)實(shí)戰(zhàn)派》的項(xiàng)目中使用 mongoose 連接數(shù)據(jù)庫,有了上面的 url 和用戶名密碼,連接方法如下:
const mongoose = require('mongoose')
mongoose.connect('mongodb://127.0.0.1:27017/dbname', {
user: 'username',
pass: 'password',
}).then(() => {
console.log('數(shù)據(jù)庫連接成功:')
}).catch(err => {
console.log('數(shù)據(jù)庫連接失?。?, err)
})
現(xiàn)在,你可以在我的開源項(xiàng)目 仿掘金博客系統(tǒng) 中添加自己的數(shù)據(jù)庫配置,項(xiàng)目就可以運(yùn)行起來了。
總結(jié)
前面我們從 MongoDB 的安裝、運(yùn)行配置、授權(quán)驗(yàn)證等方面,全面介紹了如何用 Docker 將 MongoDB 運(yùn)行起來,并在項(xiàng)目中連接使用。