# Глава 1 — Основы работы с Docker

# Compose — Управление сервисами

Эта страница объясняет базовые команды `docker compose`, которые используются для запуска, остановки, пересборки и перезапуска сервисов в проекте. Материал рассчитан на начинающих: здесь разобрано, что делает каждая команда, в каких случаях её использовать и на что обратить внимание, чтобы случайно не сломать рабочее окружение.

---

### Что такое Docker Compose

`Docker Compose` — это инструмент для управления несколькими контейнерами как единым приложением.
Обычно в проекте есть файл `docker-compose.yml`, где описано:

* какие сервисы нужно запускать
* какие образы использовать
* какие порты пробрасывать
* какие папки подключать как volumes
* какие переменные окружения передавать контейнерам

Например, один проект может состоять из:

* `nginx`
* `php`
* `mysql`
* `redis`

Вместо того чтобы запускать каждый контейнер отдельно длинными командами `docker run`, Compose позволяет поднять всё одной командой.

---

### Перед началом работы

Обычно работа с Compose ведётся из директории проекта, где лежит `docker-compose.yml`.

Пример:

```bash
cd /opt/flamy_projects/project_name
```

Проверить, что файл действительно есть в текущей папке:

```bash
ls -la
```

Если нужно найти compose-файлы во всей папке проектов:

```bash
find /opt/flamy_projects -type f -name "docker-compose*.yml"
```

> **Примечание:**
> Большинство команд `docker compose` нужно выполнять именно в той директории, где находится `docker-compose.yml`. Иначе Docker не поймёт, с каким проектом работать.

---

### Базовый принцип работы

Чаще всего цикл работы выглядит так:

1. перейти в папку проекта
2. запустить сервисы
3. проверить, что контейнеры работают
4. посмотреть логи при ошибках
5. при необходимости пересобрать или перезапустить сервисы

---

### Запуск сервисов

#### Запуск всех сервисов в фоне

```bash
docker compose up -d
```

Эта команда:

* читает `docker-compose.yml`
* создаёт нужные контейнеры
* запускает их
* оставляет терминал свободным для дальнейшей работы

Флаг `-d` означает **detached mode**, то есть запуск в фоне.

#### Когда использовать

Подходит почти для любого обычного старта проекта:

* после перезагрузки сервера
* после первого клонирования проекта
* после остановки контейнеров
* после мелких изменений конфигурации

#### Пример

```bash
cd /opt/flamy_projects/site1
docker compose up -d
```

#### Что важно помнить

Если образа ещё нет локально, Docker попытается:

* скачать его из реестра
* либо собрать локально, если это описано в конфигурации

> **Для новичков:**
> `up` не всегда означает просто «включить». Эта команда может не только запускать, но и создавать контейнеры заново, если это требуется по конфигурации.

---

### Остановка и удаление контейнеров проекта

#### Остановка проекта

```bash
docker compose down
```

Команда останавливает и удаляет:

* контейнеры проекта
* созданные Compose-сети

#### Когда использовать

Подходит, если нужно:

* полностью выключить проект
* освободить ресурсы
* заново поднять окружение
* сбросить сетевые проблемы внутри проекта

#### Что команда **не удаляет**

По умолчанию `docker compose down` **не удаляет volumes**.
Это важно, потому что именно в volumes часто лежат данные:

* база данных
* загруженные файлы
* кэш приложения
* постоянные данные сервисов

> **Важно:**
> Для новичков это одна из самых полезных вещей: обычный `down` не стирает данные сам по себе. Но всё равно всегда нужно понимать, где именно проект хранит данные — в volumes, bind mounts или внутри контейнера.

#### Пример

```bash
docker compose down
```

После этого проект можно снова поднять:

```bash
docker compose up -d
```

---

### Принудительное пересоздание контейнеров

#### Пересоздать контейнеры даже без изменений

```bash
docker compose up -d --force-recreate
```

Эта команда заставляет Docker пересоздать контейнеры, даже если он считает, что ничего не поменялось.

#### Когда использовать

Полезно, если:

* контейнер ведёт себя странно
* изменились переменные окружения
* конфигурация применена не так, как ожидалось
* нужен «чистый» перезапуск контейнера без удаления volumes

#### Что важно помнить

* контейнеры будут пересозданы
* volumes останутся на месте
* данные в volumes не пропадут

> **Пояснение:**
> Контейнер и volume — это не одно и то же.
> Контейнер — это «запущенная оболочка приложения».
> Volume — это место, где могут лежать постоянные данные.
> Поэтому пересоздание контейнера не обязательно означает потерю данных.

---

### Пересборка образов

Пересборка нужна тогда, когда меняется не только запуск контейнера, а именно его образ.
Обычно это происходит, если вы изменили:

* `Dockerfile`
* системные пакеты
* зависимости приложения
* шаги сборки

---

#### Пересборка без использования кэша

```bash
docker compose build --no-cache
```

Docker при сборке старается использовать кэш, чтобы не выполнять одинаковые шаги повторно.
Это ускоряет работу, но иногда мешает, если нужен действительно «чистый» rebuild.

Флаг `--no-cache` говорит:
**не использовать ранее сохранённые слои**, а собрать всё заново.

#### Когда использовать

Подходит, если:

* изменения в Dockerfile «не подхватываются»
* обновились зависимости
* есть подозрение на устаревший build cache
* нужно убедиться, что образ собран полностью с нуля

#### Пример

```bash
docker compose build --no-cache
docker compose up -d
```

> **Примечание:**
> Эта операция может занять заметно больше времени, чем обычная сборка.

---

#### Пересобрать и сразу запустить

```bash
docker compose up -d --build
```

Команда делает два действия сразу:

1. при необходимости пересобирает образ
2. запускает контейнеры

#### Когда использовать

Это один из самых частых сценариев после изменения:

* `Dockerfile`
* зависимостей
* конфигурации сборки

#### Пример

```bash
docker compose up -d --build
```

#### Чем отличается от `build --no-cache`

* `docker compose up -d --build` может использовать кэш
* `docker compose build --no-cache` собирает всё полностью заново

Если нужно просто обновить контейнер после обычных изменений — чаще хватает:

```bash
docker compose up -d --build
```

Если есть сомнения в корректности кэша — используйте:

```bash
docker compose build --no-cache
docker compose up -d
```

---

### Обновление образов из реестра

#### Скачать свежие версии образов

```bash
docker compose pull
```

Команда скачивает новые версии образов, которые указаны в `docker-compose.yml`.

#### Когда использовать

Подходит, если проект использует готовые образы из registry, например:

* `nginx:latest`
* `redis:7`
* `mysql:8`

#### Важный момент

`docker compose pull` **только скачивает образы**, но **не перезапускает контейнеры автоматически**.

Чтобы применить обновление, обычно выполняют:

```bash
docker compose pull && docker compose up -d
```

#### Пример

```bash
cd /opt/flamy_projects/site1
docker compose pull
docker compose up -d
```

> **Важно:**
> На production-серверах обновление образов нужно делать осторожно. Новая версия образа может изменить поведение приложения или сломать совместимость.

---

### Перезапуск сервисов

Иногда контейнер не нужно пересобирать или пересоздавать — достаточно просто перезапустить процесс.

---

#### Перезапуск одного сервиса

```bash
docker compose restart <service>
```

Пример:

```bash
docker compose restart nginx
```

#### Когда использовать

Подходит, если:

* сервис завис
* нужно перечитать конфигурацию
* произошёл временный сбой
* после некоторых изменений достаточно обычного рестарта

---

#### Перезапуск всех сервисов

```bash
docker compose restart
```

Перезапускает все сервисы, описанные в compose-файле.

#### Когда использовать

Подходит, если:

* нужно быстро перезапустить весь проект
* нет уверенности, какой именно сервис работает некорректно
* нужно «освежить» всё окружение без удаления контейнеров

---

#### Остановка и запуск отдельного сервиса вручную

```bash
docker compose stop <service> && docker compose start <service>
```

Пример:

```bash
docker compose stop php && docker compose start php
```

#### Зачем это нужно, если есть `restart`

Иногда удобнее разделить действия на две части:

* сначала корректно остановить контейнер
* затем отдельно запустить снова

Это бывает полезно при диагностике или когда нужно убедиться, что сервис полностью остановился.

---

### Запуск только одного сервиса

```bash
docker compose up -d <service>
```

Пример:

```bash
docker compose up -d nginx
```

#### Когда использовать

Полезно, если:

* нужно поднять только один сервис
* вы тестируете конкретный контейнер
* не хотите трогать всё окружение

> **Примечание:**
> Если сервис зависит от других, Compose может поднять и их тоже.

---

### Проверка итоговой конфигурации

#### Посмотреть итоговый compose-конфиг

```bash
docker compose config
```

Эта команда показывает итоговую конфигурацию после обработки:

* `docker-compose.yml`
* override-файлов
* переменных окружения
* подстановок из `.env`

#### Когда использовать

Очень полезно перед запуском, если:

* не подставляются env-переменные
* есть сомнения в корректности конфигурации
* нужно понять, что Docker реально «видит»

#### Почему это важно для новичков

Иногда в YAML всё выглядит правильно, но итоговая конфигурация получается другой.
`docker compose config` помогает увидеть конечный результат до запуска.

---

### Наиболее частые сценарии в работе

#### Обычный запуск проекта

```bash
docker compose up -d
```

---

#### Обновить образы и применить изменения

```bash
docker compose pull && docker compose up -d
```

---

#### После изменения Dockerfile или зависимостей

```bash
docker compose up -d --build
```

---

#### Полная пересборка без кэша

```bash
docker compose build --no-cache
docker compose up -d
```

---

#### Быстро перезапустить один сервис

```bash
docker compose restart nginx
```

---

#### Полностью выключить проект

```bash
docker compose down
```

---

### Что выбрать в типовых ситуациях

#### Ситуация: нужно просто запустить проект

Используйте:

```bash
docker compose up -d
```

---

#### Ситуация: поменялся Dockerfile

Используйте:

```bash
docker compose up -d --build
```

---

#### Ситуация: образ ведёт себя странно, нужен чистый rebuild

Используйте:

```bash
docker compose build --no-cache
docker compose up -d
```

---

#### Ситуация: нужно скачать свежие образы из registry

Используйте:

```bash
docker compose pull && docker compose up -d
```

---

#### Ситуация: сервис просто нужно перезапустить

Используйте:

```bash
docker compose restart <service>
```

---

### Частые ошибки новичков

#### Запуск команды не из той директории

Если выполнить `docker compose up -d` не там, где лежит `docker-compose.yml`, можно получить ошибку о том, что конфигурационный файл не найден.

---

#### Путаница между `restart`, `up`, `build` и `down`

Кратко:

* `restart` — просто перезапуск уже существующих контейнеров
* `up` — поднять проект
* `up --build` — поднять проект с пересборкой
* `down` — остановить и удалить контейнеры проекта

---

#### Ожидание, что `pull` сам обновит работающие контейнеры

`docker compose pull` только скачивает новый образ.
Чтобы контейнеры начали работать на новой версии, нужен ещё запуск:

```bash
docker compose up -d
```

---

### Краткая памятка

```bash
docker compose up -d                     # Запуск проекта в фоне
docker compose down                      # Остановка и удаление контейнеров проекта
docker compose up -d --force-recreate    # Пересоздать контейнеры принудительно
docker compose build --no-cache          # Полная пересборка без кэша
docker compose up -d --build             # Пересборка и запуск
docker compose pull                      # Скачать свежие образы
docker compose restart <service>         # Перезапуск одного сервиса
docker compose restart                   # Перезапуск всех сервисов
docker compose stop <service> && docker compose start <service>  # Остановить и запустить сервис отдельно
docker compose up -d <service>           # Запуск одного сервиса
docker compose config                    # Проверка итоговой конфигурации
```

# Docker — Отладка контейнеров

Эта страница объясняет основные команды Docker, которые используются для диагностики и отладки контейнеров. Здесь разобраны способы посмотреть запущенные контейнеры, проверить их состояние, изучить логи, подключиться внутрь контейнера и выполнить команды для анализа проблемы. Материал рассчитан на начинающих и помогает быстро понять, **что происходит внутри контейнера**, если приложение работает некорректно.

---

# Когда используется отладка контейнеров

На практике команды из этой страницы используются в следующих ситуациях:

* контейнер **не запускается**
* сервис **падает после старта**
* приложение **возвращает ошибки**
* сервис **не отвечает**
* контейнер **постоянно перезапускается**
* нужно проверить **что происходит внутри контейнера**

Типичный порядок диагностики:

1. проверить список контейнеров
2. проверить статус контейнера
3. посмотреть логи
4. зайти внутрь контейнера
5. проверить процессы или выполнить команды

---

# Просмотр контейнеров

## Показать контейнеры текущего проекта

```bash
docker compose ps
```

Команда показывает контейнеры, которые относятся к текущему `docker-compose` проекту.

Пример вывода:

```
NAME                IMAGE          STATUS        PORTS
project_nginx       nginx:latest   Up 2 hours    0.0.0.0:80->80/tcp
project_php         php:8.2-fpm    Up 2 hours
```

### Что здесь можно увидеть

* имя контейнера
* используемый образ
* статус контейнера
* проброшенные порты

### Когда использовать

Это первая команда, которую стоит выполнить, если нужно проверить:

* запущен ли сервис
* работает ли контейнер
* не упал ли он

---

## Показать все запущенные контейнеры

```bash
docker ps
```

Эта команда показывает **все запущенные контейнеры в системе**, независимо от проекта.

Пример:

```
CONTAINER ID   IMAGE         STATUS         PORTS
ab12cd34       nginx         Up 2 hours     80/tcp
cd34ef56       redis         Up 3 hours     6379/tcp
```

### Чем отличается от `docker compose ps`

| Команда             | Показывает                  |
| ------------------- | --------------------------- |
| `docker compose ps` | контейнеры текущего проекта |
| `docker ps`         | все контейнеры на сервере   |

---

## Показать все контейнеры (включая остановленные)

```bash
docker ps -a
```

Показывает:

* работающие контейнеры
* остановленные контейнеры
* контейнеры с ошибками

Пример статуса:

```
Exited (1) 5 minutes ago
```

### Что это означает

Контейнер **запустился, но приложение внутри завершилось с ошибкой**.

В таком случае следующим шагом нужно посмотреть логи.

---

## Табличный формат вывода

```bash
docker ps -a --format "table {{.ID}}\t{{.Names}}\t{{.Status}}\t{{.Ports}}"
```

Этот формат удобен, если нужно быстро увидеть:

* ID контейнера
* имя
* статус
* порты

Пример вывода:

```
CONTAINER ID   NAMES         STATUS          PORTS
3acb1234       project_php   Up 10 minutes
7d8e5678       project_nginx Up 10 minutes   80/tcp
```

---

# Просмотр логов контейнеров

Логи — это основной источник информации при отладке.

Именно здесь можно увидеть:

* ошибки приложения
* ошибки запуска
* проблемы подключения к базе
* ошибки конфигурации

---

## Просмотр логов сервиса

```bash
docker compose logs <service>
```

Пример:

```bash
docker compose logs nginx
```

Вывод покажет весь лог контейнера.

---

## Просмотр логов в реальном времени

```bash
docker compose logs -f <service>
```

Флаг `-f` означает **follow** — следить за логом в реальном времени.

Пример:

```bash
docker compose logs -f php
```

Это удобно, если:

* вы только что перезапустили сервис
* нужно увидеть новые ошибки

Выход из режима просмотра:

```
CTRL + C
```

---

## Показать последние строки логов

```bash
docker compose logs --tail=100 <service>
```

Показывает только последние 100 строк.

Пример:

```bash
docker compose logs --tail=100 nginx
```

### Когда использовать

Если контейнер работает давно и лог очень большой.

---

## Логи с временными метками

```bash
docker compose logs --timestamps <service>
```

Пример:

```bash
docker compose logs --timestamps php
```

Вывод будет выглядеть примерно так:

```
2026-03-11T12:32:10 app started
2026-03-11T12:32:11 connected to database
```

Это удобно для анализа событий во времени.

---

# Подключение внутрь контейнера

Иногда для диагностики нужно **зайти внутрь контейнера**, чтобы:

* посмотреть файлы
* проверить конфигурацию
* выполнить команды
* проверить сетевые подключения

---

## Подключиться через shell

```bash
docker compose exec <service> sh
```

Пример:

```bash
docker compose exec php sh
```

После выполнения команды вы окажетесь внутри контейнера.

---

## Использование bash

Если в контейнере установлен `bash`, можно использовать:

```bash
docker compose exec <service> bash
```

Пример:

```bash
docker compose exec php bash
```

> **Важно:**
> Не во всех контейнерах есть `bash`. Многие минимальные образы используют только `sh`.

---

## Проверить файлы внутри контейнера

После входа можно выполнять обычные команды Linux:

```
ls
cd
cat
ps
top
```

Например:

```
ls /var/www/html
```

---

# Просмотр процессов внутри контейнера

```bash
docker compose top <service>
```

Пример:

```bash
docker compose top php
```

Команда показывает список процессов внутри контейнера.

Пример вывода:

```
UID     PID     CMD
root    123     php-fpm
```

### Когда использовать

Полезно, если:

* приложение зависло
* нужно проверить, запущен ли процесс
* нужно убедиться, что сервис действительно работает

---

# Выполнение команды внутри контейнера

Можно выполнить команду **без входа в shell**.

Формат:

```bash
docker compose exec <service> <command>
```

Пример:

```bash
docker compose exec php php -v
```

Вывод:

```
PHP 8.2.4 (cli)
```

---

### Ещё примеры

Проверить установленные пакеты:

```bash
docker compose exec php composer --version
```

Проверить Node.js:

```bash
docker compose exec node node -v
```

---

# Копирование файлов из контейнера

Иногда нужно забрать файл из контейнера.

---

## Копирование файла из контейнера

```bash
docker cp container:/path/file .
```

Пример:

```bash
docker cp project_php:/var/log/php.log .
```

Файл будет скопирован в текущую папку.

---

## Копирование файла в контейнер

```bash
docker cp file container:/path/
```

Пример:

```bash
docker cp config.php project_php:/var/www/config.php
```

---

# Типичный сценарий диагностики

Если сервис не работает, обычно делают следующее:

### 1 Проверить контейнеры

```bash
docker compose ps
```

---

### 2 Проверить логи

```bash
docker compose logs --tail=100
```

---

### 3 Если ошибка не очевидна — подключиться внутрь

```bash
docker compose exec php sh
```

---

### 4 Проверить процессы

```bash
docker compose top php
```

---

### 5 Проверить приложение вручную

Например:

```
curl localhost
```

---

# Полезные советы для новичков

## Всегда начинайте диагностику с логов

В большинстве случаев ошибка уже записана в лог.

---

## Не путайте контейнер и сервис

В Compose:

* **service** — описание контейнера в `docker-compose.yml`
* **container** — фактически запущенный экземпляр

---

## Проверяйте статус контейнера

Если статус:

```
Exited
```

контейнер уже остановился, и нужно смотреть логи.

---

# Краткая памятка

```bash
docker compose ps                          # контейнеры текущего проекта
docker ps                                  # все запущенные контейнеры
docker ps -a                               # все контейнеры включая остановленные

docker compose logs <service>              # логи сервиса
docker compose logs -f <service>           # логи в реальном времени
docker compose logs --tail=100 <service>   # последние строки логов
docker compose logs --timestamps <service> # логи с временными метками

docker compose exec <service> sh           # войти в контейнер
docker compose exec <service> bash         # войти через bash
docker compose exec <service> <command>    # выполнить команду

docker compose top <service>               # процессы контейнера

docker cp container:/path/file .           # копировать из контейнера
docker cp file container:/path/            # копировать в контейнер
```

# Docker Compose — Структура docker-compose.yml

Эта страница объясняет структуру файла `docker-compose.yml` и основные параметры, используемые при описании сервисов Docker. Здесь разобраны ключевые разделы конфигурации, такие как `services`, `volumes`, `networks`, `environment`, `ports` и другие. Материал рассчитан на начинающих и помогает понять, **как правильно описывать инфраструктуру приложения в Docker Compose**.

---

# Что такое docker-compose.yml

`docker-compose.yml` — это файл конфигурации, который описывает:

* какие контейнеры нужно запустить
* какие образы использовать
* какие порты открыть
* какие volumes подключить
* какие сети создать

Compose позволяет запускать всё приложение **одной командой**:

```bash
docker compose up -d
```

---

# Базовая структура docker-compose.yml

Пример минимального файла:

```yaml
version: "3.9"

services:
  nginx:
    image: nginx:1.25
    ports:
      - "8080:80"
```

Этот файл создаёт контейнер nginx и открывает порт `8080`.

---

# Основные разделы docker-compose.yml

Типичная структура файла выглядит так:

```yaml
services:
volumes:
networks:
```

---

# Раздел services

Раздел `services` описывает контейнеры проекта.

Пример:

```yaml
services:
  nginx:
    image: nginx:1.25

  php:
    image: php:8.2-fpm
```

В этом примере создаются два сервиса:

* nginx
* php

Каждый сервис становится отдельным контейнером.

---

# Параметр image

Определяет Docker-образ, который будет использоваться.

Пример:

```yaml
services:
  nginx:
    image: nginx:1.25
```

Docker скачает образ `nginx:1.25`, если он отсутствует.

---

# Параметр build

Используется, если образ нужно **собрать локально из Dockerfile**.

Пример:

```yaml
services:
  app:
    build: .
```

Это означает:

```text
собрать образ из Dockerfile текущей директории
```

Можно указать путь:

```yaml
services:
  app:
    build: ./app
```

---

# Параметр ports

Используется для проброса портов.

Пример:

```yaml
ports:
  - "8080:80"
```

Это означает:

```text
сервер:8080 → контейнер:80
```

После запуска приложение будет доступно:

```
http://server:8080
```

---

# Параметр volumes

Подключает volumes или папки сервера.

Пример:

```yaml
volumes:
  - ./src:/var/www/html
```

Это означает:

```text
сервер ./src → контейнер /var/www/html
```

---

# Использование Docker Volumes

Пример с volume:

```yaml
services:
  mysql:
    image: mysql:8
    volumes:
      - mysql_data:/var/lib/mysql

volumes:
  mysql_data:
```

Volume будет хранить данные базы.

---

# Параметр environment

Передаёт переменные окружения контейнеру.

Пример:

```yaml
environment:
  MYSQL_ROOT_PASSWORD: secret
  MYSQL_DATABASE: app_db
```

Контейнер получит переменные:

```
MYSQL_ROOT_PASSWORD
MYSQL_DATABASE
```

---

# Использование .env файла

Переменные можно хранить в `.env`.

Пример:

```text
DB_PASSWORD=secret
APP_ENV=production
```

И использовать в Compose:

```yaml
environment:
  DB_PASSWORD: ${DB_PASSWORD}
```

---

# Параметр depends_on

Определяет зависимости между сервисами.

Пример:

```yaml
services:
  php:
    depends_on:
      - mysql
```

Это означает:

```text
сначала запускается mysql
затем php
```

> **Важно:**
> `depends_on` не гарантирует, что сервис полностью готов к работе.

---

# Параметр restart

Определяет политику перезапуска контейнера.

Пример:

```yaml
restart: always
```

Возможные значения:

| Значение       | Поведение                                 |
| -------------- | ----------------------------------------- |
| no             | не перезапускать                          |
| always         | всегда перезапускать                      |
| on-failure     | только при ошибке                         |
| unless-stopped | перезапускать, пока не остановлен вручную |

---

# Параметр networks

Определяет сети Docker.

Пример:

```yaml
services:
  app:
    networks:
      - backend

networks:
  backend:
```

Контейнер будет подключён к сети `backend`.

---

# Пример полного docker-compose.yml

Пример простого веб-приложения:

```yaml
services:

  nginx:
    image: nginx:1.25
    ports:
      - "80:80"
    volumes:
      - ./src:/var/www/html

  php:
    image: php:8.2-fpm
    volumes:
      - ./src:/var/www/html
    depends_on:
      - mysql

  mysql:
    image: mysql:8
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: app
    volumes:
      - mysql_data:/var/lib/mysql

volumes:
  mysql_data:
```

Этот файл запускает:

* nginx
* php
* mysql

---

# Проверка docker-compose.yml

Перед запуском полезно проверить конфигурацию:

```bash
docker compose config
```

Команда покажет итоговую конфигурацию после обработки переменных.

---

# Запуск проекта

Запуск всех сервисов:

```bash
docker compose up -d
```

---

# Остановка проекта

```bash
docker compose down
```

---

# Типичные ошибки в docker-compose.yml

## Ошибка YAML

Файл YAML чувствителен к отступам.

Неправильно:

```yaml
services:
nginx:
image: nginx
```

Правильно:

```yaml
services:
  nginx:
    image: nginx
```

---

## Неверные порты

Если порт уже используется:

```text
Bind for 0.0.0.0:80 failed
```

Нужно изменить порт.

---

## Отсутствие volumes

Если данные не вынесены в volumes, они могут потеряться при пересоздании контейнера.

---

# Краткая памятка

```text
services     → контейнеры проекта
image        → используемый образ
build        → сборка образа
ports        → проброс портов
volumes      → подключение хранилища
environment  → переменные окружения
depends_on   → зависимости сервисов
restart      → политика перезапуска
networks     → сети контейнеров
```