From f81e6cd95196f57a3f3e775fe0df1ee7c8a2fa83 Mon Sep 17 00:00:00 2001 From: ztimson Date: Fri, 12 Jun 2026 02:24:35 -0400 Subject: [PATCH] Added replica init --- README.md | 29 ++++++++++++++++------------- docker-compose.yml | 11 +++++++++-- entrypoint.sh | 45 ++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 69 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index b5f9149..d518ee9 100644 --- a/README.md +++ b/README.md @@ -41,25 +41,28 @@ MongoDB + Backups & Retention ## About -Custom MongoDB Docker image extending `mongo:latest` with automated backup functionality. +Custom MongoDB Docker image extending `mongo:latest` with automated backups, retention management, and replica set configuration. -Installs cron to run scheduled mongodump operations with compression and retention management, while preserving all native MongoDB server functionality. +Includes cron-based scheduled `mongodump` operations with compression, automatic stale lock recovery on unclean shutdowns, and zero-config replica set initialization — while preserving all native MongoDB functionality. -Backups can be manually triggered with: `docker --exec -t mongodb backup` +**Manually trigger a backup:** +docker exec -t mongodb backup -To restore a backup, uncompress it and use the official `mongorestore` +**Restore a backup:** +Decompress the archive and use the official `mongorestore` tool. ### Environment Variables -| Variable | Description | Default | Example | -|------------------------------|--------------------------------------------------|--------------------------|---------------| -| `BACKUP_CRON` | Cron schedule expression | | `0 */6 * * *` | -| `BACKUP_DIR` | Directory to store backups | `/data/backups` | `/backups` | -| `BACKUP_DB` | Database to backup | `$MONGO_INITDB_DATABASE` | `admin` | -| `BACKUP_RETENTION` | Number of backups to keep, defaults to unlimited | | `7` | -| `MONGO_INITDB_DATABASE` | Default database name | | `momentum` | -| `MONGO_INITDB_ROOT_USERNAME` | Root username for mongodump auth | | `root` | -| `MONGO_INITDB_ROOT_PASSWORD` | Root password for mongodump auth | | `secret` | +| Variable | Description | Default | Example | +|------------------------------|----------------------------------------------------------------------|--------------------------|-----------------------| +| `BACKUP_CRON` | Cron schedule expression | | `0 */6 * * *` | +| `BACKUP_DIR` | Directory to store backups | `/data/backups` | `/backups` | +| `BACKUP_DB` | Database to backup | `$MONGO_INITDB_DATABASE` | `admin` | +| `BACKUP_RETENTION` | Number of backups to keep, defaults to unlimited | | `7` | +| `MONGO_INITDB_DATABASE` | Default database name | | `momentum` | +| `MONGO_INITDB_ROOT_USERNAME` | Root username for mongodump auth | | `root` | +| `MONGO_INITDB_ROOT_PASSWORD` | Root password for mongodump auth | | `secret` | +| `REPLICA` | Comma-separated list of replica hostnames to init/join a replica set | | `db1:27017,db2:27017` | ### Built With diff --git a/docker-compose.yml b/docker-compose.yml index 0663d7b..bb44536 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,5 +1,5 @@ services: - db: + db1: build: . environment: MONGO_INITDB_DATABASE: momentum @@ -8,6 +8,13 @@ services: BACKUP_CRON: "0 2 * * *" BACKUP_RETENTION: "7" BACKUP_DIR: /data/backups + REPLICA: db1:27017,db2:27017 # CSV, Must match hostname volumes: - - data:/data/db + - data1:/data/db - backups:/data/backups + db2: + build: . + environment: + REPLICA: db1:27017,db2:27017 # CSV, Must match hostname + volumes: + - data2:/data/db diff --git a/entrypoint.sh b/entrypoint.sh index 65a3f3d..408e123 100644 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -15,5 +15,48 @@ if [ -f /data/db/mongod.lock ] || [ -f /data/db/WiredTiger.lock ] || [ -f /data/ echo "Repair complete, starting normally..." fi +if [ -n "$REPLICA" ]; then + # Start mongo temporarily in background with replSet enabled + mongod --replSet rs0 --bind_ip_all & + MONGO_PID=$! + + # Wait for mongo to be ready + echo "Waiting for MongoDB to be ready..." + until mongosh --quiet --eval "db.runCommand({ ping: 1 })" &>/dev/null; do + sleep 1 + done + + # Build members array from REPLICA CSV + MEMBERS="" + INDEX=0 + IFS=',' read -ra HOSTS <<< "$REPLICA" + for HOST in "${HOSTS[@]}"; do + [ $INDEX -gt 0 ] && MEMBERS+="," + MEMBERS+="{ _id: $INDEX, host: '$HOST' }" + INDEX=$((INDEX + 1)) + done + + # Init or reconfig replica set + mongosh --quiet --eval " + try { + const config = rs.conf(); + config.members = [$MEMBERS]; + rs.reconfig(config, { force: true }); + print('Replica set reconfigured'); + } catch(e) { + rs.initiate({ _id: 'rs0', members: [$MEMBERS] }); + print('Replica set initiated'); + } + " + + # Stop the temporary mongod + kill $MONGO_PID + wait $MONGO_PID 2>/dev/null +fi + +if [ -n "$REPLICA" ]; then + set -- mongod --replSet rs0 --bind_ip_all +fi + # Hand off to normal mongo entrypoint -exec /usr/local/bin/docker-entrypoint.sh "$@" \ No newline at end of file +exec /usr/local/bin/docker-entrypoint.sh "$@"