Ishlab chiqish uchun Compose — hot reload, watch

~15 daq · Docker · Docker Compose

Muammodan boshlaylik

Compose bilan butun loyiha bitta buyruqda ishga tushadi. Lekin har bir kod o'zgarishida:

docker compose up -d --build api

— 20-30 soniya. Oddiy npm run dev bilan o'zgarish bir soniyada ko'rinardi. Docker ishlab chiqishni sekinlashtirmasligi kerak.

Ikki yo'l bor: bind mount (20-dars) va zamonaviy Compose Watch.


1-usul: bind mount + dev server

services:
  api:
    build:
      context: .
      target: dev                 # multi-stage dagi dev bosqichi (16-dars)
    command: npm run dev          # tsx watch / nodemon / nest start --watch
    ports:
      - "3000:3000"
      - "9229:9229"               # Node debugger
    volumes:
      - ./:/app                   # kod — bind mount
      - /app/node_modules         # konteynerning o'z node_modules i (20-dars)
    environment:
      NODE_ENV: development
      DB_HOST: baza
    depends_on:
      baza:
        condition: service_healthy

  baza:
    image: mysql:8.4
    ports:
      - "127.0.0.1:3306:3306"     # GUI mijoz uchun — faqat lokal
    environment:
      MYSQL_ROOT_PASSWORD: root123
      MYSQL_DATABASE: dokon
    volumes:
      - baza-data:/var/lib/mysql
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "--silent"]
      interval: 5s
      retries: 20

volumes:
  baza-data:

Fayl saqlandi → bind mount orqali konteyner darhol ko'radi → npm run dev serverni qayta ishga tushiradi. Rebuild yo'q.

Yangi paket qo'shildi (npm install axios):

docker compose exec api npm install axios
# yoki package.json o'zgargach:
docker compose up -d --build api

2-usul: Compose Watch

Bind mount ning kamchiliklari: Windows/macOS da sekin, fayl o'zgarishi ba'zan sezilmaydi, node_modules hiylasi. Compose Watch — fayl o'zgarishlarini Compose o'zi kuzatadi va konteynerga nusxalaydi:

services:
  api:
    build:
      context: .
      target: dev
    command: npm run dev
    ports:
      - "3000:3000"
    develop:
      watch:
        - action: sync
          path: ./src
          target: /app/src
        - action: rebuild
          path: package.json
        - action: sync+restart
          path: ./config
          target: /app/config
docker compose watch
# yoki: docker compose up --watch
action Fayl o'zgarganda
sync Faylni konteynerga nusxalash (dev server o'zi qayta yuklaydi)
rebuild Image ni qayta yasab, konteynerni almashtirish — package.json uchun
sync+restart Nusxalash + konteynerni qayta ishga tushirish — konfiguratsiya uchun

Afzalliklari:

  • Barcha platformalarda tez va ishonchli
  • node_modules muammosi yo'q — kompyuterdagi papka umuman ulanmaydi
  • package.json o'zgarsa — avtomatik rebuild

ignore — keraksiz fayllarni o'tkazib yuborish:

        - action: sync
          path: ./src
          target: /app/src
          ignore:
            - "**/*.test.ts"

Frontend (Vite / React)

services:
  web:
    image: node:22-alpine
    working_dir: /app
    command: sh -c "npm install && npm run dev -- --host 0.0.0.0"
    ports:
      - "5173:5173"
    volumes:
      - ./frontend:/app
      - /app/node_modules

--host 0.0.0.0 — majburiy (9-dars): Vite standart holatda faqat localhost ni tinglaydi va konteyner tashqarisidan ko'rinmaydi.

Bind mount bilan fayl o'zgarishi sezilmasa — vite.config.ts da server.watch.usePolling: true, yoki Compose Watch.


Debug

Node.js:

command: node --inspect=0.0.0.0:9229 -r tsx/cjs src/index.ts
ports:
  - "9229:9229"

VS Code launch.json:

{
  "type": "node",
  "request": "attach",
  "name": "Docker ga ulanish",
  "port": 9229,
  "address": "localhost",
  "localRoot": "${workspaceFolder}",
  "remoteRoot": "/app"
}

Breakpoint lar konteyner ichidagi kodda ishlaydi.

Dev Containers — VS Code ning kengaytmasi: muharrirning o'zi konteyner ichida ishlaydi (terminal, kengaytmalar, debugger). Loyihaga .devcontainer/devcontainer.json qo'shiladi — har bir dasturchi bir xil to'liq muhitni oladi.


Qo'shimcha dev xizmatlari

Ishlab chiqishda foydali, production da kerak emas:

  adminer:
    image: adminer
    ports:
      - "127.0.0.1:8080:8080"
    profiles: [tools]

  mailpit:                         # yuborilgan email larni ushlab, brauzerda ko'rsatadi
    image: axllent/mailpit
    ports:
      - "127.0.0.1:8025:8025"      # veb interfeys
    profiles: [tools]
docker compose --profile tools up -d

profiles — faqat so'ralganda ishga tushadigan xizmatlar (31-dars). Mailpit — ilova SMTP orqali yuborgan email lar haqiqiy odamlarga emas, localhost:8025 dagi pochta qutisiga tushadi. Ro'yxatdan o'tish va parolni tiklash xatlarini sinash uchun ajoyib.


Nima uchun shunday?

Nima uchun Docker bilan ishlab chiqish kerak — kompyuterda npm run dev va o'rnatilgan MySQL bilan ishlash oddiyroq-ku?

Bitta loyiha uchun — ehtimol. Lekin uchta loyiha: biri MySQL 8.0 da, biri 8.4 da, biri PostgreSQL da; biri Node 18 da, boshqasi 22 da; biriga Redis, boshqasiga RabbitMQ kerak. Kompyuterga hammasini o'rnatish — versiyalar to'qnashuvi va "qaysi xizmat qaysi loyihaniki" chalkashligi. Docker bilan har bir loyiha — o'z izolyatsiyalangan muhiti, docker compose up bilan ko'tariladi va down bilan iz qoldirmay yo'qoladi. Hot reload va watch bilan esa tezlik yo'qotilmaydi.


Xulosa

Eslab qoling:

  • Ishlab chiqishda: target: dev + command: npm run dev
  • 1-usul: bind mount ./:/app + /app/node_modules
  • 2-usul: Compose Watch — develop.watch (sync, rebuild, sync+restart) va docker compose watch
  • Watch — tezroq, ishonchliroq, node_modules muammosiz
  • Frontend dev server — --host 0.0.0.0
  • Debug: --inspect=0.0.0.0:9229 + VS Code attach; Dev Containers
  • Dev vositalar (Adminer, Mailpit) — profiles bilan

Keyingi dars

31-dars: Bir nechta muhit — override fayllar va profiles