Главная/Containers и lifecycle/Урок

4.1. Состояния и переходы

Цели

После этого материала вы сможете:

  • назвать все состояния container и переходы между ними;
  • объяснить разницу между run, create + start и когда нужен каждый вариант;
  • объяснить, что именно делает stop, kill, pause, restart, rm;
  • прочитать состояние container из docker ps и docker inspect;
  • объяснить, что удаляется при docker rm, а что остаётся;
  • дождаться завершения container и получить его exit code программно;
  • объяснить состояние dead и что с ним делать.

Предварительные знания

Ключевые термины

ТерминОбъяснение
createdContainer создан, но процесс не запущен
runningГлавный процесс выполняется
pausedПроцессы container заморожены через cgroup freezer
restartingContainer перезапускается по restart policy
exitedГлавный процесс завершился; метаданные и writable layer сохранены
deadContainer не удалось удалить полностью; аномальное состояние
grace periodВремя между SIGTERM и SIGKILL при остановке

Теория

Граф состояний

text
                    docker create
                          │
                          ▼
                    ┌───────────┐
                    │  created  │
                    └─────┬─────┘
                          │ docker start
      docker run  ────────┤
      (create+start)      ▼
                    ┌───────────┐  docker pause   ┌──────────┐
                    │  running  │ ───────────────►│  paused  │
                    │           │ ◄─────────────── │          │
                    └─────┬─────┘  docker unpause └──────────┘
                          │
          ┌───────────────┼───────────────┐
          │               │               │
   процесс завершился  docker stop   docker kill
   сам                 (SIGTERM,     (SIGKILL
          │             затем         сразу)
          │             SIGKILL)          │
          └───────────────┼───────────────┘
                          ▼
                    ┌───────────┐
                    │  exited   │◄──── restart policy ────┐
                    └─────┬─────┘                          │
                          │ docker start              ┌────┴───────┐
                          └──────────────────────────►│ restarting │
                          │                           └────────────┘
                          │ docker rm
                          ▼
                    ┌───────────┐
                    │ удалён    │
                    └───────────┘

   ┌──────┐
   │ dead │ ← аномальное состояние: удаление не завершилось
   └──────┘

Container живёт, пока живёт процесс

Правило, введённое в уроке 2.1, определяет весь граф выше:

Container находится в состоянии running ровно столько, сколько выполняется его главный процесс.

Отсюда следуют ответы на большинство вопросов новичков:

ВопросОтвет
Почему container «сразу упал»?Его команда выполнилась и завершилась. Это не падение
Как «выключить» container?Никак. Завершается процесс — завершается container
Почему docker start на exited container работает?Запускается новый экземпляр процесса в том же окружении
Почему после docker stop container виден в docker ps -a?Метаданные и writable layer сохраняются до docker rm

run — это две операции

bash
docker run alpine echo hi

эквивалентно

bash
docker create alpine echo hi   # выведет ID
docker start -a <id>           # -a = attach к потокам

Разделение полезно в трёх случаях:

1. Нужно настроить container до запуска. Например, скопировать файлы в его файловую систему через docker cp — это работает и для created.

2. Нужен предсказуемый ID заранее. create возвращает ID, который можно использовать в скриптах до запуска.

3. Требуется точный контроль момента старта. Создать все containers, затем запустить одновременно.

В остальных случаях run удобнее.

stop против kill

Различие принципиально и постоянно проявляется в эксплуатации.

docker stopdocker kill
Первый сигналSIGTERM (или заданный в STOPSIGNAL)SIGKILL (или заданный --signal)
ОжиданиеGrace period, по умолчанию 10 секундНет
Второй сигналSIGKILL, если процесс не завершился
Приложение может подготовитьсяДаНет
Exit code при штатной обработкеТот, что вернуло приложение (часто 0)137
Типичное применениеШтатная остановкаАварийное завершение зависшего процесса

SIGKILL невозможно перехватить или проигнорировать — ядро завершает процесс немедленно. Незаписанные данные теряются, соединения обрываются, файлы остаются заблокированными.

Отсюда правило: docker kill — инструмент последней инстанции, а не быстрая замена stop.

Подробно обработка сигналов разбирается в уроке 4.4.

pause — это не остановка

docker pause замораживает все процессы container через cgroup freezer. Процессы остаются в памяти, файловые дескрипторы и сетевые соединения сохраняются, но не выполняется ни одна инструкция.

pausestop
ПроцессыЗаморожены в памятиЗавершены
ПамятьЗанятаОсвобождена
СоединенияСохранены, но не отвечаютРазорваны
Сигнал приложениюНикакогоSIGTERM
Восстановлениеunpause, мгновенноstart, процесс запускается заново

Практическое применение узкое: временно освободить CPU, снять срез состояния, отладка гонок. Для остановки сервиса pause не подходит — клиенты будут ждать ответа до таймаута вместо быстрого отказа.

Что удаляет docker rm

ОбъектУдаляется?
Метаданные containerДа
Writable layerДа — все изменения файловой системы теряются
Логи containerДа
Anonymous volumesТолько с флагом -v
Named volumesНет — никогда
ОбразНет
СетиНет

Строка про named volumes — причина, по которой данные переживают пересоздание container. Это основа работы с состоянием в разделе 07.

Строка про writable layer — причина, по которой изменения, сделанные через docker exec, исчезают. Их нельзя «сохранить в образ» иначе, чем через docker commit, который для рабочих процессов не рекомендуется (раздел 19).

Состояние dead

Редкое аномальное состояние: Docker начал удалять container, но не смог завершить операцию — обычно из-за проблем с файловой системой или занятых точек монтирования.

Container в состоянии dead не запускается и не работает. Действия:

bash
docker rm -f <container>

Если не помогает — проблема на уровне монтирований; смотрите логи daemon (урок 1.3).


Внутренний механизм

Что происходит при docker create

  1. Daemon разрешает имя образа и проверяет его наличие.
  2. Создаётся writable layer поверх слоёв образа.
  3. Формируется конфигурация container: команда, переменные, монтирования, сеть, лимиты.
  4. Container получает ID и имя; запись сохраняется в /var/lib/docker/containers/<id>/.
  5. Процесс не запускается. Namespaces и cgroup ещё не созданы.

Состояние created — это подготовленное окружение без процесса.

Что происходит при docker start

  1. Daemon через containerd создаёт задачу.
  2. Готовится OCI bundle (урок 2.6).
  3. Порождается shim, вызывается runc.
  4. Создаются namespaces и cgroup, применяются capabilities и seccomp.
  5. Выполняется execve() — процесс становится приложением.

Как отслеживается завершение

Shim является родителем процесса container. При завершении процесса shim вызывает wait(), получает статус и сообщает containerd, тот — daemon.

Daemon записывает в состояние container:

  • ExitCode — код возврата;
  • FinishedAt — время завершения;
  • OOMKilled — был ли процесс убит по нехватке памяти;
  • Error — сообщение об ошибке, если была.

Именно эти поля читает docker inspect и показывает docker ps.


Команды и примеры

Прохождение всех состояний

bash
# created
CID="$(docker create --name lc-demo alpine sleep 300)"
echo "ID: $CID"
docker ps -a --filter name=lc-demo --format 'table {{.Names}}\t{{.Status}}'
text
ID: 3f2a1b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c9d0e1f2a
NAMES     STATUS
lc-demo   Created

Процесса ещё нет — убедимся:

bash
docker inspect lc-demo --format 'PID: {{.State.Pid}}  Status: {{.State.Status}}'
text
PID: 0  Status: created

PID: 0 означает, что процесса не существует.

bash
# running
docker start lc-demo
docker inspect lc-demo --format 'PID: {{.State.Pid}}  Status: {{.State.Status}}'
text
lc-demo
PID: 190412  Status: running
bash
# paused
docker pause lc-demo
docker ps --filter name=lc-demo --format 'table {{.Names}}\t{{.Status}}'
text
NAMES     STATUS
lc-demo   Up 12 seconds (Paused)

Процесс всё ещё существует, но заморожен:

bash
docker inspect lc-demo --format 'PID: {{.State.Pid}}  Paused: {{.State.Paused}}'
ps -o pid,stat,comm -p "$(docker inspect lc-demo --format '{{.State.Pid}}')"
text
PID: 190412  Paused: true
    PID STAT COMMAND
 190412 Sl   sleep
bash
# unpause и остановка
docker unpause lc-demo
docker stop lc-demo
docker ps -a --filter name=lc-demo --format 'table {{.Names}}\t{{.Status}}'
text
lc-demo
lc-demo
NAMES     STATUS
lc-demo   Exited (137) 2 seconds ago

Exit code 137 — процесс sleep не обрабатывает SIGTERM, поэтому после grace period получил SIGKILL. Это разбирается в уроке 4.4.

bash
# повторный запуск того же container
docker start lc-demo
docker inspect lc-demo --format 'новый PID: {{.State.Pid}}'
docker stop lc-demo > /dev/null

# удаление
docker rm lc-demo
docker ps -a --filter name=lc-demo | tail -1
text
lc-demo
новый PID: 190587
lc-demo

Обратите внимание: после docker start PID другой. Это новый процесс в том же окружении, а не возобновление прежнего.

Полное состояние через inspect

bash
docker run -d --name state-demo alpine sh -c 'sleep 5; exit 42' > /dev/null
sleep 7
docker inspect state-demo --format '{{json .State}}' | python3 -m json.tool
json
{
    "Status": "exited",
    "Running": false,
    "Paused": false,
    "Restarting": false,
    "OOMKilled": false,
    "Dead": false,
    "Pid": 0,
    "ExitCode": 42,
    "Error": "",
    "StartedAt": "2026-07-29T17:20:11.482Z",
    "FinishedAt": "2026-07-29T17:20:16.601Z"
}

Полезные поля:

ПолеЗначение
StatusТекущее состояние строкой
ExitCodeКод возврата главного процесса
OOMKilledОтличает нехватку памяти от прочих причин SIGKILL
ErrorСообщение, если container не смог стартовать
StartedAt, FinishedAtВремя работы; разница даёт длительность

Извлечение конкретных полей:

bash
docker inspect state-demo \
    --format 'код: {{.State.ExitCode}}  OOM: {{.State.OOMKilled}}  работал: {{.State.StartedAt}} → {{.State.FinishedAt}}'
bash
docker rm state-demo > /dev/null

Ожидание завершения

bash
docker run -d --name wait-demo alpine sh -c 'sleep 3; exit 7' > /dev/null
echo "ждём завершения..."
CODE="$(docker wait wait-demo)"
echo "exit code: $CODE"
docker rm wait-demo > /dev/null
text
ждём завершения...
exit code: 7

docker wait блокируется до завершения container и выводит его код возврата. Это правильный способ дождаться разовой задачи в скрипте — вместо цикла с sleep и проверкой docker ps.

Практическое применение — миграции базы данных, которые должны отработать до старта приложения (раздел 09).

stop против kill на практике

Подготовим приложение, которое обрабатывает SIGTERM:

bash
mkdir -p /tmp/lifecycle && cd /tmp/lifecycle

cat > graceful.py <<'PY'
import signal
import sys
import time

running = True


def handle_term(signum, frame):
    global running
    print(f"получен сигнал {signum}, завершаюсь корректно", flush=True)
    running = False


signal.signal(signal.SIGTERM, handle_term)

print("работаю", flush=True)
while running:
    time.sleep(0.2)

print("завершил работу штатно", flush=True)
sys.exit(0)
PY

docker run -d --name grace \
    -v "$PWD/graceful.py:/app/graceful.py:ro" \
    python:3.13-slim python -u /app/graceful.py > /dev/null
sleep 1

Теперь stop:

bash
time docker stop grace
docker logs grace
docker inspect grace --format 'exit code: {{.State.ExitCode}}'
text
grace

real	0m0.312s
работаю
получен сигнал 15, завершаюсь корректно
завершил работу штатно
exit code: 0

Приложение получило SIGTERM (номер 15), завершилось само, exit code 0, заняло треть секунды.

Теперь то же самое через kill:

bash
docker rm grace > /dev/null
docker run -d --name grace \
    -v "$PWD/graceful.py:/app/graceful.py:ro" \
    python:3.13-slim python -u /app/graceful.py > /dev/null
sleep 1

docker kill grace
docker logs grace
docker inspect grace --format 'exit code: {{.State.ExitCode}}'
text
grace
работаю
exit code: 137

Приложение не успело ничего — SIGKILL не перехватывается. Строки о корректном завершении в логах нет, exit code 137.

bash
docker rm grace > /dev/null

Разница видна невооружённым глазом: в первом случае приложение закрыло бы соединения с базой, дописало буферы, сняло блокировки. Во втором — нет.

Grace period

bash
cat > stubborn.py <<'PY'
import signal
import time

# Намеренно игнорируем SIGTERM — так ведёт себя приложение
# без обработчика, если оно является PID 1.
signal.signal(signal.SIGTERM, signal.SIG_IGN)

print("игнорирую SIGTERM", flush=True)
while True:
    time.sleep(0.5)
PY

docker run -d --name stubborn \
    -v "$PWD/stubborn.py:/app/stubborn.py:ro" \
    python:3.13-slim python -u /app/stubborn.py > /dev/null
sleep 1

echo "--- stop с таймаутом по умолчанию (10 с) ---"
time docker stop stubborn
docker inspect stubborn --format 'exit code: {{.State.ExitCode}}'
docker rm stubborn > /dev/null
text
--- stop с таймаутом по умолчанию (10 с) ---
stubborn

real	0m10.284s
exit code: 137

Десять секунд ожидания, затем SIGKILL. Это и есть тот случай, когда «docker stop почему-то долгий» — приложение не реагирует на SIGTERM.

Таймаут настраивается:

bash
docker run -d --name stubborn2 \
    -v "$PWD/stubborn.py:/app/stubborn.py:ro" \
    python:3.13-slim python -u /app/stubborn.py > /dev/null
sleep 1
time docker stop --timeout 2 stubborn2
docker rm stubborn2 > /dev/null
text
real	0m2.201s

Уменьшение таймаута не решает проблему, а маскирует её. Правильное решение — научить приложение обрабатывать SIGTERM. Для Python это разбирается в разделе 06.

Значение по умолчанию для всех container можно задать в daemon.json параметром shutdown-timeout, а для конкретного — флагом --stop-timeout при создании.

Что теряется при rm

bash
docker run -d --name data-demo alpine sleep 300 > /dev/null
docker exec data-demo sh -c 'echo "важные данные" > /data.txt'
docker exec data-demo cat /data.txt

docker stop data-demo > /dev/null
docker start data-demo > /dev/null
echo "--- после stop/start ---"
docker exec data-demo cat /data.txt
text
важные данные
--- после stop/start ---
важные данные

Перезапуск данные сохраняет: writable layer остался.

bash
docker rm -f data-demo > /dev/null
docker run -d --name data-demo alpine sleep 300 > /dev/null
echo "--- после rm и повторного run ---"
docker exec data-demo cat /data.txt 2>&1 | tail -1
docker rm -f data-demo > /dev/null
text
--- после rm и повторного run ---
cat: can't open '/data.txt': No such file or directory

Данные исчезли: rm удалил writable layer. Новый container создан с чистым слоем поверх того же образа.

Массовые операции

bash
# создать несколько
for i in 1 2 3; do docker run -d --name bulk-$i alpine sleep 300 > /dev/null; done

# остановить все по фильтру имени
docker stop $(docker ps -q --filter 'name=bulk-')

# посмотреть
docker ps -a --filter 'name=bulk-' --format 'table {{.Names}}\t{{.Status}}'

# удалить остановленные
docker rm $(docker ps -aq --filter 'name=bulk-' --filter 'status=exited')

Полезные фильтры docker ps:

ФильтрОтбирает
status=running / exited / paused / createdПо состоянию
name=<подстрока>По имени
ancestor=<image>Созданные из образа
exited=<код>Завершившиеся с конкретным кодом
label=<key>=<value>По метке
before=<container> / since=<container>По времени создания

Пример практической пользы — найти всё, что упало с ошибкой:

bash
docker ps -a --filter 'status=exited' \
    --format '{{.Names}}\t{{.Status}}' | grep -v 'Exited (0)'

Автоудаление

bash
docker run --rm alpine echo "разовая задача"
docker ps -a --filter 'ancestor=alpine' --format '{{.Names}}' | head -3

Флаг --rm удаляет container сразу после завершения. Правило: для разовых команд всегда --rm, иначе накапливаются сотни записей.

Ограничение: --rm несовместим с -d в сочетании с restart policy — Docker откажет, потому что автоудаление и автоперезапуск противоречат друг другу.

Уборка

bash
docker rm -f $(docker ps -aq --filter 'name=bulk-') 2>/dev/null || true
cd /tmp && rm -rf /tmp/lifecycle

Практическое упражнение

Задание. Напишите скрипт lifecycle-tour.sh, который проводит container через все состояния и фиксирует наблюдения.

Скрипт должен для каждого шага выводить: выполненную команду, состояние из docker ps, значение .State.Status, PID процесса.

Последовательность: createstartpauseunpausestopstartrm.

Дополнительно ответьте письменно:

  1. Почему PID после docker stop и повторного docker start различается?
  2. Почему в состоянии paused PID сохраняется?
  3. Что произойдёт с файлом, созданным в container, после stop/start и после rm?

Подсказки

Подсказка 1

docker inspect <name> --format '{{.State.Status}}' даёт состояние одной строкой, {{.State.Pid}} — PID (0, если процесса нет).

Подсказка 2

Чтобы скрипт не оставлял мусора при прерывании, используйте trap ... EXIT.

Решение

Сначала выполните задание самостоятельно.

Показать решение
bash
#!/usr/bin/env bash
# lifecycle-tour.sh — прохождение container через все состояния.
set -euo pipefail

NAME="tour-$$"
trap 'docker rm -f "$NAME" >/dev/null 2>&1 || true' EXIT

step() {
    local cmd="$1"
    printf '\n── %s ──\n' "$cmd"
    local status pid ps_status
    status="$(docker inspect "$NAME" --format '{{.State.Status}}' 2>/dev/null || echo 'нет container')"
    pid="$(docker inspect "$NAME" --format '{{.State.Pid}}' 2>/dev/null || echo '-')"
    ps_status="$(docker ps -a --filter "name=^${NAME}\$" --format '{{.Status}}' 2>/dev/null)"
    printf '  .State.Status : %s\n' "$status"
    printf '  .State.Pid    : %s\n' "$pid"
    printf '  docker ps     : %s\n' "${ps_status:-—}"
}

echo "=== Жизненный цикл container ==="

docker create --name "$NAME" alpine sh -c 'echo start > /marker.txt; sleep 600' > /dev/null
step "docker create"

docker start "$NAME" > /dev/null
sleep 1
step "docker start"
PID_FIRST="$(docker inspect "$NAME" --format '{{.State.Pid}}')"

docker exec "$NAME" cat /marker.txt > /dev/null
echo "  файл /marker.txt создан внутри container"

docker pause "$NAME" > /dev/null
step "docker pause"

docker unpause "$NAME" > /dev/null
step "docker unpause"

docker stop "$NAME" > /dev/null
step "docker stop"

docker start "$NAME" > /dev/null
sleep 1
step "docker start (повторно)"
PID_SECOND="$(docker inspect "$NAME" --format '{{.State.Pid}}')"

echo
echo "  файл после stop/start:"
docker exec "$NAME" cat /marker.txt | sed 's/^/    /'

docker stop "$NAME" > /dev/null
docker rm "$NAME" > /dev/null
step "docker rm"

echo
echo "=== Наблюдения ==="
printf '  PID при первом запуске:   %s\n' "$PID_FIRST"
printf '  PID при повторном запуске: %s\n' "$PID_SECOND"
[ "$PID_FIRST" != "$PID_SECOND" ] && echo "  → PID различаются: это новый процесс, а не возобновление прежнего"

echo
echo "  Проверка потери данных после rm:"
docker run --rm --name "${NAME}-check" alpine cat /marker.txt 2>&1 \
    | sed 's/^/    /' | tail -1

Ожидаемый вывод:

text
=== Жизненный цикл container ===

── docker create ──
  .State.Status : created
  .State.Pid    : 0
  docker ps     : Created

── docker start ──
  .State.Status : running
  .State.Pid    : 191204
  docker ps     : Up 1 second
  файл /marker.txt создан внутри container

── docker pause ──
  .State.Status : paused
  .State.Pid    : 191204
  docker ps     : Up 2 seconds (Paused)

── docker unpause ──
  .State.Status : running
  .State.Pid    : 191204
  docker ps     : Up 3 seconds

── docker stop ──
  .State.Status : exited
  .State.Pid    : 0
  docker ps     : Exited (137) 1 second ago

── docker start (повторно) ──
  .State.Status : running
  .State.Pid    : 191388
  docker ps     : Up 1 second

  файл после stop/start:
    start

── docker rm ──
  .State.Status : нет container
  .State.Pid    : -
  docker ps     : —

=== Наблюдения ===
  PID при первом запуске:   191204
  PID при повторном запуске: 191388
  → PID различаются: это новый процесс, а не возобновление прежнего

  Проверка потери данных после rm:
    cat: can't open '/marker.txt': No such file or directory

Ответы на вопросы задания.

1. Почему PID различается после stop/start. docker stop завершает процесс — он перестаёт существовать. docker start создаёт новый процесс: заново формируются namespaces, cgroup, выполняется execve(). Ядро назначает новый PID. Сохраняется только окружение container: writable layer, конфигурация, имя, сетевые настройки.

Это принципиально отличается от pause/unpause, где процесс не завершается.

2. Почему в paused PID сохраняется. docker pause использует cgroup freezer: процессы переводятся в состояние, в котором ядро их не планирует к выполнению. Они остаются в памяти со всеми открытыми дескрипторами и соединениями. Ничего не завершается, поэтому PID тот же.

Проверить можно с host — процесс виден в ps:

bash
ps -o pid,stat,comm -p <pid>

3. Судьба файла. После stop/start файл на месте: writable layer container не удаляется при остановке. После rm файл исчез вместе со слоем — новый container создаётся с чистым writable layer поверх того же образа.

Отсюда практическое правило: всё, что должно пережить пересоздание container, хранится в volume, а не в его файловой системе (раздел 07).

Проверка результата

bash
docker create --name check alpine sleep 60 > /dev/null
docker inspect check --format 'Status: {{.State.Status}}  PID: {{.State.Pid}}'
docker start check > /dev/null
docker inspect check --format 'Status: {{.State.Status}}  PID: {{.State.Pid}}'
docker rm -f check > /dev/null

Первая строка должна показать created и PID: 0, вторая — running и ненулевой PID.

Типичные ошибки

ОшибкаПричинаИсправление
«Container сразу упал» для завершившейся командыОжидание, что container работает постоянноContainer живёт, пока живёт процесс. Проверить exit code
docker kill вместо docker stopКажется быстрееSIGKILL не даёт приложению завершиться корректно. Данные теряются
docker stop --timeout 1 для ускоренияМаскирует отсутствие обработчика сигналаНаучить приложение обрабатывать SIGTERM
Ожидание, что pause освободит памятьСлово «пауза» вводит в заблуждениеПроцессы остаются в памяти. Для освобождения нужен stop
Хранение данных в writable layerРаботает до rmИспользовать volumes
Изменения через exec теряются после пересозданияWritable layer удаляется вместе с containerИзменения вносить в образ или в volume
Накопление сотен Exited containersЗапуски без --rmДля разовых команд использовать --rm
Цикл с sleep для ожидания завершенияИзобретение того, что уже естьdocker wait блокируется и возвращает exit code

Контрольные вопросы

На понимание:

  1. Чем состояние created отличается от exited с точки зрения существования процесса?
  2. Почему после docker start остановленного container PID другой?
  3. Что сохраняется между stop и start, а что — нет?
  4. Почему pause не подходит для остановки сервиса?
  5. Что именно удаляет docker rm и что остаётся?

На применение:

  1. Как дождаться завершения разовой задачи и получить её exit code в скрипте?
  2. Как найти все containers, завершившиеся с ненулевым кодом?
  3. Как создать container, но не запускать его, и зачем это может понадобиться?

На диагностику:

  1. docker stop каждый раз занимает ровно 10 секунд. В чём причина и как проверить гипотезу?
  2. После docker rm и повторного docker run из того же образа пропали настройки приложения, сделанные через docker exec. Объясните.

Краткое резюме

  1. Container находится в running ровно столько, сколько выполняется его главный процесс.
  2. Состояния: created, running, paused, restarting, exited, dead.
  3. docker run = create + start; разделение нужно для настройки до запуска.
  4. docker stop посылает SIGTERM, ждёт grace period (10 с), затем SIGKILL.
  5. docker kill посылает SIGKILL сразу — приложение не может подготовиться.
  6. docker pause замораживает процессы через cgroup freezer; память не освобождается.
  7. docker start создаёт новый процесс с новым PID в прежнем окружении.
  8. docker rm удаляет writable layer и логи; named volumes не трогает.
  9. docker wait блокируется до завершения и возвращает exit code.
  10. Долгий docker stop почти всегда означает, что приложение не обрабатывает SIGTERM.

Официальные источники

ИсточникСсылкаЧто подтверждает
docker create referencehttps://docs.docker.com/reference/cli/docker/container/create/Создание container без запуска
docker start referencehttps://docs.docker.com/reference/cli/docker/container/start/Запуск существующего container, флаг -a
docker stop referencehttps://docs.docker.com/reference/cli/docker/container/stop/SIGTERM, grace period, последующий SIGKILL, флаг --timeout
docker kill referencehttps://docs.docker.com/reference/cli/docker/container/kill/Немедленный SIGKILL, флаг --signal
docker pause referencehttps://docs.docker.com/reference/cli/docker/container/pause/Использование cgroup freezer, сохранение процессов в памяти
docker rm referencehttps://docs.docker.com/reference/cli/docker/container/rm/Что удаляется, флаг -v для anonymous volumes
docker wait referencehttps://docs.docker.com/reference/cli/docker/container/wait/Блокировка до завершения и вывод exit code
docker ps referencehttps://docs.docker.com/reference/cli/docker/container/ls/Фильтры status, exited, ancestor, формат вывода
docker inspect referencehttps://docs.docker.com/reference/cli/docker/inspect/Поля .State: Status, ExitCode, OOMKilled, StartedAt

Навигация

Вернуться к разделу
Следующий материал → Режимы запуска
Главное оглавление

Markdown на GitHub ↗