$ sudo teach|
    $ sudo teach|
    IT school
  • Telegram
  • Партнёрам
  • Все курсы
$ sudo teach IT
OOO "SALEPROFIT"Контакты и реквизитыIT-Park Logo

Школа

  • Блог
  • Проверить сертификат

Сотрудничество

  • Стать учителем
  • Партнёрская программа
  • О проекте

Право

  • Оферта
  • Политика конфиденциальности

© 2023–2026 $ sudo teach IT™. All Rights Reserved. Public user contributions licensed under CC BY-SA 4.0 license with attribution required
TelegramGitHubYouTube
ГлавнаяБлогГайд по Docker для разработчика: от devcontainer до воспроизводимых окружений и быстрой отладки

Гайд по Docker для разработчика: от devcontainer до воспроизводимых окружений и быстрой отладки

$ sudo teach IT
·11 августа 2026 г.·12 мин·34
Гайд по Docker для разработчика: от devcontainer до воспроизводимых окружений и быстрой отладки

Покажем, как собрать Docker-подход для повседневной разработки: devcontainer/compose, проброс исходников, управление зависимостями, проброс портов, healthcheck и типовые сценарии отладки без лишних перезапусков.

Содержание
Зачем разработчику Docker: воспроизводимость и контролируемостьБазовый план: что именно мы собираемDevcontainer: вход в среду без лишней магииСтруктура devcontainerПодводные камни devcontainerDocker Compose: сборка сервисов без хаосаПример docker-compose.ymlПочему dependson с condition: servicehealthyDockerfile для разработки: кеширование и быстрый циклПример Dockerfile.dev (Node.js)Если вы используете pnpm/yarnПроброс исходников: что можно и чего лучше избегатьПочему отдельный volume для nodemodulesЧто насчёт watch/reloadПроброс портов и доступ извне: различаем localhost и networkПорты в ComposeТипичная ошибка: использование localhost в DATABASEURLHealthcheck: не только про БДЗдоровье приложенияБыстрая отладка без лишних перезапусковСценарий 1: приложение в dev режиме с live reloadСценарий 2: отладка в IDE через отладочный порт (Node.js example)Сценарий 3: “пересборка зависимостей” без пересборки всегоСценарий 4: миграции и инициализация БДСценарий 5: отладка проблем сети и подключения“Не трогайте контейнер без нужды”: управление перезапускамиПрактический шаблон: всё вместе (devcontainer + compose)Вариант: devcontainer через Docker ComposeЧто важно учестьВоспроизводимость: воспроизводимая сборка и “честные” версииПример принципа для NodeТиповые проблемы и их решения1) Контейнер стартует, но приложение не отвечает2) Изменения кода не видны3) Долгая пересборка образа при каждом чихе4) “Не хватает tool’ов” в контейнере5) Путаются переменные окружения между хостом и контейнеромОтдельный взгляд: production vs dev окружение (и почему их не стоит смешивать)Вывод: собираем Docker-подход как систему, а не как набор команд

Docker для разработчика — это не только про «запустить контейнер и забыть». На практике ценность появляется там, где окружение становится воспроизводимым, а цикл разработки — коротким и предсказуемым: меньше “у меня работает”, больше стабильности, быстрее отладка и ясные правила, что именно запускается и почему.

В этом гайде соберём практичный Docker-подход для повседневной разработки:

  • Dev Containers (devcontainer) как удобная оболочка для входа в проект
  • Docker Compose для запуска нескольких сервисов
  • проброс исходников без лишних пересборок
  • управление зависимостями (включая кеширование)
  • проброс портов и работа с network
  • healthcheck для контроля готовности
  • типовые сценарии отладки, которые уменьшают количество “полных перезапусков”
  • несколько рабочих паттернов, которые обычно “появляются позже”, когда проект уже живой

Пример курса для углубления: в процессе можно дополнительно посмотреть материалы по теме контейнеризации и workflow в [«/course/»] — они помогают систематизировать знания и отстроить практики, но в статье мы разберём всё самостоятельно.


Зачем разработчику Docker: воспроизводимость и контролируемость

С точки зрения разработчика Docker решает три задачи:

  1. Воспроизводимость окружений
    Контейнер фиксирует базовые зависимости ОС, версии языка, системные пакеты и прочие “скрытые” требования. Это особенно важно, когда:

    • на машине один набор версий библиотек,
    • в CI другой,
    • а у пользователя — третий.
  2. Изоляция и предсказуемость
    Контейнеры уменьшают конфликт между проектами: разные версии Node/Python/Java не конкурируют за системные пакеты.

  3. Ускорение разработки при правильной архитектуре
    Если сделать неправильно, Docker станет медленным (частые пересборки, тяжёлые монтирования, отсутствие кеша, “перезапускаем всё каждый раз”). Если правильно — вы получите:

    • быстрый запуск,
    • короткий цикл редактирования/отладки,
    • понятные точки отказа.

Базовый план: что именно мы собираем

Допустим, у нас есть типичный проект: приложение + база (PostgreSQL или другая), плюс возможно отдельный сервис для очередей/кэшей.

Цель — получить структуру, где:

  • Devcontainer обеспечивает удобный вход в среду (VS Code/IDE).
  • Docker Compose управляет сервисами разработки.
  • Исходники монтируются в контейнер, чтобы изменения были видны сразу.
  • Зависимости устанавливаются управляемо (с кешированием слоёв).
  • Порты пробрасываются так, чтобы приложение работало локально.
  • healthcheck помогает дождаться готовности сервисов.
  • Отладка делается без «полного перезапуска мира».

Devcontainer: вход в среду без лишней магии

Devcontainer — это конфигурация, которая позволяет IDE поднять контейнер и “приземлиться” внутрь него. Даже если вы не используете VS Code, концепции полезны: идея в том, чтобы единообразно описать, как должна выглядеть среда разработки.

Структура devcontainer

Часто применяют такой подход:

  • .devcontainer/devcontainer.json — основной файл
  • .devcontainer/Dockerfile — образ для dev окружения (опционально)
  • .devcontainer/library-scripts и прочие утилиты — по необходимости

Пример devcontainer.json для Node.js проекта:

code
{
  "name": "myapp-dev",
  "image": "node:20-bookworm",
  "workspaceFolder": "/workspace",
  "mounts": [
    "source=${localWorkspaceFolder},target=/workspace,type=bind,consistency=cached"
  ],
  "forwardPorts": [3000],
  "postCreateCommand": "npm ci",
  "customizations": {
    "vscode": {
      "settings": {
        "terminal.integrated.defaultProfile.linux": "bash"
      },
      "extensions": ["dbaeumer.vscode-eslint"]
    }
  }
}

Ключевые моменты:

  • workspaceFolder фиксирует путь внутри контейнера.
  • mounts пробрасывает исходники. Важно, чтобы editor работал по реальному файлам.
  • postCreateCommand выполняет установку зависимостей один раз после создания контейнера (но не на каждый запуск).
  • forwardPorts упрощает жизнь: IDE помогает прокинуть порты без ручной возни.

Подводные камни devcontainer

  1. Установка зависимостей каждый запуск
    Если вы поставите postStartCommand: "npm install" — оно может выполняться многократно. Лучше использовать postCreateCommand или вынести зависимости в слой образа.

  2. Слишком тяжёлые монтирования
    На больших проектах bind-mount может замедлять файловую систему. В зависимости от ОС используйте режимы cached/consistent (как в примере) и следите за производительностью.

  3. Путаница “какой контейнер”
    Если devcontainer конфигурирует один образ, а Compose поднимает другие сервисы — легко потерять контроль. Лучше связать devcontainer с compose (ниже будет пример).


Docker Compose: сборка сервисов без хаоса

Compose — это оркестрация “локального мира”: приложение, база, вспомогательные компоненты. Главное — разделить:

  • конфигурацию запуска для разработки,
  • конфигурацию для production,
  • и не смешивать секреты и реальные данные.

Пример docker-compose.yml

Возьмём базу PostgreSQL и сервис приложения (условно Node). Архитектура: приложение в отдельном контейнере, код монтируется, база использует volume.

code
services:
  db:
    image: postgres:16-bookworm
    environment:
      POSTGRES_USER: dev
      POSTGRES_PASSWORD: dev
      POSTGRES_DB: mydb
    ports:
      - "5432:5432"
    volumes:
      - pgdata:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U dev -d mydb"]
      interval: 5s
      timeout: 3s
      retries: 10

  app:
    build:
      context: .
      dockerfile: Dockerfile.dev
    environment:
      DATABASE_URL: postgres://dev:dev@db:5432/mydb
      NODE_ENV: development
    depends_on:
      db:
        condition: service_healthy
    ports:
      - "3000:3000"
    volumes:
      - ./:/workspace
      - /workspace/node_modules
    command: ["npm", "run", "dev"]

volumes:
  pgdata:

Почему depends_on с condition: service_healthy

Без healthcheck compose умеет ждать только “запуск контейнера”, а не готовность сервиса. Для БД это критично: приложение может начать миграции/запросы раньше, чем PostgreSQL реально принимает соединения.

pg_isready — простой и эффективный инструмент для PostgreSQL.


Dockerfile для разработки: кеширование и быстрый цикл

Самая частая проблема: Dockerfile “заточен под сборку образа”, а не под разработку. Мы сделаем Dockerfile.dev, который:

  • минимально перестраивает слои,
  • отделяет установку зависимостей от копирования исходников,
  • чтобы npm ci выполнялся только когда изменились lock-файлы.

Пример Dockerfile.dev (Node.js)

code
FROM node:20-bookworm

WORKDIR /workspace

# 1) Сначала копируем только манифесты зависимостей,
#    чтобы слой с npm ci переиспользовался.
COPY package.json package-lock.json ./

# 2) Устанавливаем зависимости.
#    npm ci следует использовать с package-lock.json.
RUN npm ci

# 3) Исходники будут проброшены volume-монтированием (docker-compose).
#    Поэтому COPY . . в dev-образе не обязателен.
#    Но оставляем /workspace пустым — код приходит через bind mount.

Ключевой трюк: не копировать исходники на этапе сборки dev-образа, если они подмонтируются в runtime. Это предотвращает “засорение кеша” и снижает время пересборки образа.

Если вы используете pnpm/yarn

Принцип тот же:

  • копируете lock-файлы и “manifests”,
  • ставите зависимости,
  • исходники приходят через bind mount.

Для pnpm дополнительно часто используют store path (и кеш), но это уже отдельная тема.


Проброс исходников: что можно и чего лучше избегать

В примере Compose использована схема:

  • - ./:/workspace — bind mount исходников
  • - /workspace/node_modules — отдельный volume, чтобы node_modules не “затирались” с хоста

Почему отдельный volume для node_modules

Если вы монтируете всю директорию проекта внутрь контейнера, то node_modules, установленный на хосте, начнёт конкурировать с тем, что установлен в контейнере. В итоге получаем:

  • несовпадение версий,
  • ошибки native modules,
  • странные “оно работает на моей машине”.

Отдельный volume на node_modules заставляет контейнер использовать свои зависимости, не смешивая их с хостом.

Что насчёт watch/reload

Почти все фреймворки для dev режима требуют корректного file watching. На Linux чаще всего всё ок, на macOS/Windows иногда нужно включать polling.

Пример для Node (через webpack/vite/ts-node — конкретика зависит от стека). Общая идея: если вы видите, что изменения не подхватываются, не спешите перезапускать контейнер — настройте watcher.


Проброс портов и доступ извне: различаем localhost и network

Есть два уровня “куда ходит приложение”:

  1. внутри Docker network
    Контейнеры видят друг друга по именам сервисов (db в примере).
  2. снаружи (ваш хост)
    Вы ходите в приложение через localhost:3000, потому что Compose пробросил порт 3000:3000.

Порты в Compose

code
ports:
  - "3000:3000"

Формат host:container.

Если вы не пробрасываете порты, приложение может быть недоступно с хоста, но при этом оно может успешно общаться с другими сервисами внутри сети.

Типичная ошибка: использование localhost в DATABASE_URL

Внутри контейнеров localhost — это сам контейнер, а не хост и не другой сервис. Поэтому правильно писать postgres://...@db:5432/..., а не @localhost:5432.


Healthcheck: не только про БД

Healthcheck полезен не только для БД. Он отвечает на вопрос: “готово ли приложение выполнять запросы?” — и это напрямую влияет на зависимость сервисов и на удобство отладки.

Здоровье приложения

Например, у приложения есть endpoint /health. Тогда можно сделать:

code
app:
  # ...
  healthcheck:
    test: ["CMD-SHELL", "curl -fsS http://localhost:3000/health || exit 1"]
    interval: 5s
    timeout: 3s
    retries: 10

Важно:

  • healthcheck выполняется внутри контейнера, поэтому адрес — localhost:3000, а не 127.0.0.1 снаружи.
  • curl может отсутствовать в образе; тогда либо добавьте curl, либо используйте другой способ (например, wget или команду языка).

Быстрая отладка без лишних перезапусков

Самая неприятная часть Docker-отладки — когда вместо контроля вы получаете “сначала остановим контейнер, потом пересоберём, потом подождём”. Сделаем так, чтобы отладка была итеративной и управляемой.

Разберём несколько сценариев.


Сценарий 1: приложение в dev режиме с live reload

В Compose мы запускаем:

code
command: ["npm", "run", "dev"]

Смысл: dev-server должен следить за файлами и пересобирать/перезапускать обработчики. Тогда вы не перезапускаете контейнер — вы перезапускаете только приложение внутри него (обычно автоматически).

Если у вас TypeScript/webpack/vite, убедитесь, что dev-конфиг реально настроен на hot reload, а не просто на “перезапуск по изменению”.


Сценарий 2: отладка в IDE через отладочный порт (Node.js example)

В Node.js вы обычно включаете inspector:

  • --inspect=0.0.0.0:9229, чтобы debugger слушал с сетевых интерфейсов контейнера
  • проброс 9229:9229 в Compose

Пример:

code
app:
  ports:
    - "3000:3000"
    - "9229:9229"
  command: ["node", "--inspect=0.0.0.0:9229", "server.js"]

Если у вас TS и start script другой — адаптируйте команду. Главное правило: inspector должен быть доступен вне контейнера, иначе IDE не подключится.


Сценарий 3: “пересборка зависимостей” без пересборки всего

Когда меняются зависимости:

  • изменились package-lock.json
  • добавили библиотеку
  • обновили версии

Правильный подход:

  1. Изменить lock-файл на хосте
  2. Пересобрать образ dev-слоя (или просто запустить rebuild Compose)
  3. Не перезапускать контейнеры “вручную десятки раз”, а делать это через Compose

Например:

code
docker compose build app
docker compose up app

Потому что слой с npm ci пересоберётся только при изменении lock-файла, а не при каждом изменении исходников.


Сценарий 4: миграции и инициализация БД

Частая проблема: вы меняете схему и хотите перезапустить миграции, но не хотите терять данные или всё время пересоздавать volume.

Решение зависит от подхода к данным:

  • Для локальной разработки часто допустимо держать “dev data” в volume.
  • Но миграции нужно выполнять детерминированно.

Обычно делают отдельный сервис migrator или используют entrypoint.

Пример минимального сервиса миграций:

code
  migrate:
    build:
      context: .
      dockerfile: Dockerfile.dev
    depends_on:
      db:
        condition: service_healthy
    environment:
      DATABASE_URL: postgres://dev:dev@db:5432/mydb
    command: ["npm", "run", "migrate"]

Запуск:

code
docker compose run --rm migrate

Плюс: миграции изолированы, и вы не “крутите” их внутри основного контейнера при каждом старте.


Сценарий 5: отладка проблем сети и подключения

Когда приложение не подключается к БД внутри compose, типичные виновники:

  • неверная DATABASE_URL (используется localhost вместо db)
  • сервис ещё не healthy (решает healthcheck+depends_on)
  • неправильные порты внутри контейнера
  • приложение слушает не тот интерфейс

Полезные команды для диагностики:

code
docker compose ps
docker compose logs -f app
docker compose logs -f db

Если нужно зайти внутрь контейнера:

code
docker compose exec app sh

Дальше можно тестировать сетевое соединение (например, nc -z db 5432 или psql — зависит от образа).


“Не трогайте контейнер без нужды”: управление перезапусками

Docker и Compose позволяют легко устраивать перезапуски. Но важно понимать: перезапуск контейнера не то же самое, что “применить код”.

Правильные правила:

  1. Если код подмонтирован volume — меняйте файлы, не пересобирая образ.
  2. Если изменились зависимости — пересобирайте образ слоя зависимостей (через docker compose build app).
  3. Если проблема в конфиге env — перезапустите контейнер (compose up), но не обязательно пересобирать образ.
  4. Если проблема в данных — не пересоздавайте volume без причины.

Для Compose очень удобно использовать “точечные” операции:

  • docker compose restart app
  • docker compose up -d app (с нужными изменениями)
  • docker compose logs -f app

Практический шаблон: всё вместе (devcontainer + compose)

Теперь свяжем devcontainer с compose так, чтобы IDE использовала те же сервисы, что и разработчик.

Вариант: devcontainer через Docker Compose

Идея: devcontainer.json указывает на сервис app в compose-файле, а IDE подключается к нему.

Пример .devcontainer/devcontainer.json:

code
{
  "name": "myapp-dev",
  "dockerComposeFile": [
    "../docker-compose.yml"
  ],
  "service": "app",
  "workspaceFolder": "/workspace",
  "forwardPorts": [3000, 9229],
  "settings": {
    "terminal.integrated.defaultProfile.linux": "bash"
  }
}

Тогда контейнер app — единый источник правды:

  • в нём установлен нужный runtime и зависимости,
  • в нём смонтированы исходники,
  • IDE просто “садится” в эту среду.

Что важно учесть

  • Убедитесь, что devcontainer не пытается ставить зависимости второй раз (postCreateCommand может повторить npm ci).
  • Логику установки зависимостей лучше закрепить в Dockerfile.dev + rebuild по lock-файлу.

Воспроизводимость: воспроизводимая сборка и “честные” версии

Контейнер — это не гарантия, если внутри всё равно происходит “нефиксированная” установка зависимостей.

Критически важно:

  • Использовать lock-файлы (package-lock, yarn.lock, pnpm-lock.yaml).
  • В Dockerfile использовать npm ci вместо npm install (для npm).
  • Фиксировать версии системных пакетов, если они критичны (на практике чаще полагаются на образ базовой ОС + конкретный тег версии языка/дистрибутива).
  • Следить за :latest тегами — они ломают воспроизводимость.

Пример принципа для Node

Правильно:

  • FROM node:20-bookworm (не node:latest)
  • RUN npm ci

Неприятно:

  • FROM node:latest
  • RUN npm install без lock

Типовые проблемы и их решения

1) Контейнер стартует, но приложение не отвечает

  • Проверьте healthcheck базы и depends_on.
  • Посмотрите логи приложения: docker compose logs -f app.
  • Убедитесь, что приложение слушает нужный интерфейс (часто для inspector/remote debugging).

2) Изменения кода не видны

  • Проверьте, что bind mount действительно работает.
  • Убедитесь, что dev-скрипт включён (npm run dev с watcher’ом).
  • Для некоторых стеков на Windows/macOS потребуется polling.

3) Долгая пересборка образа при каждом чихе

  • В Dockerfile.dev не должно быть COPY . . (если код монтируется).
  • Слои установки зависимостей должны зависеть только от lock-файлов.

4) “Не хватает tool’ов” в контейнере

Например, нужен curl, psql, git.

  • Добавьте их точечно в dev-образ (apt-get).
  • Не тяните тяжёлые пакеты без нужды.

5) Путаются переменные окружения между хостом и контейнером

  • Фиксируйте env в compose.
  • Не полагайтесь на то, что переменные будут автоматически подхватываться с вашей оболочки (если вы этого явно не настраивали).
  • Для секретов используйте .env/secrets механизмы, но отдельно от production практик (не стоит хранить реальные ключи в compose для dev).

Отдельный взгляд: production vs dev окружение (и почему их не стоит смешивать)

Даже если вы используете один и тот же Dockerfile, стоит понимать разницу между “как разрабатываем” и “как запускаем в прод”.

  • Dev:
    • монтируем исходники
    • нужны инструменты для сборки/отладки
    • включён watcher
  • Prod:
    • копируем собранный артефакт (или делаем multi-stage build)
    • минимум пакетов
    • нет watcher, нет лишних зависимостей
    • корректная стратегия логирования и сигналов

Практика: держите Dockerfile.dev и Dockerfile (или multi-stage) — это предотвращает разрастание dev-образа в production.


Вывод: собираем Docker-подход как систему, а не как набор команд

Хороший Docker workflow — это не “одна конфигурация, которая всегда работает”, а набор устойчивых принципов:

  • Devcontainer даёт единый вход в среду разработки и уменьшает разночтения.
  • Docker Compose централизует сервисы и делает зависимости управляемыми.
  • Bind mount + отдельный volume для node_modules защищают от конфликтов.
  • Кеширование слоёв в Dockerfile.dev ускоряет пересборку только при изменении зависимостей.
  • Healthcheck и depends_on: condition: service_healthy убирают случайные ошибки старта.
  • Отладка строится через live reload и удалённые дебаг-порты, а не через бесконечные перезапуски контейнеров.

Если хочется углубиться в workflow, практики отладки и принципы построения контейнеров “от задач”, а не “от примеров”, полезно дополнить чтение материалами из [«/course/»] — но базу, описанную выше, вполне реально довести до продакшен-качества своими руками, используя этот шаблон как отправную точку.


Войдите, чтобы поставить лайк и оставить комментарий.

Автор

$ sudo teach IT

Продолжите обучение

Все курсы
Python – для начинающих!

Python – для начинающих!

С нуля до профессионального уровня. Подходит для всех. Учитесь каждый день и овладейте самым популярным языком программирования.

Перейти к курсу

Приложения для iPhone и Apple Watch на SwiftUI

Разработка приложений для iPhone и Apple Watch на SwiftUI: навигация, SwiftData, виджеты, часы, выпуск. Нужен Mac с Xcode 27, сами устройства не нужны.

Перейти к курсу
Ботостроение Telegram

Ботостроение Telegram

Лёгкий, быстрый и доступный способ познакомиться с миром ботостроения в Telegram. Видео, конспекты, практика и помощь – всё у нас на курсе.

Перейти к курсу

Приложения для macOS на SwiftUI

Разработка приложений для Mac на SwiftUI: окна и меню, Liquid Glass, SwiftData, сеть, выпуск. Нужен Mac с macOS 27 и Xcode 27.

Перейти к курсу

Другие статьи

Docker Compose для реальных проектов: конфиги, сети, volume и воспроизводимые окружения
docker

Docker Compose для реальных проектов: конфиги, сети, volume и воспроизводимые окружения

Научимся поднимать набор сервисов одним файлом, правильно разделять окружения и делать так, чтобы «у меня работает» исчезло.

20 июля 2026 г.
560
Docker для разработчика: запускаем приложение в контейнере с нуля
docker

Docker для разработчика: запускаем приложение в контейнере с нуля

Пошаговый гид по Docker без лишней теории: пишем Dockerfile, поднимаем сервис, разбираемся с volumes и сетями. После прочтения вы сможете контейнеризировать любой свой проект.

17 июля 2026 г.
550
Создание Telegram бота в 2026 легко и просто! Полный курсы!
создание

Создание Telegram бота в 2026 легко и просто! Полный курсы!

19 июня 2026 г.
1111
Какой первый проект выбрать новичку, чтобы не бросить обучение
первый

Какой первый проект выбрать новичку, чтобы не бросить обучение

Подберём 5–7 идей под уровень “с нуля”, объясним, что делать по шагам и как довести проект до результата без перегруза. В конце — как оформить мини-портфолио и что показать, даже если проект маленький.

23 сентября 2026 г.
210
FastAPI и фоновые задачи: когда лучше использовать BackgroundTasks, а когда очередь
fastapi

FastAPI и фоновые задачи: когда лучше использовать BackgroundTasks, а когда очередь

Поймём различия между синхронной обработкой, BackgroundTasks и внешними очередями. Разберём idempotency, ретраи и мониторинг фоновых процессов.

22 июля 2026 г.
780
Как выучить программирование самому и бесплатно: с чего начать и в каком порядке
выучить

Как выучить программирование самому и бесплатно: с чего начать и в каком порядке

Разберём понятный маршрут для новичка: как выбрать первый язык, что учить в первую очередь, какие мини-проекты делать и как не забросить занятия. Дам бесплатные ориентиры и план, чтобы знания складывались в портфолио.

21 сентября 2026 г.
330

Комментарии

Пока нет комментариев

Содержание

Зачем разработчику Docker: воспроизводимость и контролируемостьБазовый план: что именно мы собираемDevcontainer: вход в среду без лишней магииСтруктура devcontainerПодводные камни devcontainerDocker Compose: сборка сервисов без хаосаПример docker-compose.ymlПочему dependson с condition: servicehealthyDockerfile для разработки: кеширование и быстрый циклПример Dockerfile.dev (Node.js)Если вы используете pnpm/yarnПроброс исходников: что можно и чего лучше избегатьПочему отдельный volume для nodemodulesЧто насчёт watch/reloadПроброс портов и доступ извне: различаем localhost и networkПорты в ComposeТипичная ошибка: использование localhost в DATABASEURLHealthcheck: не только про БДЗдоровье приложенияБыстрая отладка без лишних перезапусковСценарий 1: приложение в dev режиме с live reloadСценарий 2: отладка в IDE через отладочный порт (Node.js example)Сценарий 3: “пересборка зависимостей” без пересборки всегоСценарий 4: миграции и инициализация БДСценарий 5: отладка проблем сети и подключения“Не трогайте контейнер без нужды”: управление перезапускамиПрактический шаблон: всё вместе (devcontainer + compose)Вариант: devcontainer через Docker ComposeЧто важно учестьВоспроизводимость: воспроизводимая сборка и “честные” версииПример принципа для NodeТиповые проблемы и их решения1) Контейнер стартует, но приложение не отвечает2) Изменения кода не видны3) Долгая пересборка образа при каждом чихе4) “Не хватает tool’ов” в контейнере5) Путаются переменные окружения между хостом и контейнеромОтдельный взгляд: production vs dev окружение (и почему их не стоит смешивать)Вывод: собираем Docker-подход как систему, а не как набор команд