Docker Compose: шпаргалка по командам и грабли
Как Compose находит проект, запуск и остановка, логи, exec и run, обновление образов, профили, несколько файлов и какие флаги удаляют данные.

Команды Compose v2 (docker compose, через пробел), сгруппированные по задачам. Рядом с каждой группой — типичные ошибки, которые стоят часов отладки.
Все команды проверены на VPS с Ubuntu 24.04 и Debian 12 — на tanaka.host оба образа ставятся при заказе сервера, а если что-то пойдёт не так, выручит консоль в кабинете.
Как Compose находит проект
- Файл. Без
-fищетсяcompose.yaml(такжеcompose.yml,docker-compose.yaml,docker-compose.yml) в текущей папке, потом в родительских.compose.override.yamlподмешивается автоматически. - Имя проекта. Берётся из
-p, переменнойCOMPOSE_PROJECT_NAME, поляname:в файле или имени папки — в таком порядке. Оно становится префиксом контейнеров, сетей и томов:/opt/blog/compose.yaml→blog-web-1,blog_default,blog_db_data. - Переменные подставляются из окружения и файла
.envрядом с compose-файлом.
Правило: сначала cd в папку проекта, потом команда. «Контейнеры пропали» в 90% случаев означает, что вы не в той папке.
Запуск и остановка
docker compose up -d # поднять всё в фоне
docker compose up -d app # только один сервис (и его зависимости)
docker compose up -d --wait # дождаться healthy
docker compose stop # остановить, контейнеры остаются
docker compose start # запустить остановленные
docker compose restart app # перезапустить сервис
docker compose down # остановить и удалить контейнеры и сети
docker compose kill # убить немедленно
Грабли:
restartне применяет изменения вcompose.yamlи.env. Для этого нуженup -d— он пересоздаст только то, что поменялось.upбез-dпривязывается к терминалу, и Ctrl+C останавливает всё.stopсохраняет контейнеры,downудаляет их. Именованные тома переживают и то, и другое.- На остановку даётся 10 секунд, потом SIGKILL. Для баз данных поставьте
stop_grace_period: 60sв сервисе илиdocker compose stop -t 60.
Состояние и логи
docker compose ps # сервисы проекта
docker compose ps -a # включая остановленные
docker compose ls # все проекты на сервере
docker compose logs -f # логи всех сервисов
docker compose logs -f --tail 100 app
docker compose logs --since 30m
docker compose top # процессы внутри контейнеров
docker compose stats # CPU и память
logs без --tail выведет всё с момента создания контейнера. ls показывает путь к compose-файлу каждого проекта — помогает найти «потерянный».
Команды внутри контейнеров
docker compose exec app sh # шелл в работающем контейнере
docker compose exec -u root app sh # под root
docker compose exec db psql -U postgres
docker compose exec -T db pg_dump -U postgres mydb > dump.sql # -T для вывода в файл и cron
docker compose run --rm app sh # новый временный контейнер
docker compose run --rm --no-deps app ./migrate
docker compose cp app:/app/config.yml ./config.yml
docker compose cp ./config.yml app:/app/config.yml
exec заходит в уже запущенный контейнер, run создаёт новый — всегда с --rm, иначе они копятся. run не публикует порты (нужен --service-ports). В контейнере может не быть bash — пробуйте sh.
Образы и обновление
docker compose pull # скачать свежие образы
docker compose build # собрать из Dockerfile
docker compose build --no-cache
docker compose up -d --build # собрать и поднять
docker compose up -d --force-recreate
docker compose up -d --pull always
Стандартное обновление:
docker compose pull
docker compose up -d
docker image prune -f
pull сам по себе ничего не меняет — контейнеры продолжают работать на старом образе до up -d. --force-recreate не скачивает и не собирает образ, только пересоздаёт контейнеры.
Проверка конфигурации
docker compose config # итоговый конфиг с подставленными переменными
docker compose config --quiet # только проверить синтаксис
docker compose config --services
docker compose --dry-run up -d # показать, что будет сделано
config печатает секреты из .env — не вставляйте вывод в чаты. Привычка config --quiet && docker compose up -d экономит много нервов.
Несколько файлов и проектов
docker compose -f compose.yaml -f compose.prod.yaml up -d
docker compose -f /opt/blog/compose.yaml ps
docker compose -p staging up -d
docker compose --env-file .env.prod up -d
Те же -f и -p нужно повторять в каждой команде, иначе Compose не найдёт проект. Удобнее задать их один раз в .env:
COMPOSE_FILE=compose.yaml:compose.prod.yaml
COMPOSE_PROJECT_NAME=blog
Профили
Сервисы, которые нужны не всегда (админка, отладочные инструменты):
services:
db:
image: postgres:18
adminer:
image: adminer
profiles: [tools]
ports:
- "127.0.0.1:8081:8080"
docker compose up -d # только db
docker compose --profile tools up -d # db и adminer
docker compose --profile tools down # down без профиля adminer не увидит
Очистка и опасные флаги
| Команда | Удаляет данные? |
|---|---|
docker compose down |
Нет |
docker compose down --remove-orphans |
Нет, убирает контейнеры удалённых из файла сервисов |
docker compose down --rmi all |
Нет, образы скачаются заново |
docker compose down -v |
Да, удаляет именованные тома вместе с базой |
docker compose up -d -V |
Анонимные тома |
docker volume prune --all |
Да, все тома, которые сейчас не используются, включая проекты в состоянии down |
Тома с external: true Compose не удаляет никогда. Перед down -v сделайте дамп.
Переход с docker-compose v1
v1 (Python, команда через дефис) не поддерживается с 2023 года. Файлы docker-compose.yml продолжают работать, но:
- имена контейнеров меняются с
project_web_1наproject-web-1— проверьте скрипты и мониторинг; - поле
version:игнорируется, его можно удалить; docker compose up -dв папке проекта пересоздаст контейнеры с новыми именами, тома останутся.
Для старых скриптов, вызывающих docker-compose, достаточно обёртки:
printf '#!/bin/sh\nexec docker compose "$@"\n' | sudo tee /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose