docker-compose — API + PostgreSQL + Redis bir yerda

~20 daq · .NET Backend · Deploy

Muammodan boshlaylik

API ishlashi uchun kerak: PostgreSQL, Redis va API ning o'zi. Har birini alohida docker run bilan:

docker network create dokon-net
docker run -d --name db --network dokon-net -e POSTGRES_PASSWORD=... -v pgdata:/var/lib/postgresql/data postgres:17
docker run -d --name redis --network dokon-net redis:7
docker run -d --name api --network dokon-net -p 5000:8080 -e ConnectionStrings__Dokon=... dokon-api

Uzun buyruqlar, tartibni eslab qolish, yangi dasturchi uchun yarim kunlik sozlash. Bittasida xato — hech narsa ishlamaydi.


Hayotiy o'xshatma

Orkestr dirijyori va partitura. Har bir musiqachini alohida chaqirib "sen skripka chal, sen keyin baraban" deb tushuntirish o'rniga — bitta partitura: kim, qachon, qaysi asbobda. Dirijyor bitta ishora bilan butun orkestrni boshlaydi va to'xtatadi. docker-compose.yml — sizning partiturangiz.


compose.yaml

services:
  api:
    build:
      context: .
      dockerfile: Dokon.Api/Dockerfile
    ports:
      - "5000:8080"
    environment:
      ASPNETCORE_ENVIRONMENT: Development
      ConnectionStrings__Dokon: "Host=db;Port=5432;Database=dokon;Username=dokon;Password=${DB_PAROL}"
      ConnectionStrings__Redis: "redis:6379"
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_started
    restart: unless-stopped

  db:
    image: postgres:17
    environment:
      POSTGRES_DB: dokon
      POSTGRES_USER: dokon
      POSTGRES_PASSWORD: ${DB_PAROL}
    volumes:
      - pgdata:/var/lib/postgresql/data
    ports:
      - "5432:5432"            # lokal vositalar (DBeaver) uchun; production da olib tashlang
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U dokon -d dokon"]
      interval: 5s
      timeout: 3s
      retries: 10

  redis:
    image: redis:7
    volumes:
      - redisdata:/data

volumes:
  pgdata:
  redisdata:
# .env — compose bilan bir papkada, git ga QO'SHILMAYDI
DB_PAROL=lokal-uchun-parol-123

Asosiy tushunchalar

Tarmoq — compose barcha servislarni bitta tarmoqqa qo'yadi; ular bir-birini servis nomi bilan topadi: Host=db, redis:6379. localhost emas!

Volume — pgdata konteyner o'chirilsa ham ma'lumot saqlanadi. Volume siz docker compose down — butun baza yo'qoladi.

depends_on + service_healthy — API faqat PostgreSQL tayyor bo'lgandan keyin ishga tushadi (faqat konteyner boshlangani emas).

${DB_PAROL} — .env faylidan yoki muhitdan olinadi.


Buyruqlar

docker compose up -d              # hammasini ishga tushirish (fon rejimida)
docker compose up -d --build      # API image ini qayta qurib
docker compose ps                 # holat
docker compose logs -f api        # API log lari
docker compose exec db psql -U dokon -d dokon
docker compose restart api
docker compose down               # to'xtatish va konteynerlarni o'chirish (volume lar qoladi)
docker compose down -v            # volume lar bilan — BAZA O'CHADI

Migratsiyalar

API ishga tushganda bazani yangilash usullari:

// 1) ishga tushishda (kichik loyihalar, bitta nusxa)
using (var scope = app.Services.CreateScope())
{
    var db = scope.ServiceProvider.GetRequiredService<DokonDbContext>();
    await db.Database.MigrateAsync();
}
# 2) alohida qadam — SQL skript yoki migration bundle (tavsiya)
dotnet ef migrations bundle -o efbundle
./efbundle --connection "Host=...;..."

[!WARNING] Bir nechta API nusxasi bir vaqtda MigrateAsync chaqirsa — migratsiyalar to'qnashishi mumkin. Production da migratsiyani deploy jarayonining alohida qadami sifatida, bitta marta bajaring (bundle yoki idempotent SQL skript: dotnet ef migrations script --idempotent).


Development va production fayllari

compose.yaml              asosiy
compose.override.yaml     lokal — avtomatik qo'shiladi (portlar, debug)
compose.prod.yaml         production farqlari
docker compose up -d                                         # compose.yaml + override
docker compose -f compose.yaml -f compose.prod.yaml up -d    # production
# compose.prod.yaml
services:
  api:
    environment:
      ASPNETCORE_ENVIRONMENT: Production
    deploy:
      resources:
        limits:
          memory: 512M
  db:
    ports: !reset []          # bazani tashqariga ochmaslik

Qo'shimcha servislar

  seq:
    image: datalust/seq
    environment:
      ACCEPT_EULA: "Y"
    ports:
      - "5341:80"

Markaziy log (66-dars), pgAdmin, mail sinovchi (Mailpit) — har biri bir necha qator.

[!TIP] Faqat bog'liqliklarni (db, redis) compose da ishga tushirib, API ni IDE dan debug bilan ishlatish — lokal ishlab chiqish uchun eng qulay variant: docker compose up -d db redis. Connection string da u holda Host=localhost.

[!INFO] .NET Aspire — xuddi shu vazifani C# kodi bilan bajaruvchi yangi vosita: AppHost loyihasida builder.AddPostgres("db"), builder.AddRedis("cache") — konteynerlarni ishga tushiradi, connection string larni avtomatik uzatadi va boshqaruv paneli (log, trace, metrikalar) beradi.


Tez-tez uchraydigan xatolar

Host=localhost konteyner ichida — API o'zini qidiradi; servis nomi db.

depends_on sharti yo'q — API baza tayyor bo'lmasdan ishga tushib yiqiladi.

.env git da — parollar oshkor; .gitignore ga va .env.example (qiymatlarsiz) ni git ga.

down -v tasodifan — lokal baza ma'lumotlari yo'qoladi.


Xulosa

docker-compose — bir nechta konteynerni bitta faylda tavsiflash va bitta buyruq bilan boshqarish. services: build yoki image, ports, environment, volumes, depends_on (service_healthy + healthcheck). Servislar bir-birini nomi bilan topadi (Host=db), volume — ma'lumotni saqlaydi, .env — maxfiy qiymatlar.

up -d, logs -f, exec, down (-v — ehtiyot). Migratsiya — production da alohida qadam (bundle, idempotent skript). Override fayllar — muhitlar farqi. Muqobil — .NET Aspire.


Keyingi dars

82-dars: Environment va Secrets — production sozlamalar, secret management