Files
butcem/docs/MONGODB-KURULUM.md
T

145 lines
6.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# MongoDB kurulumu (canlı, Dokploy)
BÜTÇEM çok adımlı yazmaları (transfer, "Alışverişi tamamla", kart ödemesi…) **MongoDB transaction**
ile yapar. Transaction yalnızca **replica set** üzerinde çalışır; tek sunucu için **tek düğümlü
replica set** (`rs0`) yeterlidir. Uygulama başlarken bunu kontrol eder; replica set yoksa açık bir
hata mesajıyla durur.
Bu belge mevcut kurulumu esas alır: Dokploy'da **`mongo:7`** veritabanı servisi (mongo:8 sunucu
çekirdeğiyle uyumsuz), kimlik doğrulama açık, `butcem_root` (yönetici) ve `butcem_app` (uygulama)
kullanıcıları oluşturulmuş. Uygulama mongo:7.0 ile test edilmiştir (tüm entegrasyon testleri).
> Komutlar Atlas sunucusunda çalıştırılır. `<…>` ile gösterilen yerleri kendi değerlerinizle
> değiştirin. Parolaları komut geçmişine yazmamak için `mongosh` parola sorduğunda girin.
---
## 1. MongoDB konteynerini bul
```bash
docker ps --format '{{.Names}}' | grep -i mongo
```
Çalışan konteynerlerin adlarından MongoDB'ninkini listeler. Dokploy ada rastgele bir son ek ekler
(ör. `butcem-mongo-a1b2c3.1.xyz`). Aşağıda bu adı `<MONGO>` olarak kullanın; adın ayırt edici
başlangıcı (ör. `butcem-mongo-a1b2c3`) da yeterlidir.
```bash
MONGO=$(docker ps -q --filter name=<mongo-servis-adı> | head -n1); echo "$MONGO"
```
Konteyner kimliğini bir değişkene alır; sonraki komutlar `$MONGO` ile kısalır.
## 2. Replica set açık mı?
```bash
docker exec -it "$MONGO" mongosh -u butcem_root --authenticationDatabase admin \
--eval 'try { const s = rs.status(); print(s.set, s.members[0].stateStr) } catch (e) { print("REPLICA SET YOK: " + e.codeName) }'
```
Yönetici olarak bağlanıp replica set durumunu yazdırır (parolayı sorar).
- Çıktı **`rs0 PRIMARY`** ise replica set hazır; **4. adıma** geçin.
- Çıktı **`REPLICA SET YOK: NoReplicationEnabled`** ise **3. adımı** uygulayın.
## 3. Tek düğümlü replica set'i aç
Dokploy'un MongoDB servisinde bir **"Replica Set"** seçeneği varsa (sürüme göre değişir) onu açıp
servisi yeniden deploy etmeniz ve 3.4'e geçmeniz yeterlidir. Yoksa aşağıdaki elle yöntemi uygulayın.
Kimlik doğrulama açıkken replica set bir **anahtar dosyası (keyfile)** ister.
### 3.1 Yedek alın
```bash
docker exec -it "$MONGO" mongodump -u butcem_root --authenticationDatabase admin --gzip --archive=/data/db/oncesi.archive.gz
docker cp "$MONGO":/data/db/oncesi.archive.gz ~/mongo-oncesi.archive.gz && docker exec "$MONGO" rm /data/db/oncesi.archive.gz
```
Değişiklikten önce tüm veritabanlarının yedeğini konteyner içinde bir dosyaya alır (parolayı sorar),
sonra ev dizinine kopyalayıp konteynerdeki kopyayı siler. Yeni kurulumda veri yoksa atlanabilir.
### 3.2 Anahtar dosyasını oluştur
```bash
docker exec "$MONGO" sh -c 'head -c 756 /dev/urandom | base64 > /data/db/rs-keyfile && chmod 400 /data/db/rs-keyfile && chown 999:999 /data/db/rs-keyfile && ls -l /data/db/rs-keyfile'
```
Kalıcı veri volume'u (`/data/db`) içinde rastgele bir anahtar dosyası üretir; yalnızca `mongodb`
kullanıcısı (uid 999) okuyabilir. Çıktıda `-r-------- … mongodb mongodb` görmelisiniz. Dosya
volume'da olduğu için yeniden başlatmalarda korunur.
### 3.3 Başlatma komutunu değiştir ve yeniden deploy et
Dokploy › MongoDB servisi › **Advanced** sekmesi › **Command** alanına:
```
mongod --replSet rs0 --bind_ip_all --keyFile /data/db/rs-keyfile
```
yazıp kaydedin ve servisi **Redeploy** edin. (`MONGO_INITDB_ROOT_*` ortam değişkenleri yerinde
kaldığı için kimlik doğrulama açık kalır.) Konteyner yeniden oluşacağından 1. adımdaki `MONGO`
değişkenini yeniden alın.
### 3.4 Replica set'i başlat (tek seferlik)
```bash
docker exec -it "$MONGO" mongosh -u butcem_root --authenticationDatabase admin \
--eval 'rs.initiate({ _id: "rs0", members: [{ _id: 0, host: "localhost:27017" }] })'
```
`rs0` adlı tek üyeli replica set'i başlatır; çıktıda `{ ok: 1 }` görmelisiniz. Uygulama
`directConnection=true` ile bağlandığı için üye adresinin `localhost` olması sorun değildir.
Birkaç saniye sonra 2. adımdaki kontrolü tekrarlayın: **`rs0 PRIMARY`**.
## 4. Uygulama kullanıcısını doğrula
```bash
docker exec -it "$MONGO" mongosh -u butcem_root --authenticationDatabase admin --eval '
for (const d of ["admin", "butcem"]) {
const u = db.getSiblingDB(d).getUser("butcem_app");
if (u) print("tanımlı veritabanı:", d, "| roller:", JSON.stringify(u.roles));
}'
```
`butcem_app` kullanıcısının hangi veritabanında tanımlı olduğunu (bağlantı dizesindeki
`authSource`) ve rollerini yazdırır. Beklenen rol: `[{"role":"readWrite","db":"butcem"}]`.
Rol farklıysa düzeltin:
```bash
docker exec -it "$MONGO" mongosh -u butcem_root --authenticationDatabase admin \
--eval 'db.getSiblingDB("<authSource>").updateUser("butcem_app", { roles: [{ role: "readWrite", db: "butcem" }] })'
```
Uygulama kullanıcısına yalnızca `butcem` veritabanında okuma-yazma yetkisi verir (migration'lar
index oluşturmak için bu yetkiyle yetinir).
## 5. Bağlantı dizesi (Dokploy uygulama ortam değişkeni)
```
MONGODB_URI=mongodb://butcem_app:<parola-url-kodlu>@<iç-host>:27017/butcem?authSource=<authSource>&replicaSet=rs0&directConnection=true
```
- `<iç-host>`: Dokploy › MongoDB servisi › **Internal Host** (ör. `butcem-mongo-a1b2c3`). Uygulama
ve veritabanı aynı Dokploy ağında olduğundan **dışa port açmaya gerek yoktur**; açmayın.
- `<authSource>`: 4. adımın çıktısındaki veritabanı (`admin` veya `butcem`).
- Parolada `@ : / ? # %` gibi karakterler varsa URL kodlayın:
```bash
python3 -c 'import urllib.parse,getpass; print(urllib.parse.quote(getpass.getpass(), safe=""))'
```
Parolayı sorar ve bağlantı dizesine yazılacak kodlu hâlini basar (geçmişe düşmez).
## 6. Transaction denemesi (isteğe bağlı)
```bash
docker exec -it "$MONGO" mongosh "mongodb://butcem_app@localhost:27017/butcem?authSource=<authSource>&replicaSet=rs0&directConnection=true" --eval '
const s = db.getMongo().startSession(); const c = s.getDatabase("butcem").getCollection("tx_probe");
s.startTransaction(); c.insertOne({ a: 1 }); s.commitTransaction();
print("transaction tamam:", db.getSiblingDB("butcem").getCollection("tx_probe").countDocuments({}));
db.getSiblingDB("butcem").getCollection("tx_probe").drop();'
```
Uygulama kullanıcısıyla bağlanıp küçük bir transaction yazar, sonucu basar ve deneme
koleksiyonunu siler. `transaction tamam: 1` görmelisiniz.