Короткий ответ
Стек проекта app в /opt/app не поднялся — это почти всегда файл Compose, имя проекта, сеть или depends_on, а не «Docker сломался». Сначала docker compose config (рендер без up), docker info (демон жив), затем конфликт портов и сетей. depends_on без healthcheck не ждёт готовности Postgres, только старт контейнера. Не запускайте down -v «чтобы пересоздать»: -v снимет named volume app_data.
Плагин Compose v2: команда docker compose, не устаревший docker-compose из pip, если вы на Ubuntu 22.04/24.04 с docker-ce.
Симптомы и как отличить
docker compose up -dпечатаетyaml: line 17: did not find expected key;Error response from daemon: network app_backend not found;service "web" depends on undefined service "redis";Bind for 0.0.0.0:8080 failed: port is already allocated;- часть сервисов Up,
dbнет — смотрите не «сеть Docker», а один сервис.
| Ошибка | Не то | Куда |
|---|---|---|
| Cannot connect to daemon | compose файл | daemon |
| контейнеры Up, ping по имени нет | up «успешен» | сети сервисов |
| listen есть, с LAN нет | publish | порт |
| volume ... not a directory | mounts | volume |
Возможные причины
- Табы/CRLF/дубли ключа
ports:в YAML. - Смешали version: "3.8" с атрибутами Compose Specification (
develop:,include:), плагин v2 их не понял или наоборот. - Внешняя сеть
external: true, которую забылиdocker network create. depends_onна сервис из другого файла, не попавшего в-f.- Порт хоста занят nginx/другим стеком.
- Профили
profiles:— сервис не в default,upего молча не стартует. - Редко:
name:контейнера захардкожен и уже занят чужим проектом.
Диагностика
1. Демон и версия клиента
docker info >/dev/null && echo daemon_ok
docker compose version
cd /opt/app && ls -l compose.yaml docker-compose.yml compose.yml 2>/dev/nullДва файла compose.yaml и docker-compose.yml в одном каталоге — источник сюрпризов. Compose v2 мержит по своим правилам; лучше один файл.
2. Рендер конфига
cd /opt/app
docker compose config >/tmp/app.compose.rendered.yaml
echo $?
docker compose config --services
docker compose config --volumes
docker compose config --networksОшибка unmarshal на этом шаге. Смотрите номер строки в рендере, затем в исходнике.
3. Сети и проект
docker compose ls
docker network ls | grep app
docker compose ps -aОжидаемая user-defined сеть часто app_default. Если YAML требует app_backend как external — её должно быть видно в network ls до up.
4. depends_on и профили
docker compose config | grep -n -A6 'depends_on'
docker compose --profile '*' config --servicesСервис только с profiles: [batch] не войдёт в обычный up -d.
5. Порт хоста
sudo ss -tlnp | grep -E ':8080|:80 '
docker compose config | grep -A4 'ports:'Решение
Сценарий A. YAML не парсится
Правите отступ (два пробела), кавычки в environment. Проверка:
python3 -c 'import yaml,sys; yaml.safe_load(open("compose.yaml"))'
docker compose config >/dev/nullНе «конвертируйте» файл через онлайн-YAML с чужой машины с секретами.
Сценарий B. network not found
Если сеть должна быть внутренней:
networks:
backend:Без external: true. Compose создаст app_backend.
Если сеть общая на хосте:
docker network create app_backend
docker compose up -dДокументируйте create в runbook, не в чате.
Сценарий C. depends_on врёт о порядке
services:
db:
healthcheck:
test: ["CMD-SHELL", "pg_isready -U app -d app"]
interval: 5s
timeout: 3s
retries: 20
web:
depends_on:
db:
condition: service_healthyБез healthcheck depends_on: [db] только ждёт start, не accept на 5432. Приложение web падает — это уже мгновенный exit, не «compose сломался».
Сценарий D. port already allocated
Найдите владельца 8080, не меняйте вслепую на 8081 в проде без DNS/proxy.
sudo ss -tlnp | grep 8080Либо остановите чужой стек, либо поправьте publish. Тема публикации: порт недоступен.
Сценарий E. Несколько -f
docker compose -f /opt/app/compose.yaml -f /opt/app/compose.prod.yaml configВсегда одни и те же -f в systemd unit и в руках админа. Иначе «у меня работает».
Как проверить, что проблема устранена
cd /opt/app
docker compose up -d
docker compose ps
docker compose top
docker network inspect app_default --format '{{len .Containers}}'Все нужные сервисы running (или healthy). Число контейнеров на сети проекта совпадает с ожиданием. DNS-имя db резолвится из web — см. Docker DNS.
Если не помогло
upок, браузер нет — это порт/firewall, не YAML.service "web" depends on undefined service "db"после split файлов — не тот-f.- Orphans:
docker compose up -d --remove-orphansудалит контейнеры этого проекта, которых нет в текущем файле. Не путать с чужими стеками, если имя проекта общее. include:в спецификации — проверьте версиюdocker compose version; старый плагин не поймёт.- Build context ENOENT — путь относительно файла compose, не cwd.
Профилактика
- Один
compose.yaml, overlays явно-f. COMPOSE_PROJECT_NAME=appв/opt/app/.env(не секреты туда).- CI:
docker compose config -q. - Запрет
down -vв шпаргалках без подтверждения томаapp_data. - Healthcheck +
condition: service_healthyдля БД.
FAQ
docker compose vs docker-compose
На Ubuntu с docker-ce 27.x используйте плагин v2. Бинарь docker-compose 1.29 иначе парсит condition: и секреты иначе. Сверьте docker compose version.
Нужен ли version: "3.9"?
Для Compose Specification поле version игнорируется. Не чините им сети.
Почему сеть называется app_default, а в YAML default?
Префикс проекта. В контейнере DNS-имя сервиса web, не app-web-1 (это hostname контейнера). Путаница даёт «не видят друг друга».
Можно ли network_mode: host чтобы «точно поднялось»?
Сломаете DNS сервисов и publish. Не обход для YAML.
up --force-recreate удалит app_data?
Нет, named volume живёт отдельно от контейнера. Удаляет -v у down/rm.