docs(deploy): Dokploy canlıya alma ve MongoDB replica set kılavuzları

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-11-07 02:13:10 +03:00
parent 1bdcedefdc
commit 6ce8ffa4a5
3 changed files with 422 additions and 14 deletions
+144
View File
@@ -0,0 +1,144 @@
# 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.