Danh mục:
Đây là bài thực hành cấu hình MongoDB Replica Set (Bộ bản sao) bằng Docker Compose, tự động chạy lệnh
rs.initiate() và liên kết với giao diện quản lý (mongo-express).Các thành phần chính
-
mongo1,mongo2,mongo3: 3 node MongoDB cấu thành nên Replica Set. -
mongo-express: Công cụ quản trị MongoDB dựa trên giao diện web. -
replica-init: Một container chạy một lần để thực hiện khởi tạo cụm (cluster).
Cấu trúc thư mục
├── docker-compose.yml
├── .env
├── secrets/
│ └── mongo.key # file khóa xác thực cho replica set
├── mongo-init/
│ └── init-replica.sh # script tự động khởi tạo cluster
└── mongo-express/
├── Dockerfile # bao gồm tính năng wait-for
└── wait-for.sh
Ví dụ file .env
snippet MONGO_INITDB_ROOT_USERNAME=root MONGO_INITDB_ROOT_PASSWORD=example ME_CONFIG_MONGODB_ADMINUSERNAME=root ME_CONFIG_MONGODB_ADMINPASSWORD=example ME_CONFIG_BASICAUTH_USERNAME=admin ME_CONFIG_BASICAUTH_PASSWORD=admin MONGODB_URI=mongodb://root:example@mongo1:27017/?replicaSet=rs0
secrets/mongo.key
# Cách tạo openssl rand -base64 756 > secrets/mongo.key chmod 400 secrets/mongo.key
docker-compose.yml
version: "3.9" services: mongo1: image: mongo:6.0 container_name: mongo1 ports: - "27017:27017" volumes: - ./data/mongo1:/data/db - ./secrets/mongo.key:/etc/mongo.key:ro environment: - MONGO_INITDB_ROOT_USERNAME= - MONGO_INITDB_ROOT_PASSWORD= command: ["--replSet", "rs0", "--auth", "--keyFile", "/etc/mongo.key"] networks: - sample-app mongo2: image: mongo:6.0 container_name: mongo2 ports: - "27018:27017" volumes: - ./data/mongo2:/data/db - ./secrets/mongo.key:/etc/mongo.key:ro environment: - MONGO_INITDB_ROOT_USERNAME= - MONGO_INITDB_ROOT_PASSWORD= command: ["--replSet", "rs0", "--auth", "--keyFile", "/etc/mongo.key"] networks: - sample-app mongo3: image: mongo:6.0 container_name: mongo3 ports: - "27019:27017" volumes: - ./data/mongo3:/data/db - ./secrets/mongo.key:/etc/mongo.key:ro environment: - MONGO_INITDB_ROOT_USERNAME= - MONGO_INITDB_ROOT_PASSWORD= command: ["--replSet", "rs0", "--auth", "--keyFile", "/etc/mongo.key"] networks: - sample-app replica-init: image: mongo:6.0 container_name: mongo-init depends_on: - mongo1 volumes: - ./scripts/init-replica.sh:/init-replica.sh:ro entrypoint: [ "/bin/bash", "/init-replica.sh" ] networks: - sample-app mongo-express: image: mongo-express:1.0.0-alpha.4 container_name: mongo-express restart: always # Khởi động lại nếu kết nối tới mongo1 thất bại ports: - "38081:8081" environment: - ME_CONFIG_MONGODB_URL= - ME_CONFIG_MONGODB_ADMINUSERNAME= - ME_CONFIG_MONGODB_ADMINPASSWORD= - ME_CONFIG_BASICAUTH_USERNAME= - ME_CONFIG_BASICAUTH_PASSWORD= depends_on: - mongo1 networks: - sample-app networks: sample-app: driver: bridge
Script tự động khởi tạo Cluster
mongo-init/init-replica.sh#!/bin/bash echo "[replica-init] Đang chờ MongoDB sẵn sàng..." until mongosh --host mongo1 --username root --password example --authenticationDatabase admin --eval "db.adminCommand('ping')" >/dev/null 2>&1; do sleep 2 done echo "[replica-init] Đã kết nối. Đang kiểm tra trạng thái replica set..." # Kiểm tra xem đã khởi tạo chưa IS_INITIALIZED=$(mongosh --host mongo1 --username root --password example --authenticationDatabase admin --quiet --eval "try { rs.status().ok } catch(e) { 0 }") if [[ "$IS_INITIALIZED" == "1" ]]; then echo "[replica-init] Replica set đã được khởi tạo. Bỏ qua." else echo "[replica-init] Đang khởi tạo replica set..." mongosh --host mongo1 --username root --password example --authenticationDatabase admin <<EOF rs.initiate({ _id: "rs0", members: [ { _id: 0, host: "mongo1:27017" }, { _id: 1, host: "mongo2:27017" }, { _id: 2, host: "mongo3:27017" } ] }) EOF echo "[replica-init] Đã khởi tạo replica set thành công." fi
Chạy hệ thống
docker compose up -d
Thông tin truy cập
- MongoDB URI:
mongodb://root:example@localhost:27017/?replicaSet=rs0 - Mongo Express: http://localhost:38081
- Đăng nhập:
admin/admin
Mẹo nhỏ kết thúc
- Sử dụng lệnh
rs.status()để kiểm tra xem các node Primary/Secondary đã được phân bổ đúng chưa. - Nếu giữ lại Docker volume, cấu hình sẽ được duy trì ngay cả khi khởi động lại.
-
mongo-expressđược đặtrestart: alwaysđể tự động thử lại nếu ban đầu chưa kết nối được tới DB.
Nguồn bài viết ryukato.github.io