6ce8ffa4a5
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
145 lines
6.4 KiB
Markdown
145 lines
6.4 KiB
Markdown
# 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.
|