ludo web based game config file changes
This commit is contained in:
parent
4cd0fe970f
commit
5b02a13cb4
8
.env
Normal file
8
.env
Normal file
@ -0,0 +1,8 @@
|
||||
# MongoDB connection for backend
|
||||
CONNECTION_URI=mongodb://admin:adminpassword@mongo:27017/ludo?authSource=admin&replicaSet=rs0
|
||||
|
||||
# Backend port
|
||||
PORT=18081
|
||||
|
||||
# Environment
|
||||
NODE_ENV=production
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@ -21,4 +21,4 @@ build
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
.env
|
||||
# .env
|
||||
116
Dockerfile
116
Dockerfile
@ -1,19 +1,111 @@
|
||||
FROM node:14 as frontend
|
||||
# FROM node:14 as frontend
|
||||
# WORKDIR /app
|
||||
# COPY . /app
|
||||
# RUN npm install --production
|
||||
# RUN npm run build
|
||||
|
||||
# FROM node:14 as backend
|
||||
# WORKDIR /app
|
||||
# COPY /backend /app
|
||||
# RUN npm install
|
||||
|
||||
# FROM node:14
|
||||
# WORKDIR /app
|
||||
# COPY --from=backend /app /app/
|
||||
# COPY --from=frontend /app/build /app/build
|
||||
|
||||
# EXPOSE 8080
|
||||
|
||||
# CMD ["npm", "run", "start"]
|
||||
|
||||
|
||||
const express = require('express');
|
||||
const cors = require('cors');
|
||||
const path = require('path');
|
||||
const cookieParser = require('cookie-parser');
|
||||
const mongoose = require('mongoose');
|
||||
require('dotenv').config();
|
||||
const { sessionMiddleware } = require('./config/session');
|
||||
|
||||
const PORT = process.env.PORT || 5000;
|
||||
|
||||
const app = express();
|
||||
|
||||
app.use(cookieParser());
|
||||
app.use(express.urlencoded({ extended: true }));
|
||||
app.use(express.json());
|
||||
app.set('trust proxy', 1);
|
||||
|
||||
/* ---------- CORS ---------- */
|
||||
app.use(
|
||||
cors({
|
||||
origin:
|
||||
process.env.NODE_ENV === 'production'
|
||||
? true // same origin (Docker / prod)
|
||||
: 'http://localhost:3000',
|
||||
credentials: true,
|
||||
})
|
||||
);
|
||||
|
||||
app.use(sessionMiddleware);
|
||||
|
||||
const server = app.listen(PORT, "0.0.0.0", () => {
|
||||
console.log(`Server listening on port ${PORT}`);
|
||||
});
|
||||
|
||||
/* ---------- Mongo + Socket ---------- */
|
||||
require('./config/database')(mongoose);
|
||||
require('./config/socket')(server);
|
||||
|
||||
/* ---------- Serve React build ---------- */
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
const buildPath = path.resolve(__dirname, 'build');
|
||||
|
||||
app.use(express.static(buildPath));
|
||||
|
||||
app.get('*', (req, res) => {
|
||||
res.sendFile(path.join(buildPath, 'index.html'));
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = { server };
|
||||
root@DietPi:~/mern-ludo/backend# ^C
|
||||
root@DietPi:~/mern-ludo/backend# cd .
|
||||
root@DietPi:~/mern-ludo/backend# cd ..
|
||||
root@DietPi:~/mern-ludo# nano Dockerfile
|
||||
root@DietPi:~/mern-ludo# cat Dockerfile
|
||||
# Node 20 for Pi 5 (ARM64)
|
||||
FROM node:20-bullseye-slim
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Copy all files
|
||||
COPY . /app
|
||||
RUN npm install --production
|
||||
|
||||
# Install frontend (root) dependencies
|
||||
RUN npm install --legacy-peer-deps
|
||||
|
||||
# Build frontend
|
||||
RUN npm run build
|
||||
|
||||
FROM node:14 as backend
|
||||
WORKDIR /app
|
||||
COPY /backend /app
|
||||
RUN npm install
|
||||
# Install backend dependencies
|
||||
RUN cd backend && npm install --production --legacy-peer-deps
|
||||
|
||||
FROM node:14
|
||||
WORKDIR /app
|
||||
COPY --from=backend /app /app/
|
||||
COPY --from=frontend /app/build /app/build
|
||||
# Move frontend build into backend/public for Express
|
||||
# RUN cp -r build backend/public
|
||||
RUN rm -rf backend/build
|
||||
RUN cp -r build backend/build
|
||||
|
||||
EXPOSE 8080
|
||||
# Copy wait-for-mongo.sh and make it executable
|
||||
COPY wait-for-mongo.sh ./
|
||||
RUN chmod +x wait-for-mongo.sh
|
||||
|
||||
CMD ["npm", "run", "start"]
|
||||
# Default fallback values (can be overridden by Compose)
|
||||
ENV NODE_ENV=production
|
||||
ENV PORT=8080
|
||||
ENV CONNECTION_URI=mongodb://mongo:27017/ludo?replicaSet=rs0
|
||||
|
||||
EXPOSE 18081
|
||||
|
||||
# Start backend with wait-for-mongo
|
||||
CMD ["bash", "./wait-for-mongo.sh", "mongo", "27017", "node", "backend/server.js"]
|
||||
|
||||
@ -1,13 +1,9 @@
|
||||
module.exports = function (mongoose) {
|
||||
mongoose.set('useFindAndModify', false);
|
||||
mongoose
|
||||
.connect(process.env.CONNECTION_URI, {
|
||||
useNewUrlParser: true,
|
||||
useUnifiedTopology: true,
|
||||
dbName: 'test',
|
||||
})
|
||||
.then(() => {
|
||||
console.log('MongoDB Connected…');
|
||||
})
|
||||
.catch(err => console.error(err));
|
||||
module.exports = async function (mongoose) {
|
||||
try {
|
||||
await mongoose.connect(process.env.CONNECTION_URI);
|
||||
console.log('✅ MongoDB connected');
|
||||
} catch (err) {
|
||||
console.error('❌ MongoDB connection error:', err);
|
||||
process.exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
@ -6,36 +6,44 @@ const mongoose = require('mongoose');
|
||||
require('dotenv').config();
|
||||
const { sessionMiddleware } = require('./config/session');
|
||||
|
||||
const PORT = process.env.PORT;
|
||||
const PORT = process.env.PORT || 5000;
|
||||
|
||||
const app = express();
|
||||
|
||||
app.use(cookieParser());
|
||||
app.use(
|
||||
express.urlencoded({
|
||||
extended: true,
|
||||
})
|
||||
);
|
||||
app.use(express.urlencoded({ extended: true }));
|
||||
app.use(express.json());
|
||||
app.set('trust proxy', 1);
|
||||
|
||||
/* ---------- CORS ---------- */
|
||||
app.use(
|
||||
cors({
|
||||
origin: 'http://localhost:3000',
|
||||
origin:
|
||||
process.env.NODE_ENV === 'production'
|
||||
? true // same origin (Docker / prod)
|
||||
: 'http://localhost:3000',
|
||||
credentials: true,
|
||||
})
|
||||
);
|
||||
|
||||
app.use(sessionMiddleware);
|
||||
|
||||
const server = app.listen(PORT);
|
||||
const server = app.listen(PORT, "0.0.0.0", () => {
|
||||
console.log(`Server listening on port ${PORT}`);
|
||||
});
|
||||
|
||||
/* ---------- Mongo + Socket ---------- */
|
||||
require('./config/database')(mongoose);
|
||||
require('./config/socket')(server);
|
||||
|
||||
/* ---------- Serve React build ---------- */
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
app.use(express.static('./build'));
|
||||
const buildPath = path.resolve(__dirname, 'build');
|
||||
|
||||
app.use(express.static(buildPath));
|
||||
|
||||
app.get('*', (req, res) => {
|
||||
const indexPath = path.join(__dirname, './build/index.html');
|
||||
res.sendFile(indexPath);
|
||||
res.sendFile(path.join(buildPath, 'index.html'));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
42
docker-compose.yml
Normal file
42
docker-compose.yml
Normal file
@ -0,0 +1,42 @@
|
||||
version: "3.9"
|
||||
|
||||
services:
|
||||
mongo:
|
||||
image: mongo:7.0
|
||||
container_name: ludo-mongo
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- ludo-net
|
||||
volumes:
|
||||
- ludo-mongo-data:/data/db
|
||||
- ./mongo-keyfile:/etc/mongo-keyfile:ro
|
||||
# - ./mongo-init.js:/docker-entrypoint-initdb.d/mongo-init.js:ro
|
||||
command:
|
||||
- bash
|
||||
- -c
|
||||
- |
|
||||
cp /etc/mongo-keyfile /data/db/keyfile &&
|
||||
chown mongodb:mongodb /data/db/keyfile &&
|
||||
chmod 400 /data/db/keyfile &&
|
||||
exec mongod --replSet rs0 --keyFile /data/db/keyfile --bind_ip_all
|
||||
ports:
|
||||
- "27017:27017"
|
||||
|
||||
app:
|
||||
build: .
|
||||
container_name: mern-ludo-app
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- ludo-net
|
||||
env_file:
|
||||
- .env
|
||||
ports:
|
||||
- "18081:${PORT}" # Host:Container mapping
|
||||
depends_on:
|
||||
- mongo
|
||||
|
||||
networks:
|
||||
ludo-net:
|
||||
|
||||
volumes:
|
||||
ludo-mongo-data:
|
||||
@ -13,7 +13,7 @@ function App() {
|
||||
const [playerSocket, setPlayerSocket] = useState();
|
||||
const [redirect, setRedirect] = useState();
|
||||
useEffect(() => {
|
||||
const socket = io(`http://${window.location.hostname}:8080`, { withCredentials: true });
|
||||
const socket = io(`${window.location.protocol}//${window.location.host}`, { withCredentials: true });
|
||||
socket.on('player:data', data => {
|
||||
data = JSON.parse(data);
|
||||
setPlayerData(data);
|
||||
@ -72,5 +72,3 @@ function App() {
|
||||
</SocketContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
||||
|
||||
562
troubleshooting.md
Normal file
562
troubleshooting.md
Normal file
@ -0,0 +1,562 @@
|
||||
You’ve identified the Mongo volume that’s causing the auth issue.
|
||||
|
||||
What this means
|
||||
local mern-ludo_mongo_data
|
||||
|
||||
|
||||
This volume still exists, so Mongo is:
|
||||
|
||||
reusing old, broken initialization
|
||||
|
||||
not recreating the admin user
|
||||
|
||||
continuing to fail authentication
|
||||
|
||||
We now need to delete this volume so Mongo can initialize cleanly.
|
||||
|
||||
✅ Do this EXACTLY (safe + correct)
|
||||
🔴 Step 1: Stop containers
|
||||
docker compose down
|
||||
|
||||
🔴 Step 2: Remove the Mongo volume
|
||||
docker volume rm mern-ludo_mongo_data
|
||||
|
||||
|
||||
If Docker complains it’s in use, run:
|
||||
|
||||
docker compose down -v
|
||||
|
||||
|
||||
(that removes volumes automatically)
|
||||
|
||||
✅ Step 3: Confirm it’s gone
|
||||
docker volume ls | grep ludo
|
||||
|
||||
|
||||
👉 This should return nothing.
|
||||
|
||||
✅ Step 4: Start ONLY Mongo first (important)
|
||||
docker compose up -d mongo
|
||||
|
||||
|
||||
Wait 10–15 seconds.
|
||||
|
||||
Check logs:
|
||||
|
||||
docker logs ludo-mongo --tail=30
|
||||
|
||||
|
||||
You should NOT see:
|
||||
|
||||
bad file
|
||||
|
||||
Unable to acquire security key
|
||||
|
||||
crash/restart loops
|
||||
|
||||
✅ Step 5: Test authentication (this MUST work)
|
||||
docker exec -it ludo-mongo mongosh -u admin -p adminpassword --authenticationDatabase admin
|
||||
|
||||
|
||||
If you get a > prompt → 🎉 auth is fixed
|
||||
|
||||
✅ Step 6: Initialize replica set (ONCE)
|
||||
|
||||
Inside mongosh:
|
||||
|
||||
rs.initiate({
|
||||
_id: "rs0",
|
||||
members: [{ _id: 0, host: "mongo:27017" }]
|
||||
})
|
||||
|
||||
|
||||
Then:
|
||||
|
||||
rs.status().members[0].stateStr
|
||||
|
||||
|
||||
Must be:
|
||||
|
||||
"PRIMARY"
|
||||
|
||||
✅ Step 7: Start the app
|
||||
docker compose up -d app
|
||||
|
||||
|
||||
(or just)
|
||||
|
||||
docker compose up -d
|
||||
|
||||
|
||||
Then:
|
||||
|
||||
docker restart mern-ludo-app
|
||||
|
||||
🎯 Expected final result
|
||||
Mongo
|
||||
|
||||
Auth works
|
||||
|
||||
Replica set PRIMARY
|
||||
|
||||
No errors in logs
|
||||
|
||||
Backend
|
||||
MongoDB connected
|
||||
Server listening on port 18081
|
||||
|
||||
Browser
|
||||
|
||||
App loads
|
||||
|
||||
No crashes
|
||||
|
||||
No noscript / auth errors
|
||||
|
||||
🧾 One-line status
|
||||
|
||||
The Mongo volume still existed; deleting it allows Mongo to create the admin user correctly.
|
||||
|
||||
Once Step 5 succeeds, you are fully unblocked.
|
||||
Run Step 2 now and tell me when mongosh login works 👍
|
||||
|
||||
|
||||
You’re very close, and the remaining issue is not random.
|
||||
|
||||
What the two messages really mean (important)
|
||||
1️⃣ These messages are NOT the main problem ❌
|
||||
Collection [local.oplog.rs] not found
|
||||
ReadConcernMajorityNotAvailableYet
|
||||
|
||||
|
||||
These appear when:
|
||||
|
||||
replica set is not initiated yet
|
||||
|
||||
PRIMARY is not elected yet
|
||||
|
||||
They are expected noise before rs.initiate() succeeds.
|
||||
|
||||
👉 We’ll fix them automatically once the replica set is initialized.
|
||||
|
||||
2️⃣ THIS is the real blocker 🔴
|
||||
MongoServerError: Authentication failed
|
||||
|
||||
|
||||
This means 100%:
|
||||
|
||||
🔐 MongoDB is running with authentication enabled,
|
||||
❌ but the admin user does not exist.
|
||||
|
||||
This is why:
|
||||
|
||||
backend can’t connect
|
||||
|
||||
mongosh -u admin fails
|
||||
|
||||
oplog can’t be created
|
||||
|
||||
replica set can’t complete
|
||||
|
||||
Why the admin user does NOT exist (root cause)
|
||||
|
||||
Mongo creates the root user only once, on first successful startup, when:
|
||||
|
||||
/data/db is empty
|
||||
|
||||
Mongo reaches a stable running state
|
||||
|
||||
Earlier, Mongo:
|
||||
|
||||
crashed due to keyFile issues
|
||||
|
||||
restarted several times
|
||||
|
||||
skipped user creation
|
||||
|
||||
but auth stayed enabled
|
||||
|
||||
Result:
|
||||
|
||||
Mongo requires auth, but no users exist → permanent auth failure
|
||||
|
||||
This is a classic Mongo + replica set + keyFile edge case.
|
||||
|
||||
✅ The ONLY correct fix (clean & guaranteed)
|
||||
|
||||
We must let Mongo start once without auth, create the user manually, then re-enable auth.
|
||||
|
||||
This is the official MongoDB recovery method.
|
||||
|
||||
🔥 DO THIS STEP-BY-STEP (no skipping)
|
||||
STEP 1️⃣ Stop everything
|
||||
docker compose down
|
||||
|
||||
STEP 2️⃣ Temporarily DISABLE auth (Mongo only)
|
||||
|
||||
Edit docker-compose.yml mongo service:
|
||||
|
||||
🔴 TEMPORARY CHANGE
|
||||
|
||||
Comment out these lines for now:
|
||||
|
||||
# environment:
|
||||
# MONGO_INITDB_ROOT_USERNAME: admin
|
||||
# MONGO_INITDB_ROOT_PASSWORD: adminpassword
|
||||
|
||||
|
||||
And change the command to NO keyFile, NO auth:
|
||||
|
||||
command:
|
||||
- mongod
|
||||
- --replSet
|
||||
- rs0
|
||||
- --bind_ip_all
|
||||
|
||||
|
||||
(Leave volumes as-is.)
|
||||
|
||||
STEP 3️⃣ Start Mongo only
|
||||
docker compose up -d mongo
|
||||
|
||||
|
||||
Wait ~10 seconds.
|
||||
|
||||
STEP 4️⃣ Connect WITHOUT auth (this must work)
|
||||
docker exec -it ludo-mongo mongosh
|
||||
|
||||
|
||||
If you get a prompt → good.
|
||||
|
||||
STEP 5️⃣ Create admin user MANUALLY
|
||||
|
||||
Inside mongosh:
|
||||
|
||||
use admin
|
||||
db.createUser({
|
||||
user: "admin",
|
||||
pwd: "adminpassword",
|
||||
roles: [ { role: "root", db: "admin" } ]
|
||||
})
|
||||
|
||||
|
||||
You must see:
|
||||
|
||||
{ ok: 1 }
|
||||
|
||||
STEP 6️⃣ Initialize replica set (NOW it will work)
|
||||
rs.initiate({
|
||||
_id: "rs0",
|
||||
members: [{ _id: 0, host: "mongo:27017" }]
|
||||
})
|
||||
|
||||
|
||||
Wait ~5–10 seconds, then:
|
||||
|
||||
rs.status().members[0].stateStr
|
||||
|
||||
|
||||
Must be:
|
||||
|
||||
"PRIMARY"
|
||||
|
||||
|
||||
Exit mongosh:
|
||||
|
||||
exit
|
||||
|
||||
STEP 7️⃣ Re-enable auth + keyFile (FINAL config)
|
||||
|
||||
Restore your correct mongo config:
|
||||
|
||||
environment:
|
||||
MONGO_INITDB_ROOT_USERNAME: admin
|
||||
MONGO_INITDB_ROOT_PASSWORD: adminpassword
|
||||
|
||||
command:
|
||||
- bash
|
||||
- -c
|
||||
- |
|
||||
cp /tmp/mongo-keyfile /data/db/keyfile &&
|
||||
chown mongodb:mongodb /data/db/keyfile &&
|
||||
chmod 400 /data/db/keyfile &&
|
||||
exec mongod --replSet rs0 --keyFile /data/db/keyfile --bind_ip_all
|
||||
|
||||
STEP 8️⃣ Restart clean
|
||||
docker compose down
|
||||
docker compose up -d
|
||||
|
||||
STEP 9️⃣ Test auth (this WILL work now)
|
||||
docker exec -it ludo-mongo mongosh -u admin -p adminpassword --authenticationDatabase admin
|
||||
|
||||
STEP 🔟 Start / restart backend
|
||||
docker restart mern-ludo-app
|
||||
|
||||
✅ What you should see now
|
||||
Mongo
|
||||
|
||||
Auth works
|
||||
|
||||
PRIMARY elected
|
||||
|
||||
local.oplog.rs exists
|
||||
|
||||
No auth errors
|
||||
|
||||
Backend
|
||||
MongoDB connected
|
||||
Server listening on port 18081
|
||||
|
||||
App
|
||||
|
||||
Loads normally
|
||||
|
||||
No crashes
|
||||
|
||||
Change Streams work
|
||||
|
||||
🧠 One-line final diagnosis
|
||||
|
||||
MongoDB authentication was enabled before any user existed; manual user creation was required to recover.
|
||||
|
||||
This is the last MongoDB trap — once done, you will not hit this again.
|
||||
|
||||
MongoServerError[NotWritablePrimary]: not primary
|
||||
|
||||
Perfect — that error is expected at this exact moment, and it tells us precisely what to do next 👍
|
||||
You didn’t break anything.
|
||||
|
||||
What this error means (very clear)
|
||||
MongoServerError[NotWritablePrimary]: not primary
|
||||
|
||||
|
||||
This means:
|
||||
|
||||
MongoDB is running as a replica set member,
|
||||
but no PRIMARY has been elected yet.
|
||||
|
||||
Until a node becomes PRIMARY:
|
||||
|
||||
❌ you cannot create users
|
||||
|
||||
❌ you cannot write data
|
||||
|
||||
❌ db.createUser() will fail
|
||||
|
||||
So this is not an auth issue anymore.
|
||||
|
||||
✅ Correct order (important)
|
||||
|
||||
When running Mongo as a replica set, the order must be:
|
||||
|
||||
Start Mongo
|
||||
|
||||
Initiate replica set
|
||||
|
||||
Wait until PRIMARY
|
||||
|
||||
Create users
|
||||
|
||||
Enable auth (already planned)
|
||||
|
||||
Right now, you’re at step 2½.
|
||||
|
||||
✅ DO THIS NOW (inside mongosh)
|
||||
|
||||
You are already connected with:
|
||||
|
||||
docker exec -it ludo-mongo mongosh
|
||||
|
||||
|
||||
At the > prompt, run THIS FIRST 👇
|
||||
|
||||
🔥 Step 1: Initiate replica set
|
||||
rs.initiate({
|
||||
_id: "rs0",
|
||||
members: [
|
||||
{ _id: 0, host: "mongo:27017" }
|
||||
]
|
||||
})
|
||||
|
||||
Expected output
|
||||
{ ok: 1 }
|
||||
|
||||
🔥 Step 2: Wait a few seconds, then verify PRIMARY
|
||||
rs.status().members[0].stateStr
|
||||
|
||||
|
||||
You must see:
|
||||
|
||||
"PRIMARY"
|
||||
|
||||
|
||||
If it still says STARTUP or SECONDARY, wait 5 seconds and run again.
|
||||
|
||||
✅ ONLY AFTER PRIMARY → create admin user
|
||||
|
||||
Now run:
|
||||
|
||||
use admin
|
||||
|
||||
db.createUser({
|
||||
user: "admin",
|
||||
pwd: "adminpassword",
|
||||
roles: [ { role: "root", db: "admin" } ]
|
||||
})
|
||||
|
||||
Expected:
|
||||
{ ok: 1 }
|
||||
|
||||
🧠 Why this happened (important lesson)
|
||||
|
||||
You started Mongo with:
|
||||
|
||||
mongod --replSet rs0
|
||||
|
||||
|
||||
That automatically puts Mongo into replica set mode, but:
|
||||
|
||||
replica set is inactive
|
||||
|
||||
no PRIMARY exists yet
|
||||
|
||||
Mongo rejects all writes until a PRIMARY is elected.
|
||||
|
||||
This is correct MongoDB behavior.
|
||||
|
||||
✅ After user creation (next steps preview)
|
||||
|
||||
Once { ok: 1 } appears:
|
||||
|
||||
Exit mongosh:
|
||||
|
||||
exit
|
||||
|
||||
|
||||
Re-enable auth + keyFile in docker-compose (as discussed)
|
||||
|
||||
Restart containers
|
||||
|
||||
Verify:
|
||||
|
||||
docker exec -it ludo-mongo mongosh -u admin -p adminpassword --authenticationDatabase admin
|
||||
|
||||
🎯 One-line status update
|
||||
|
||||
MongoDB is in replica-set mode but not PRIMARY yet — initialize the replica set first.
|
||||
|
||||
👉 Action for you now
|
||||
|
||||
Run rs.initiate(...), wait for PRIMARY, then retry db.createUser.
|
||||
|
||||
Tell me what rs.status().members[0].stateStr prints, and we’ll finish this cleanly 💪
|
||||
|
||||
|
||||
```yaml
|
||||
version: "3.9"
|
||||
|
||||
services:
|
||||
mongo:
|
||||
image: mongo:7.0
|
||||
container_name: ludo-mongo
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- ludo-net
|
||||
environment:
|
||||
MONGO_INITDB_ROOT_USERNAME: admin
|
||||
MONGO_INITDB_ROOT_PASSWORD: adminpassword
|
||||
volumes:
|
||||
- ludo-mongo-data:/data/db
|
||||
- ./mongo-keyfile:/tmp/mongo-keyfile:ro
|
||||
command:
|
||||
- bash
|
||||
- -c
|
||||
- |
|
||||
cp /tmp/mongo-keyfile /data/db/keyfile &&
|
||||
chown mongodb:mongodb /data/db/keyfile &&
|
||||
chmod 400 /data/db/keyfile &&
|
||||
exec mongod --replSet rs0 --keyFile /data/db/keyfile --bind_ip_all
|
||||
ports:
|
||||
- "27017:27017"
|
||||
|
||||
app:
|
||||
build: .
|
||||
container_name: mern-ludo-app
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- ludo-net
|
||||
env_file:
|
||||
- .env
|
||||
ports:
|
||||
- "18081:8080"
|
||||
depends_on:
|
||||
- mongo
|
||||
|
||||
networks:
|
||||
ludo-net:
|
||||
|
||||
volumes:
|
||||
ludo-mongo-data:
|
||||
```
|
||||
|
||||
Step 2️⃣ Recreate keyfile cleanly (one last time)
|
||||
cd ~/mern-ludo
|
||||
rm -f mongo-keyfile
|
||||
openssl rand -base64 756 > mongo-keyfile
|
||||
chmod 400 mongo-keyfile
|
||||
|
||||
|
||||
Verify:
|
||||
|
||||
wc -c mongo-keyfile
|
||||
|
||||
Step 3️⃣ Full reset (MANDATORY)
|
||||
docker compose down -v
|
||||
docker compose up -d --build
|
||||
|
||||
|
||||
Wait ~10 seconds.
|
||||
|
||||
Step 4️⃣ Confirm Mongo is RUNNING (not restarting)
|
||||
docker ps
|
||||
|
||||
|
||||
You should NOT see Restarting.
|
||||
|
||||
Step 5️⃣ Now exec WILL work
|
||||
docker exec -it ludo-mongo mongosh -u admin -p adminpassword --authenticationDatabase admin
|
||||
|
||||
|
||||
If you get a shell → 🎉 Mongo is fixed
|
||||
|
||||
Step 6️⃣ Initialize replica set (ONCE)
|
||||
rs.initiate({
|
||||
_id: "rs0",
|
||||
members: [{ _id: 0, host: "mongo:27017" }]
|
||||
})
|
||||
|
||||
|
||||
Check:
|
||||
|
||||
rs.status().members[0].stateStr
|
||||
// PRIMARY
|
||||
|
||||
Step 7️⃣ Restart app
|
||||
docker restart mern-ludo-app
|
||||
|
||||
|
||||
Your Change Stream error will now be gone permanently.
|
||||
|
||||
🧠 Why ALL previous attempts failed
|
||||
Attempt Why it failed
|
||||
Bind mount keyfile Ownership mismatch
|
||||
chmod 400 only Not enough
|
||||
DietPi ARM Stricter FS behavior
|
||||
Mongo 7 Enforces keyfile rules hard
|
||||
|
||||
This copy + chown pattern solves all of them.
|
||||
|
||||
✅ One-line final diagnosis
|
||||
|
||||
MongoDB rejected the keyfile because bind-mounted files keep host ownership, and Mongo runs as a non-root user.
|
||||
|
||||
Loading…
Reference in New Issue
Block a user