up, down, logs, ps, exec: рабочий цикл compose
Compose в работе — это десяток команд, которые повторяются каждый день. up, down, logs, ps, exec плюс ещё несколько. В этом уроке разберём каждую с реальными флагами и сценариями. Цель — чтобы после урока ты не лез в docker compose --help за рутинными операциями.
up: запуск стенда
docker compose up
Запускает все сервисы в foreground. Логи всех контейнеров идут в твой терминал, цветными префиксами по имени сервиса. Ctrl+C — корректный shutdown: compose шлёт SIGTERM каждому контейнеру, ждёт 10 секунд, потом SIGKILL.
Detached
docker compose up -d
То же самое, но в фоне (detached). После запуска возвращает контроль в shell. Логи смотришь через docker compose logs.
Это default-режим для нормальной работы. up без -d — для быстрой проверки, что всё стартует.
Force rebuild
Если изменил Dockerfile или зависимости — нужно пересобрать образ:
docker compose up -d --build
--build форсит сборку всех сервисов с build:-секцией, даже если образ существует. Без флага compose использует существующий локальный образ.
docker compose build app # пересобрать только app
docker compose up -d # запустить с новым образом
— альтернативно, два шага.
Pull
docker compose up -d --pull always
--pull always — каждый раз дёргать registry, даже если образ есть локально. Полезно, чтобы получить свежий тэг типа :latest.
docker compose pull # только pull всех образов, без запуска
Selective up
docker compose up -d postgres redis # только эти два сервиса
docker compose up -d --no-deps app # app, игнорируя depends_on
--no-deps нужен, когда у тебя уже Postgres запущен и ты хочешь перезапустить только app, не трогая БД.
down: остановка и cleanup
docker compose down
Останавливает все контейнеры стенда и удаляет их. Удаляется и сеть проекта.
Volume и образы НЕ трогаются. Это важно: данные Postgres переживут down.
Полный wipe
docker compose down -v
-v дополнительно удаляет named volumes, объявленные в compose-файле. Anonymous volumes тоже удаляются. Это уничтожит данные Postgres.
docker compose down --rmi local
Удаляет ещё и собранные локально образы (только те, у которых нет registry-prefix). Для очень тщательного wipe — down -v --rmi all удалит вообще всё.
docker compose down -v — частая команда «когда что-то сломалось, давай пересоздадим». Запомни: она удаляет данные. Если в pgdata лежала рабочая БД — она пропадёт. Перед -v бэкап.
stop / start / restart
В отличие от down, stop контейнеры не удаляет:
docker compose stop # все
docker compose stop app # только app
docker compose start # запустить остановленные обратно
docker compose restart # stop + start (без пересборки)
stop полезен, когда хочется освободить ресурсы, но потом продолжить с тем же state. После start контейнер увидит тот же volume и продолжит работу.
restart — для применения изменений в environment или примонтированных конфигах. Если код в bind-mount изменился — restart дёрнет приложение.
logs: смотреть выхлоп
docker compose logs
# Все логи всех сервисов, с цветными префиксами.
docker compose logs app
# Только app.
docker compose logs -f
# Follow — стримит новые логи реал-тайм.
docker compose logs --tail 100
# Последние 100 строк.
docker compose logs --since 10m
# Логи за последние 10 минут.
docker compose logs -t
# С timestamps.
Самая частая комбинация в дев-цикле:
docker compose logs -f --tail 50 app
Хвост 50 строк + follow. Видишь свежие логи, не захлёбываешься историей.
ps: состояние
docker compose ps
# NAME IMAGE STATUS PORTS
# myproj-app-1 myorg/app:dev Up 5 minutes 0.0.0.0:8000->8000/tcp
# myproj-postgres-1 postgres:17 Up 5 minutes (healthy) 127.0.0.1:5432->5432/tcp
-a — включая остановленные. --format json — машинно-читаемый формат.
docker compose ps --services
# postgres
# app
— только имена сервисов.
docker compose ps -q
# 8a3f...
# c5d2...
— ID контейнеров. Удобно для скриптов: docker compose ps -q | xargs docker stats.
exec: зайти в контейнер
docker compose exec postgres psql -U postgres
# Открывает psql внутри контейнера postgres.
docker compose exec app sh
# Shell внутри app.
docker compose exec -T app sh -c 'env | grep DB'
# -T отключает TTY-allocation, полезно в скриптах.
docker compose exec -u root app sh
# Зайти как root, даже если образ запускает от другого user'а.
Команды через exec выполняются в уже запущенном контейнере. Если контейнер не запущен — exec упадёт.
Альтернатива — run:
docker compose run --rm app python -c "print('hi')"
run запускает новый контейнер из того же образа, для одной команды. --rm удаляет его после. Полезно для one-off задач: миграции, скрипты, шеллы.
| exec | run |
|---|---|
| Уже запущенный контейнер | Создаёт новый из образа |
| Шарит state с основным процессом | Чистый env, никакой связи |
| Используется для дебага | Используется для миграций, one-off jobs |
| Не передаёт depends_on | Передаёт depends_on (compose поднимет depends) |
build
docker compose build # все services с build:
docker compose build app # один
docker compose build --no-cache app
# Принудительно без кэша. Долго.
docker compose build --pull
# Перед сборкой делает pull base image.
docker compose build --progress plain
# Без TTY-прогресс-бара, plain output (для CI логов).
config: проверить итоговый compose
docker compose config
# Выводит итоговый эффективный compose-файл, после интерполяции переменных, мерджа override и т.д.
docker compose config --services
# Список сервисов.
Очень полезно для дебага: «у меня где-то переменная не подставилась — посмотрю, что compose реально видит».
kill: жёсткая остановка
docker compose kill app
SIGKILL сразу, без graceful shutdown. Используется когда stop не помогает (процесс игнорирует SIGTERM).
События: events
docker compose events
# Стримит events стенда: start, stop, die, health_status, restart...
Полезно когда у тебя контейнеры рестартятся, но непонятно почему — events покажут sequence.
Жизненный цикл, как в реальном dev
Попробуй сам
# 1. Стенд для эксперимента.
mkdir -p ./compose-cli-demo && cd ./compose-cli-demo
cat > compose.yml <<'YAML'
services:
redis:
image: redis:7-alpine
worker:
image: alpine:3.20
depends_on: [redis]
command: sh -c 'while true; do echo "tick $(date)"; sleep 3; done'
YAML
# 2. Запусти в фоне.
docker compose up -d
# 3. Логи.
docker compose logs --tail 5 worker
docker compose logs -f worker &
sleep 6
kill %1
# 4. Состояние.
docker compose ps
# 5. Exec в worker.
docker compose exec worker date
# 6. Run — новый контейнер.
docker compose run --rm worker echo "one-off task"
# 7. Конфиг.
docker compose config --services
# redis
# worker
# 8. Stop без удаления.
docker compose stop
docker compose ps
# Контейнеры в статусе Exited.
docker compose start
docker compose ps
# Снова Up.
# 9. Полный cleanup.
docker compose down
cd ..
rm -rf compose-cli-demo
Все команды compose работают только в папке с compose-файлом (или с -f путь/к/compose.yml). Если ты в другой папке — compose не найдёт проект. Это базовая привычка: cd <project> && docker compose ....
В следующем уроке — depends_on, healthcheck, condition: что значит «постгрес готов» и как избежать race condition.