1. Контейнер как процесс
Контейнеры — это способ стандартизации развёртки приложения и отделения его от общей инфраструктуры. Экземпляр приложения запускается в изолированной среде, не влияющей на основную операционную систему.
В отличие от виртуальных машин, контейнер — это не полноценная ОС, а изолированный процесс, использующий ядро хостовой системы. Поэтому контейнеры запускаются за секунды и потребляют значительно меньше ресурсов.
docker run ubuntu без команды мгновенно останавливается: ubuntu-образ не имеет вечно работающего процесса по умолчанию.
2. Основные состояния контейнеров
Контейнер в Docker проходит через несколько чётко определённых состояний:
| Состояние | Описание | Команда перехода |
|---|---|---|
| Created | Контейнер создан из образа, но ещё не запущен. Docker зарезервировал ресурсы, но процесс не стартовал. | docker create |
| Running | Контейнер запущен, его приложение активно выполняется. Контейнер потребляет CPU, память и другие ресурсы хоста. | docker start / docker run |
| Paused | Выполнение процессов контейнера приостановлено (cgroup freezer). Состояние сохраняется, ресурсы памяти заняты, CPU — нет. | docker pause |
| Stopped (Exited) | Контейнер остановлен: процесс завершён, ресурсы хоста освобождены, но файловая система контейнера сохранена на диске. | docker stop / docker kill |
| Deleted | Контейнер удалён. Файловая система контейнера удалена с диска. Данные без volume потеряны навсегда. | docker rm |
3. Docker Entrypoint
Docker Entrypoint — это команда (или исполняемый файл), которая определяет, что будет запущено внутри контейнера при его старте. Entrypoint задаётся в Dockerfile инструкцией ENTRYPOINT.
docker run можно переопределить Entrypoint флагом --entrypoint, а аргументы передать позиционно.
Зачем нужен Entrypoint
- Определение команды запуска: задаёт основной процесс, который удерживает контейнер в состоянии Running
- Настройка инициализации: позволяет выполнить скрипт инициализации перед запуском основного приложения (настройка окружения, миграции БД)
- Повторное использование: один образ — разные задачи через разные аргументы к одному Entrypoint
Проблема мгновенного завершения контейнера
Контейнеры в Docker завершаются сразу, как только завершается их основной процесс (PID 1). Если образ не определяет долгоживущего процесса, контейнер мгновенно переходит в состояние Exited:
# Терминал
# ubuntu не имеет длительного процесса по умолчанию — контейнер сразу завершится
docker run ubuntu
# Проверим — контейнер в состоянии Exited
docker ps -a
Решения для длительной работы контейнера:
# Терминал
# Вариант 1: интерактивный bash
docker run -it ubuntu bash
# Вариант 2: фоновый режим с вечной задачей (tail -f /dev/null читает пустой файл бесконечно)
docker run -d --name my_ubuntu_container ubuntu tail -f /dev/null
# Приложения типа nginx или PostgreSQL сами удерживают процесс — дополнительная команда не нужна
docker run -d --name mynginx nginx
tail -f бесконечно ждёт новых данных из файла, а /dev/null — пустое устройство, которое никогда не пишет данные. Результат: процесс не завершается, контейнер остаётся Running.
4. Команды управления контейнерами
Команды управления изменяют состояние контейнера. Принимают ID или имя контейнера.
| Команда | Что делает |
|---|---|
docker create <image> |
Создаёт контейнер из образа, не запуская его (Created) |
docker run <image> |
Создаёт и сразу запускает контейнер (= create + start) |
docker start <id> |
Запускает остановленный контейнер |
docker stop <id> |
Останавливает контейнер: посылает SIGTERM, ждёт 10 с, затем SIGKILL |
docker kill <id> |
Немедленно завершает контейнер сигналом SIGKILL (без graceful shutdown) |
docker restart <id> |
Перезапускает контейнер (= stop + start) |
docker pause <id> |
Приостанавливает все процессы контейнера (cgroup freezer) |
docker unpause <id> |
Возобновляет приостановленный контейнер |
docker rm <id> |
Удаляет остановленный контейнер |
docker rm -f <id> |
Принудительно удаляет даже работающий контейнер |
5. Инспектирование контейнеров
Команды инспектирования позволяют читать состояние контейнеров, не меняя его.
| Команда | Что показывает |
|---|---|
docker ps |
Список работающих контейнеров: ID, имя, образ, статус, порты, время запуска |
docker ps -a |
Все контейнеры, включая остановленные и завершённые |
docker logs <id> |
Вывод stdout и stderr контейнера (весь журнал) |
docker logs -f <id> |
Логи в режиме follow — новые записи выводятся в реальном времени (как tail -f) |
docker top <id> |
Список процессов внутри контейнера (PID, пользователь, команда) |
docker diff <id> |
Изменения файловой системы контейнера относительно базового образа (A=added, C=changed, D=deleted) |
docker inspect <id> |
Полная информация в JSON: сетевые настройки, монтированные тома, переменные окружения, метаданные образа |
6. Взаимодействие с контейнером
Команды взаимодействия позволяют управлять данными и процессами внутри работающего контейнера.
| Команда | Назначение |
|---|---|
docker exec <id> <cmd> |
Выполняет команду внутри работающего контейнера. С флагами -it — открывает интерактивную оболочку. |
docker cp <src> <dst> |
Копирует файлы между хостом и контейнером в обоих направлениях |
docker attach <id> |
Присоединяется к stdin/stdout/stderr работающего контейнера (PID 1) |
docker export <id> |
Экспортирует файловую систему контейнера в .tar архив (без метаданных образа) |
docker wait <id> |
Блокирует терминал до завершения контейнера, затем выводит код выхода |
docker commit <id> <name> |
Создаёт новый образ на основе текущего состояния контейнера (включая изменения в файловой системе) |
docker exec— запускает новый процесс в пространстве контейнера. Безопаснее, чаще используется.docker attach— подключается к PID 1 (основному процессу). Нажатие Ctrl+C завершит основной процесс и остановит контейнер!
7. Команды управления образами
Помимо контейнеров, Docker предоставляет команды для управления образами на хосте.
| Команда | Назначение |
|---|---|
docker images |
Список всех образов на хосте: ID, репозиторий, тег, размер, дата создания |
docker history <image> |
История слоёв образа: команды, которые выполнялись при сборке каждого слоя |
docker inspect <image> |
Подробная информация об образе в JSON: конфигурация, метки, переменные среды |
docker tag <src> <dst> |
Устанавливает новый тег для образа (псевдоним для пуша в реестр) |
docker commit <container> <image> |
Создаёт образ из текущего состояния контейнера |
docker import <file.tar> |
Импортирует образ из .tar архива (созданного docker export) |
docker rmi <image> |
Удаляет образ с хоста (нельзя удалить, пока есть использующие его контейнеры) |
docker commit из изменённых контейнеров — неплохой учебный инструмент, но в реальных проектах образы всегда собираются через Dockerfile. Это обеспечивает воспроизводимость и версионирование. Подробнее — в уроке 03.