文章目錄
使用 Docker Compose 建立有 Auth 的 MongoDB Replica Set
之前在筆記 使用 Docker Compose 建立有 Auth 的 MongoDB Replica Set (Single Node) 紀錄到如何使用 docker compose 建立啟用 auth 機制的單一 node MongoDB Replica Set,但單一 node 的 MongoDB Replica Set 對我來說不太滿足 MongoDB Replica Set 的定義,所以嘗試了三個 nodes ( primary + secondary + secondary) 的做法
基本環境說明
- macOS Catalina 10.15.5
- docker desktop community 2.3.0.3(45519)
docker images
- mongo:4.2.8-bionic
建立方式
建立 keyfile
openssl rand -base64 756 > keyfile chmod 400 keyfile
docker-compose.yaml
version: "3.4" services: mongotmp: container_name: mongotmp image: mongo:4.2.8-bionic volumes: - ./keyfile:/keyfile environment: - MONGO_INITDB_ROOT_USERNAME=${username} - MONGO_INITDB_ROOT_PASSWORD=${password} ports: - 27047:27047 healthcheck: test: [ "CMD", "mongo", "admin", "--port", "27047", "-u", "${username}", "-p", "${password}", "--eval", 'rs.initiate( { _id : "rs0",members: [{ _id: 0,host: "mongotmp:27047" }]});db.getSiblingDB("admin").createUser({user: "${username}",pwd: "${password}",roles: [{role: "userAdminAnyDatabase",db:"admin"},{role: "clusterAdmin",db:"admin"}]})', ] interval: 10s start_period: 10s command: [ "--transitionToAuth", "-keyFile", "/keyfile", "--replSet", "rs0", "--bind_ip_all", "--port", "27047" ] mongo2: container_name: mongo2 image: mongo:4.2.8-bionic volumes: - ./keyfile:/keyfile ports: - 27027:27027 depends_on: - mongotmp healthcheck: test: [ "CMD", "mongo", "--host", "mongotmp", "--port", "27047", "admin", "-u", "${username}", "-p", "${password}", "--eval", 'rs.add( { host: "mongo2:27027"} )', ] interval: 10s start_period: 20s command: [ "-keyFile", "/keyfile", "--replSet", "rs0", "--bind_ip_all", "--port", "27027", ] mongo3: container_name: mongo3 image: mongo:4.2.8-bionic volumes: - ./keyfile:/keyfile ports: - 27037:27037 depends_on: - mongotmp - mongo2 healthcheck: test: [ "CMD", "mongo", "--host", "mongotmp", "--port", "27047", "admin", "-u", "${username}", "-p", "${password}", "--eval", 'rs.add( { host: "mongo3:27037"} )', ] interval: 10s start_period: 30s command: [ "-keyFile", "/keyfile", "--replSet", "rs0", "--bind_ip_all", "--port", "27037", ] mongo1: container_name: mongo1 image: mongo:4.2.8-bionic volumes: - ./keyfile:/keyfile ports: - 27017:27017 depends_on: - mongotmp - mongo2 - mongo3 healthcheck: test: [ "CMD", "mongo", "--host", "mongotmp", "--port", "27047", "admin", "-u", "${username}", "-p", "${password}", "--eval", 'rs.add( { host: "mongo1:27017"} );db.adminCommand( { replSetStepDown: 1,force:true } );', ] interval: 10s start_period: 40s command: [ "-keyFile", "/keyfile", "--replSet", "rs0", "--bind_ip_all" ] remover: container_name: remover image: mongo:4.2.8-bionic volumes: - ./keyfile:/keyfile depends_on: - mongo1 healthcheck: test: /usr/bin/mongo "mongodb://${username}:${password}@mongo1:27017,mongo2:27027,mongo3:27037/admin?replicaSet=rs0" --eval 'rs.remove("mongotmp:27047")' interval: 10s start_period: 45s command: [ "-keyFile", "/keyfile", "--replSet", "rs0", "--bind_ip_all" ]
直接使用 docker compose 啟動
如果想要移除中繼 container ,請直接跳至
步驟 4
或是執行此步驟後手動移除語法
username={username} password={password} docker-compose up -d
範例
username=root password=pass.123 docker-compose up -d
(optional) 將移除非必要 container 包裝成 shell
把中介性質的 container 停掉,不在意資源使用狀況的話,這個步驟可以直接略過
start.sh
請記得將 username 與 password 換成需要的值
語法
username={username} password={password} docker-compose up -d sleep 50 docker-compose stop mongotmp remover
範例
chmod 400 keyfile username=root password=pass.123 docker-compose up -d sleep 50 docker-compose stop mongotmp remover
啟動 mongodb replica set
sh ./start.sh
實際使用
沒有提供 auth,無法取得 replica set 資訊
提供 auth 資訊,可以看到 replica set 已有三個 member
心得
完整程式碼請參考 yowko/docker-compose-mongodb-replica-set-with-auth
經同事測試後提醒,直接下載完整程式碼如果沒有重新產生 keyfile,如果是自行執行
docker-compose up
,請記得調整下載的 keyfile 權限chmod 400 keyfile
(這個動作已加入start.sh
)
雖然 mongo 用了好多年了,但每次遇到 mongo 不論是什麼角色,mongo 還是常常讓我覺得棘手,這次也一樣:反覆看著官方文件,還是不知道問題出在哪兒、該如何解決XD
以下簡單說明這份 docker-compose 的意圖
mongotmp
- 有基本的 user、password
- 建立 replica set
- 建立 admin 與 clusteradmin user 用
- 啟動時使用
keyfile
做為後續 member 驗證 transitionToAuth
讓後續 member 可以不驗證,但這個參數只要存在就會讓 mongo 可以不驗證
mongo 2, mongo3
- 在 healthcheck 時連線至 mongotmp 加入 replica set
mongo 1
- 在 healthcheck 時連線至 mongotmp 加入 replica set 並將 mongotmp 降級 (primary –> secondary)
remover
- 將 mongotmp 自 replica set 中移除 (讓所有 member 再沒有
transitionToAuth
以完全啟用 auth)
- 將 mongotmp 自 replica set 中移除 (讓所有 member 再沒有
最後將完成階段性任務的
mongotmp
與remover
兩個 docker-compose service 移除
說實話個人覺得寫得不是很漂亮,但這是目前可以完成目標的最佳解法,暫時先這樣,待日後想到其他方式再來更新囉
參考資訊
文章作者 Yowko Tsai
上次更新 2020-12-11
授權合約
本部落格 (Yowko's Notes) 所有的文章內容(包含圖片),任何轉載行為,必須通知並獲本部落格作者 (Yowko Tsai) 的同意始得轉載,且轉載皆須註明出處與作者。
Yowko's Notes 由 Yowko Tsai 製作,以創用CC 姓名標示-非商業性-相同方式分享 3.0 台灣 授權條款 釋出。