文章目錄
MongoDB cli 中的 try catch
這是在調整團隊 MongoDB instance 時遇到的問題:某一隻 js 會在 db init 時執行 create user 的動作,完成後會繼續建立其他 collection 跟 index,但因為這個 user 是跨 db 的 user ,已經被其他 db init 建立過了,所以打算透過 try catch 來處理:create user 失敗就改用 grant 的方式來讓 user 有權限
基本環境說明
- macOS Monterey 12.1
- docker desktop 4.3.2 (72729)
docker images
- mongo:4.4.11
建立測試環境
init/0.js
use admin; db.createUser( { user: "backupuser", pwd: "pass.123", roles: [ { role: "readWrite", db: "demo" } ] } );
init/1.js
use admin; db.createUser( { user: "backupuser", pwd: "pass.123", roles: [ { role: "readWrite", db: "test" } ] } );
mongo-init.sh
#! /bin/bash init_mongodb(){ for file in /tmp/mongo/*.js; do echo $file mongo -u $MONGO_INITDB_ROOT_USERNAME -p $MONGO_INITDB_ROOT_PASSWORD < $file done } main(){ echo "init_data" init_mongodb } main "$@"
docker-compose
version: '3.1' services: mongo: image: mongo:4.4.11 restart: always environment: MONGO_INITDB_ROOT_USERNAME: root MONGO_INITDB_ROOT_PASSWORD: pass.123 volumes: - ${PWD}/init:/tmp/mongo - ${PWD}/mongo-init.sh:/docker-entrypoint-initdb.d/mongo-init.sh
錯誤訊息
訊息內容
mongo_1 | uncaught exception: Error: couldn't add user: User "backupuser@admin" already exists : mongo_1 | _getErrorWithCode@src/mongo/shell/utils.js:25:13 mongo_1 | DB.prototype.createUser@src/mongo/shell/db.js:1386:11 mongo_1 | @(shell):1:1 mongo_1 | bye
錯誤截圖
解決方式:在 mongo shell 中使用 try catch
調整啟動方式
1-1. init/0.js
db = db.getSiblingDB("admin") try { db.createUser( { user: "backupuser", pwd: "pass.123", roles: [ { role: "readWrite", db: "demo" } ] } ); } catch (err) { print ("backupuser user already created"); db.grantRolesToUser( "backupuser", [ { role: "readWrite", db: "demo" }] ); }
1-2. init/1.js
db = db.getSiblingDB("admin") try { db.createUser( { user: "backupuser", pwd: "pass.123", roles: [ { role: "readWrite", db: "test" } ] } ); } catch (err) { print ("backupuser user already created"); db.grantRolesToUser( "backupuser", [ { role: "readWrite", db: "test" }] ); }
1-3. docker-compose
version: '3.1' services: mongo: image: mongo:4.4.11 restart: always environment: MONGO_INITDB_ROOT_USERNAME: root MONGO_INITDB_ROOT_PASSWORD: pass.123 volumes: - ${PWD}/init:/docker-entrypoint-initdb.d/
調整 js 寫法
2-1. init/0.js
use admin; initFunction= { start: function(){ try { db.createUser( { user: "backupuser", pwd: "pass.123", roles: [ { role: "readWrite", db: "demo" } ] } ); } catch (err) { print(err); db.grantRolesToUser( "backupuser", [ { role: "readWrite", db: "demo" }] ); } } } initFunction.start();
2-2. init/1.js
use admin; initFunction= { start: function(){ try { db.createUser( { user: "backupuser", pwd: "pass.123", roles: [ { role: "readWrite", db: "test" } ] } ); } catch (err) { print(err); db.grantRolesToUser( "backupuser", [ { role: "readWrite", db: "test" }] ); } } } initFunction.start();
心得
如果是 for docker image 的 init 使用 mongodb image 預設的 MONGO_INITDB_DATABASE 機制:調整啟動方式
會單純許多
但如果想要讓 container 與實體 mongodb instance 行為一致,就可以參考使用 調整 js 寫法
修改前
修改後
參考資訊
文章作者 Yowko Tsai
上次更新 2022-01-16
授權合約
本部落格 (Yowko's Notes) 所有的文章內容(包含圖片),任何轉載行為,必須通知並獲本部落格作者 (Yowko Tsai) 的同意始得轉載,且轉載皆須註明出處與作者。
Yowko's Notes 由 Yowko Tsai 製作,以創用CC 姓名標示-非商業性-相同方式分享 3.0 台灣 授權條款 釋出。