4.2. Режимы запуска
Цели
После этого материала вы сможете:
- осознанно выбирать между foreground и detached режимом;
- объяснить, что делает
-iи что делает-tпо отдельности; - предсказать поведение любой комбинации
-i,-t,-d; - объяснить, почему
Ctrl+Cиногда останавливает container, а иногда нет; - работать со стандартными потоками container: передавать данные на stdin, разделять stdout и stderr;
- объяснить, почему
docker runв скрипте ведёт себя иначе, чем в терминале; - управлять именами containers и понимать, откуда берутся автогенерируемые.
Предварительные знания
- 4.1. Состояния и переходы;
- понимание stdin, stdout, stderr и перенаправления в shell;
- представление о том, что такое терминал.
Ключевые термины
| Термин | Объяснение |
|---|---|
foreground | Режим, в котором CLI остаётся подключённым к потокам container и ждёт его завершения |
detached | Фоновый режим: CLI печатает ID container и завершается |
stdin | Стандартный поток ввода, дескриптор 0 |
stdout | Стандартный поток вывода, дескриптор 1 |
stderr | Стандартный поток ошибок, дескриптор 2 |
TTY | Терминальное устройство. Даёт эхо ввода, обработку Ctrl+C, размер окна, цвета |
pseudo-TTY | Программная эмуляция терминала — то, что создаёт флаг -t |
attach | Подключение к потокам уже работающего container |
Теория
Два режима запуска
docker run alpine sleep 5 # foreground: терминал занят 5 секунд
docker run -d alpine sleep 5 # detached: сразу вернулся ID
| Foreground (по умолчанию) | Detached (-d) | |
|---|---|---|
| CLI ждёт завершения | Да | Нет |
| Потоки container | Подключены к терминалу | Не подключены |
| Что печатается | Вывод приложения | ID container |
| Exit code команды | Exit code container | 0, если запуск удался |
| Как посмотреть вывод | Он на экране | docker logs |
| Типичное применение | Разовые команды, отладка, CI | Сервисы, долгоживущие процессы |
Важная деталь: в detached режиме exit code docker run не имеет отношения к приложению. Команда вернёт 0, даже если приложение упадёт через секунду. Проверять нужно отдельно — через docker wait или docker inspect.
-i и -t — два независимых флага
Их почти всегда пишут вместе как -it, из-за чего кажется, что это один флаг. Это не так.
-i (--interactive) — держать stdin открытым. Без него stdin container сразу закрывается: программа, читающая ввод, получает конец файла.
-t (--tty) — выделить pseudo-TTY. Это меняет поведение программ: появляется эхо символов, работают управляющие последовательности, программы включают цветной вывод и интерактивный режим.
Таблица всех комбинаций:
| Флаги | stdin | TTY | Что получится |
|---|---|---|---|
| нет | закрыт | нет | Пакетный запуск. Оболочка сразу завершится |
-i | открыт | нет | Можно подавать данные на вход. Нет эха, нет промпта |
-t | закрыт | есть | TTY есть, но ввести ничего нельзя. Почти всегда ошибка |
-it | открыт | есть | Полноценная интерактивная сессия |
Строка -t без -i объясняет частое недоумение: терминал вроде выделен, промпт появился, а на нажатия клавиш реакции нет — потому что stdin закрыт.
Когда -t вреден
Флаг -t — не «сделать красивее». Он меняет структуру потоков.
При -t stdout и stderr объединяются. Терминал — одно устройство, у него нет двух отдельных каналов. Поэтому:
docker run -t alpine sh -c 'echo OUT; echo ERR >&2' 2>/dev/null
выведет обе строки: перенаправление stderr не сработало, потому что stderr и не было — всё шло через TTY.
Практические следствия:
- в скриптах и CI флаг
-tиспользовать не нужно — он ломает разделение потоков и добавляет управляющие символы в вывод; - при парсинге вывода
-tдаёт\r\nвместо\n, из-за чего сравнение строк неожиданно не срабатывает; - Docker откажется выделять TTY, если стандартный ввод не является терминалом, — отсюда ошибка
the input device is not a TTYв CI.
Правило: -t только для интерактивной работы человека. Для всего остального — без него.
Что делает Ctrl+C
Поведение зависит от режима, и это регулярно путают.
| Режим | Что происходит при Ctrl+C |
|---|---|
docker run (без -t) | CLI получает SIGINT и отключается. Container продолжает работать |
docker run -t | SIGINT передаётся процессу в container через TTY. Обычно container останавливается |
docker run --sig-proxy=false | Сигнал не передаётся, CLI отключается |
docker attach | По умолчанию сигнал передаётся; отключиться без остановки — Ctrl+P, Ctrl+Q |
Первая строка — источник ситуации «нажал Ctrl+C, а он всё работает». Проверяется через docker ps.
Стандартные потоки container
Процесс в container имеет те же три потока, что и обычный процесс. Разница в том, куда они ведут.
foreground без -t:
stdout ──► daemon ──► CLI ──► ваш stdout
stderr ──► daemon ──► CLI ──► ваш stderr (потоки раздельны)
stdin ◄── CLI ◄── ваш stdin (только с -i)
foreground с -t:
stdout ─┐
├─► pseudo-TTY ──► CLI ──► ваш терминал (потоки слиты)
stderr ─┘
detached:
stdout ──┐
├─► logging driver ──► docker logs
stderr ──┘
stdin — закрыт (если не задан -i)
В detached режиме оба потока идут в logging driver. docker logs умеет их разделять, если драйвер сохраняет метку потока — json-file и local сохраняют.
Это объясняет, почему приложение должно писать логи в stdout и stderr, а не в файл: только так их увидит Docker. Тема разбирается в разделе 06.
Имена containers
Если имя не задано, Docker генерирует его из пары «прилагательное_фамилия»: nifty_lamarr, relaxed_hopper. Фамилии — известных учёных и инженеров.
Имя должно быть уникальным среди всех containers, включая остановленные. Отсюда частая ошибка:
docker: Error response from daemon: Conflict. The container name "/api" is
already in use by container "a1b2c3...". You have to remove (or rename)
that container to be able to reuse that name.
Container с таким именем существует, пусть и в состоянии exited. Варианты: удалить его, переименовать через docker rename или использовать --rm при запуске.
Имя работает как альтернатива ID во всех командах и как DNS-имя в user-defined сетях (раздел 08).
Внутренний механизм
Как передаются потоки
В detached режиме процесс container пишет в дескрипторы, которые держит shim (урок 2.6). Shim передаёт данные daemon, тот — в logging driver.
В foreground режиме CLI открывает соединение к эндпоинту API /containers/<id>/attach и получает поток данных. Если TTY не выделен, поток мультиплексирован: каждый фрагмент предваряется восьмибайтовым заголовком с указанием, к какому потоку он относится. CLI разбирает заголовки и раскладывает данные по своим stdout и stderr.
При выделенном TTY мультиплексирования нет — идёт сырой поток байтов. Именно поэтому разделение потоков теряется.
Почему docker run -t в CI падает
Флаг -t требует, чтобы стандартный ввод CLI был терминалом. В CI-раннере stdin обычно перенаправлен из файла или /dev/null, терминала нет.
the input device is not a TTY
Решение — убрать -t. Если команда используется и локально, и в CI, флаг добавляют условно:
[ -t 0 ] && TTY_FLAG="-it" || TTY_FLAG="-i"
docker run --rm $TTY_FLAG alpine sh -c 'echo ok'
Конструкция [ -t 0 ] проверяет, является ли дескриптор 0 терминалом.
Команды и примеры
Foreground против detached
echo "--- foreground: терминал занят ---"
time docker run --rm alpine sleep 3
echo "--- detached: сразу возвращается ---"
time docker run -d --rm --name bg alpine sleep 3
docker ps --filter name=bg --format '{{.Names}} {{.Status}}'
sleep 4
--- foreground: терминал занят ---
real 0m3.412s
--- detached: сразу возвращается ---
7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a
real 0m0.389s
bg Up Less than a second
Разница в поведении CLI, а не container: в обоих случаях процесс выполнялся три секунды.
Exit code в двух режимах
echo "--- foreground: exit code приложения ---"
docker run --rm alpine sh -c 'exit 42'
echo "код: $?"
echo "--- detached: exit code запуска ---"
docker run -d --name failing alpine sh -c 'exit 42' > /dev/null
echo "код docker run: $?"
sleep 1
echo "код приложения: $(docker inspect failing --format '{{.State.ExitCode}}')"
docker rm failing > /dev/null
--- foreground: exit code приложения ---
код: 42
--- detached: exit code запуска ---
код docker run: 0
код приложения: 42
Вторая строка — ловушка для скриптов. В detached режиме docker run сообщает только об успехе запуска. Приложение может упасть немедленно, и скрипт этого не заметит.
Правильная проверка в скрипте:
docker run -d --name svc alpine sh -c 'sleep 1; exit 3' > /dev/null
CODE="$(docker wait svc)"
echo "фактический код: $CODE"
docker rm svc > /dev/null
фактический код: 3
Комбинации -i и -t
Без флагов:
docker run --rm alpine sh
echo "код: $?"
код: 0
Мгновенно завершилось, ничего не выведя. Оболочка запустилась, обнаружила закрытый stdin, прочитала конец файла и вышла.
Только -i:
echo -e 'echo "команда из stdin"\nid -u\nexit' | docker run --rm -i alpine sh
команда из stdin
0
Оболочка приняла команды со стандартного ввода и выполнила их. Промпта нет — TTY не выделен, оболочка работает в неинтерактивном режиме.
Только -t:
timeout 3 docker run --rm -t alpine sh
echo "завершено по таймауту: $?"
/ #
завершено по таймауту: 124`
Промпт появился — TTY есть. Но ввести ничего нельзя: stdin закрыт. Пришлось прерывать по таймауту. Практического применения у этой комбинации нет.
-it:
docker run --rm -it alpine sh
/ # echo "работает"
работает
/ # exit
Полноценная сессия: промпт, эхо, история, Ctrl+C.
Разделение потоков и влияние -t
echo "=== без -t: потоки раздельны ==="
echo "-- только stdout --"
docker run --rm alpine sh -c 'echo "в stdout"; echo "в stderr" >&2' 2>/dev/null
echo "-- только stderr --"
docker run --rm alpine sh -c 'echo "в stdout"; echo "в stderr" >&2' 1>/dev/null
echo
echo "=== с -t: потоки слиты ==="
echo "-- пытаемся отбросить stderr --"
docker run --rm -t alpine sh -c 'echo "в stdout"; echo "в stderr" >&2' 2>/dev/null
=== без -t: потоки раздельны ===
-- только stdout --
в stdout
-- только stderr --
в stderr
=== с -t: потоки слиты ===
-- пытаемся отбросить stderr --
в stdout
в stderr
В последнем случае обе строки прошли, хотя stderr перенаправлен в /dev/null. Разделения потоков больше нет.
Второе следствие — символы возврата каретки:
echo "=== без -t ==="
docker run --rm alpine echo "строка" | od -c | head -1
echo "=== с -t ==="
docker run --rm -t alpine echo "строка" | od -c | head -1
=== без -t ===
0000000 с т р о к а \n
=== с -t ===
0000000 с т р о к а \r \n
С -t в конце \r\n. Именно из-за этого сравнение вывода со строкой в скрипте не срабатывает:
OUT="$(docker run --rm -t alpine echo ok)"
[ "$OUT" = "ok" ] && echo "совпало" || echo "НЕ совпало (виноват \\r)"
OUT="$(docker run --rm alpine echo ok)"
[ "$OUT" = "ok" ] && echo "совпало" || echo "не совпало"
НЕ совпало (виноват \r)
совпало
Вывод: в скриптах -t не использовать.
Передача данных на stdin
# файл на вход
echo "строка 1
строка 2
строка 3" | docker run --rm -i alpine wc -l
3
Практический пример — обработка данных Python-скриптом без создания файлов:
cat > /tmp/sum.py <<'PY'
import sys
total = 0
for line in sys.stdin:
line = line.strip()
if line:
total += int(line)
print(f"сумма: {total}")
PY
printf '10\n20\n30\n' | docker run --rm -i \
-v /tmp/sum.py:/sum.py:ro \
python:3.13-slim python /sum.py
сумма: 60
Обратите внимание: -i есть, -t нет. Данные приходят из конвейера, терминал не нужен.
Обработка целого файла:
docker run --rm -i alpine sh -c 'grep -c "" ' < /etc/services
Ctrl+C и --sig-proxy
Демонстрация того, что без -t container переживает Ctrl+C. Воспроизведём это программно, послав SIGINT самому CLI:
docker run --name sigtest -d alpine sleep 120 > /dev/null
docker attach --sig-proxy=false sigtest &
ATTACH_PID=$!
sleep 1
kill -INT "$ATTACH_PID" 2>/dev/null
wait "$ATTACH_PID" 2>/dev/null
echo "после прерывания attach:"
docker ps --filter name=sigtest --format '{{.Names}} {{.Status}}'
docker rm -f sigtest > /dev/null
после прерывания attach:
sigtest Up 2 seconds
Container продолжает работать. Флаг --sig-proxy=false явно указывает не передавать сигналы в container — это поведение по умолчанию для docker run без TTY и удобный способ отсоединиться, ничего не сломав.
Для отсоединения от интерактивного attach без остановки container используется последовательность Ctrl+P, Ctrl+Q.
attach против exec
docker run -d --name att alpine sh -c 'while true; do echo "тик $(date +%T)"; sleep 2; done' > /dev/null
sleep 1
echo "--- attach: подключаемся к ОСНОВНОМУ процессу ---"
timeout 5 docker attach --sig-proxy=false att
echo
echo "--- exec: запускаем НОВЫЙ процесс ---"
docker exec att ps -o pid,comm
docker rm -f att > /dev/null
--- attach: подключаемся к ОСНОВНОМУ процессу ---
тик 17:42:11
тик 17:42:13
--- exec: запускаем НОВЫЙ процесс ---
PID COMMAND
1 sh
14 sleep
19 ps
Различие:
attach | exec | |
|---|---|---|
| Что делает | Подключается к потокам PID 1 | Запускает новый процесс |
| Влияние на container | Может остановить его сигналом | Не влияет |
| Видит прошлый вывод | Нет, только новый | Не применимо |
| Безопасность в production | Опасно | Безопасно |
docker attachв production применять не стоит: случайныйCtrl+Cостанавливает сервис. Для входа в работающий container используйтеdocker exec— разбирается в уроке 4.3.
Именование
# автогенерируемое имя
CID="$(docker run -d alpine sleep 60)"
docker inspect "$CID" --format 'сгенерировано: {{.Name}}'
# явное имя
docker run -d --name my-service alpine sleep 60 > /dev/null
docker ps --filter name=my-service --format '{{.Names}}'
сгенерировано: /wizardly_hopper
my-service
Конфликт имён:
# head -1, а не tail: Docker 29 печатает после ошибки пустую строку
# и подсказку «Run 'docker run --help'», и tail забирает именно их
docker run -d --name my-service alpine sleep 60 2>&1 | head -1
docker: Error response from daemon: Conflict. The container name "/my-service"
is already in use by container "b3c4d5e6f7a8...".
Три способа решения:
# 1. удалить старый
docker rm -f my-service > /dev/null
# 2. переименовать
docker run -d --name my-service alpine sleep 60 > /dev/null
docker rename my-service my-service-old
docker run -d --name my-service alpine sleep 60 > /dev/null
docker ps --filter 'name=my-service' --format '{{.Names}}'
# 3. --rm, чтобы имя освобождалось автоматически
docker rm -f my-service my-service-old > /dev/null
docker run --rm --name tmp-task alpine echo "готово"
docker ps -a --filter name=tmp-task --format '{{.Names}}' | wc -l
my-service
my-service-old
готово
0
Уборка:
docker rm -f "$CID" 2>/dev/null || true
rm -f /tmp/sum.py
Флаг --rm и его ограничения
# работает с foreground
docker run --rm alpine echo ok
# работает с detached
docker run -d --rm --name auto alpine sleep 2 > /dev/null
sleep 4
docker ps -a --filter name=auto --format '{{.Names}}' | wc -l
ok
0
Несовместимость с restart policy:
docker run -d --rm --restart=always alpine sleep 10 2>&1 | head -1
docker: conflicting options: cannot specify both --restart and --rm
Сообщение печатает клиент, а не демон: несовместимость флагов видна ещё до обращения к API — потому и нет Error response from daemon.
Логика очевидна: автоудаление и автоперезапуск противоречат друг другу — нельзя перезапустить удалённый container.
Практическое упражнение
Задание. Напишите скрипт run-modes-matrix.sh, который экспериментально заполняет таблицу поведения для всех четырёх комбинаций -i и -t.
Для каждой комбинации проверьте:
- Завершается ли
shнемедленно. - Принимает ли команды со stdin.
- Разделены ли stdout и stderr.
- Есть ли
\rв конце строк вывода.
Дополнительно напишите функцию docker_run_safe, которая подставляет -t только когда stdin является терминалом, — чтобы одна и та же команда работала и локально, и в CI.
Подсказки
Подсказка 1
Проверить разделение потоков: выполнить команду, пишущую в оба потока, с перенаправлением 2>/dev/null. Если строка из stderr всё равно появилась — потоки слиты.
Подсказка 2
Наличие \r определяется так:
out="$(docker run --rm -t alpine echo x | od -c | head -1)"
case "$out" in *'\r'*) echo "есть" ;; *) echo "нет" ;; esac
Подсказка 3
Комбинация -t без -i зависает — оборачивайте её в timeout.
Решение
Сначала выполните задание самостоятельно.
Показать решение
#!/usr/bin/env bash
# run-modes-matrix.sh — экспериментальная матрица поведения -i и -t.
set -uo pipefail
IMG=alpine:3.21
docker pull -q "$IMG" > /dev/null
# 1. Завершается ли sh немедленно
test_immediate_exit() {
local flags="$1"
if timeout 3 docker run --rm $flags "$IMG" sh < /dev/null > /dev/null 2>&1; then
echo "да"
else
[ $? -eq 124 ] && echo "нет (зависает)" || echo "да"
fi
}
# 2. Принимает ли команды со stdin
test_stdin() {
local flags="$1" out
out="$(printf 'echo ПРИНЯТО\n' | timeout 3 docker run --rm $flags "$IMG" sh 2>/dev/null)"
case "$out" in *ПРИНЯТО*) echo "да" ;; *) echo "нет" ;; esac
}
# 3. Разделены ли stdout и stderr
test_streams() {
local flags="$1" out
out="$(timeout 3 docker run --rm $flags "$IMG" \
sh -c 'echo OUT; echo ERR >&2' 2>/dev/null < /dev/null)"
case "$out" in
*ERR*) echo "слиты" ;;
*OUT*) echo "раздельны" ;;
*) echo "?" ;;
esac
}
# 4. Есть ли \r
test_cr() {
local flags="$1" dump
dump="$(timeout 3 docker run --rm $flags "$IMG" echo x < /dev/null 2>/dev/null | od -c | head -1)"
case "$dump" in *'\r'*) echo "да" ;; *) echo "нет" ;; esac
}
printf '%-8s %-16s %-14s %-12s %s\n' ФЛАГИ 'sh выходит' 'stdin' 'потоки' '\\r'
printf '%s\n' "--------------------------------------------------------------------"
for flags in "" "-i" "-t" "-it"; do
label="${flags:-(нет)}"
printf '%-8s %-16s %-14s %-12s %s\n' \
"$label" \
"$(test_immediate_exit "$flags")" \
"$(test_stdin "$flags")" \
"$(test_streams "$flags")" \
"$(test_cr "$flags")"
done
echo
echo "=== Безопасный запуск для скриптов и CI ==="
docker_run_safe() {
local tty_flags="-i"
# -t только если и stdin, и stdout — терминалы
if [ -t 0 ] && [ -t 1 ]; then
tty_flags="-it"
fi
docker run --rm $tty_flags "$@"
}
echo -n " stdin терминал: "; [ -t 0 ] && echo "да" || echo "нет"
echo -n " выбранные флаги: "; { [ -t 0 ] && [ -t 1 ] && echo "-it"; } || echo "-i"
echo -n " результат: "
docker_run_safe "$IMG" echo "команда выполнена"
Запуск:
chmod +x run-modes-matrix.sh
./run-modes-matrix.sh
Ожидаемый вывод при запуске из терминала:
ФЛАГИ sh выходит stdin потоки \r
--------------------------------------------------------------------
(нет) да нет раздельны нет
-i да да раздельны нет
-t нет (зависает) нет слиты да
-it нет (зависает) да слиты да
=== Безопасный запуск для скриптов и CI ===
stdin терминал: да
выбранные флаги: -it
результат: команда выполнена
Разбор таблицы по строкам.
Без флагов. stdin закрыт, TTY нет. Оболочка читает конец файла и завершается — отсюда «container сразу упал» при docker run alpine sh. Потоки раздельны, \r нет. Это правильный режим для пакетного выполнения.
-i. stdin открыт, TTY нет. Команды из конвейера принимаются, промпта нет. Потоки по-прежнему раздельны, \r нет. Это правильный режим для скриптов, которым нужно что-то подать на вход.
-t. TTY есть, stdin закрыт. Оболочка не завершается (терминал считается интерактивным), но ввести ничего нельзя — зависает. Потоки слиты, появился \r. Комбинация без практического применения.
-it. Полноценная интерактивная сессия. Потоки слиты и \r присутствует — но для человека за терминалом это не важно, потому что вывод не парсится.
Ключевой вывод. Слитые потоки и \r — не побочный дефект, а прямое следствие того, что TTY является одним символьным устройством. Поэтому -t уместен ровно там, где по ту сторону человек, и не уместен нигде больше.
Функция docker_run_safe проверяет оба дескриптора. Проверки только [ -t 0 ] недостаточно: при ./script.sh > out.txt стандартный ввод остаётся терминалом, а вывод уже нет, и -t испортит содержимое файла символами \r.
Проверка результата
docker run --rm alpine echo test | od -c | head -1
docker run --rm -t alpine echo test | od -c | head -1
Первая строка должна заканчиваться \n, вторая — \r \n. Если вы понимаете, почему, материал усвоен.
Типичные ошибки
| Ошибка | Причина | Исправление |
|---|---|---|
-it в скриптах и CI | Скопировано из интерактивных примеров | Использовать -i или ничего; -t только для человека |
the input device is not a TTY в CI | Флаг -t при отсутствии терминала | Убрать -t или добавлять его условно через [ -t 0 ] |
| Сравнение вывода не срабатывает | -t добавил \r в конец строк | Убрать -t |
2>/dev/null не отбрасывает stderr | При -t потоки слиты | Убрать -t |
| Скрипт не замечает падения сервиса | В detached режиме docker run возвращает 0 | Проверять через docker wait или docker inspect |
«Нажал Ctrl+C, а он работает» | Без -t сигнал получает CLI, а не container | docker stop |
docker attach в production | Случайный Ctrl+C останавливает сервис | Использовать docker exec |
| Конфликт имён | Имя занято остановленным container | docker rm, docker rename или --rm |
--rm вместе с --restart | Кажется, что флаги независимы | Взаимоисключающие: нельзя перезапустить удалённое |
Контрольные вопросы
На понимание:
- Что делает
-iи что делает-tпо отдельности? - Почему
docker run alpine shзавершается мгновенно? - Почему при
-tперенаправление2>/dev/nullперестаёт работать? - Откуда берётся
\rв выводе и почему это ломает скрипты? - Почему в detached режиме
docker runвозвращает0, даже если приложение упало?
На применение:
- Как передать содержимое файла на стандартный вход процесса в container?
- Как написать команду, работающую и в терминале, и в CI без изменений?
- Как получить реальный exit code приложения, запущенного в detached режиме?
На диагностику:
- Один и тот же скрипт работает локально и падает в CI с
the input device is not a TTY. Причина и исправление? - Проверка
[ "$(docker run --rm -t img cmd)" = "ok" ]не срабатывает, хотя команда выводит именноok. Что происходит?
Краткое резюме
- Foreground подключает потоки container к терминалу и ждёт завершения; detached возвращает ID и завершается.
- В detached режиме exit code
docker runотносится к запуску, а не к приложению. -iоткрывает stdin,-tвыделяет pseudo-TTY — это независимые флаги.- Без флагов оболочка завершается сразу: stdin закрыт.
-tбез-iдаёт терминал без возможности ввода — практического смысла нет.- При
-tstdout и stderr сливаются, а в конец строк добавляется\r. - В скриптах и CI
-tиспользовать нельзя; условная подстановка — через[ -t 0 ] && [ -t 1 ]. - Без
-tCtrl+Cпрерывает CLI, но не container. attachподключается к главному процессу и опасен в production;execзапускает новый процесс.- Имя уникально среди всех containers, включая остановленные;
--rmосвобождает его автоматически.
Официальные источники
| Источник | Ссылка | Что подтверждает |
|---|---|---|
| docker run reference | https://docs.docker.com/reference/cli/docker/container/run/ | Флаги -d, -i, -t, --rm, --name, --sig-proxy, конфликт --rm и --restart |
| docker attach reference | https://docs.docker.com/reference/cli/docker/container/attach/ | Подключение к главному процессу, Ctrl+P Ctrl+Q, --sig-proxy |
| docker rename reference | https://docs.docker.com/reference/cli/docker/container/rename/ | Переименование container |
| docker wait reference | https://docs.docker.com/reference/cli/docker/container/wait/ | Получение exit code для detached container |
| Docker Engine API: attach | https://docs.docker.com/reference/api/engine/version/v1.53/#tag/Container/operation/ContainerAttach | Мультиплексирование потоков и его отсутствие при выделенном TTY |
tty(4) man page | https://man7.org/linux/man-pages/man4/tty.4.html | Поведение терминального устройства, единый канал вывода |
test(1) man page | https://man7.org/linux/man-pages/man1/test.1.html | Проверка -t для файлового дескриптора |
Навигация
← Предыдущий материал
Вернуться к разделу
Следующий материал → Exec, logs, inspect
Главное оглавление