## Зачем Docker Compose

Когда сервисов несколько (БД, бэкенд, фронт, прокси), писать длинные `docker run` неудобно. **Compose** описывает весь стек в одном файле (`compose.yaml` или `docker-compose.yml`), поднимает общую сеть и тома, учитывает порядок старта через `depends_on` и проверки `healthcheck`.

Команды:

`docker compose up -d --build` - запустить докер компос в фоне и полностью пересобрать
`docker compose ps` - список контейнеров в докер компос
`docker compose logs -f api` - смотреть в реальном времени логи контейнера `api` из докер компос
`docker compose down` - остановить контейнере и удалить

## Где лежит учебный проект
В репозитории подготовлен полный стек, четыре сервиса:

| Путь                                        | Содержимое                               |
| ------------------------------------------- | ---------------------------------------- |
| `docker/examples/multi-service/compose.yaml` | Описание всех сервисов, сетей, томов     |
| `docker/examples/multi-service/.env.example`       | Пример переменных окружения для Compose  |
| `docker/examples/multi-service/web/`               | Nginx + статика через `COPY`             |
| `docker/examples/multi-service/api/`               | Flask + Postgres + загрузка файлов в том |
| `docker/examples/multi-service/proxy/`             | Входной nginx: `/` → web, `/api/` → api  |

Скопируйте переменные окружения:

```
cd docker/examples/multi-service
cp .env.example .env
```

<img src="./assets/image_1777885724388.jpg" width="auto">

Запуск:
```
docker compose up -d --build
```

<img src="./assets/image_1777885746375.jpg" width="auto">

<img src="./assets/image_1777885786226.jpg" width="auto">

<img src="./assets/image_1777885816731.jpg" width="auto">

Все сервисы подняты

Откройте в браузере адрес с портом из `.env` (по умолчанию `http://127.0.0.1:8080`). Главная страница — статика из сервиса **web**: мини-дашборд с индикаторами **прокси**, **web**, **API** и **PostgreSQL** (данные приходят с эндпоинта `/api/status` через прокси), блок **заметок** (чтение и создание через `/api/notes`) и простая загрузка файлов в том **api_uploads**. Всё работает в одной вкладке, без `curl` — гайд остаётся про Docker и Compose, а проверка стека — через интерфейс.

**Скриншот:** открытая главная страница с зелёными статусами и списком заметок.

<img src="./assets/image_1777886340548.jpg" width="auto">

Нам сейчас не интересна логика работы стека, так как не по теме.

## Разбор ключевых фрагментов `docker-compose.yaml`### Имена и сеть
Поле `name: multi-service-demo` задаёт **префикс** для имён контейнеров/ресурсов по умолчанию (удобно не конфликтовать с другими проектами).

Сеть `backend` с драйвером `bridge` - все перечисленные сервисы в одной L2-сети, видят друг друга по **DNS-имени сервиса** (`db`, `api`, `web`, `proxy`).

### Зависимости и здоровье
```
depends_on:
  db:
    condition: service_healthy
```

Без `condition` Compose лишь **упорядочивает** старт, но не ждёт готовности БД. С `healthcheck` у `db` сервис `api` не начнёт считаться поднятым для зависимых, пока Postgres не пройдёт проверку.

<img src="./assets/image_1777886554471.jpg" width="auto">

### `expose` vs `ports`

- **`ports`** - публикация на хост (нужно для proxy).
- **`expose`** - документация + открытие порта **между** контейнерами сети; на сетевой интерфейс хоста не выводится.

Так мы не публикуем Postgres наружу - к БД можно попасть только из контейнеров в той же сети (или если вы явно добавите `ports` для отладки).

### Тома
```yaml
volumes:
  pgdata:
  api_uploads:
```

Именованные тома хранятся в области Docker на диске. Пример «скопировать/сохранить файл в Docker» в runtime:

```
echo hello > /tmp/up.txt
docker cp /tmp/up.txt "$(docker compose ps -q api)":/data/uploads/host-demo.txt
docker compose exec api ls -la /data/uploads
```

Альтернатива для разработки - **bind-mount** каталога с хоста в сервис (в учебном файле не включено, чтобы не привязывать пути к вашему `$HOME`):

```yaml
services:
  api:
    volumes:
      - ./local_uploads:/data/uploads
```

## Копирование файлов в контейнер в контексте Compose

| Способ | Когда использовать |
|--------|---------------------|
| `COPY` в `Dockerfile` | Статика, код, конфиги, которые должны быть **в образе** на момент деплоя |
| Именованный / bind том | Данные, логи, загрузки пользователей, меняющиеся без пересборки |
| `docker cp` | Разовая отладка, экстренная подмена файла |

## Обновление одного сервиса после правки кода
```
# изменили только api/app.py
docker compose build api
docker compose up -d api
```

## Остановка и очистка
Мягко (тома сохраняются):

```
docker compose down
```

Полный сброс демо:

```
docker compose down -v --rmi local
```
## Документация
- [Compose file reference](https://docs.docker.com/compose/compose-file/)
- [Networking in Compose](https://docs.docker.com/compose/networking/)
