Фоновый и интерактивный режим запуска контейнеров

Режим меняет подключение терминала, но не природу контейнера: он живёт, пока жив PID 1.

Detached

docker run -d --name demo-app demo-app:1.0
docker logs -f demo-app
docker stop demo-app

-d возвращает управление shell и оставляет контейнер работать. Для сервисов это обычный режим. Сигнал остановки получает PID 1; приложение должно корректно завершать работу за отведённый timeout.

Interactive

docker run --rm -it eclipse-temurin:21-jdk jshell
docker exec -it demo-app sh
  • -i держит stdin открытым.
  • -t создаёт pseudo-TTY.
  • run создаёт новый контейнер.
  • exec запускает дополнительный процесс в уже работающем.

Для non-interactive pipeline TTY может мешать:

docker exec demo-app printenv APP_MODE

Attach и сигналы

docker attach подключается к основному процессу. Нажатие Ctrl+C может передать сигнал приложению и остановить контейнер. Для диагностики обычно безопаснее logs или exec.

Если shell-скрипт стал PID 1 и не использует exec для запуска Java, сигналы могут не дойти до JVM:

#!/bin/sh
exec java -jar app.jar

Типичные сбои

  • Запустить сервер без -d, закрыть терминал и принять остановку за падение.
  • Использовать -it в CI без TTY.
  • Подключиться через attach и случайно остановить основной процесс.
  • Запустить daemon внутри контейнера, а PID 1 завершить — контейнер всё равно остановится.
  • Ожидать bash в image, где есть только sh или нет shell вообще.

Вопросы для собеседования

Что делает -d? Отключает терминал клиента после запуска; процесс остаётся основным процессом контейнера.

Чем exec отличается от run? exec добавляет процесс в существующий container, run создаёт новый.

Зачем -t? Для псевдотерминала, удобного человеку; машинам он часто не нужен.

Почему важен PID 1? Его завершение останавливает контейнер, а обработка сигналов определяет graceful shutdown.

См. Docker, Структура команды docker run.