deшка
Урок 5.1

Docker, образ и контейнер: что именно запускается

От двух версий PostgreSQL на ноутбуке до процессов, изоляции и слоёв образа.

Автор приложения передаёт вам main.py. Скрипту нужны Python, несколько библиотек и системный пакет для подключения к базе. Один файл с кодом этого не содержит, поэтому на новой машине возникает вопрос: что именно нужно установить?

Docker позволяет подготовить окружение приложения заранее. Разработчик описывает сборку, получает образ и передаёт его вместе с настройками запуска. На другой машине Docker создаёт из образа контейнер. Внутри уже есть нужные файлы программы, а устанавливать её библиотеки в вашу основную систему не требуется.

Рецепт, образ и экземпляр

Dockerfile — текстовый рецепт сборки. Он задаёт исходную основу, установку зависимостей, копирование кода и команду по умолчанию. Например: взять образ Python, положить в него main.py, при запуске выполнить python main.py.

Образ, image, — результат сборки. Он состоит из слоёв: поверх файлов базового образа добавляются изменения. В основе уже может быть Python, следующим слоем добавлены библиотеки, ещё одним — код приложения. Сам образ неизменяем: новый код означает новую сборку. Не всякая строка Dockerfile добавляет файлы; часть инструкций задаёт метаданные, например команду запуска.

Контейнер — экземпляр, созданный на основе образа. Когда он работает, это один или несколько процессов с отдельным представлением файловой системы и сети. После остановки объект контейнера может остаться в Docker вместе с настройками и изменёнными файлами.

Один образ позволяет создать несколько контейнеров. Их общая основа одинакова, но состояние различается: в одном работает тестовая база, в другом — база другого проекта. Созданный в первом контейнере файл не появляется во втором сам по себе.

Один образ PostgreSQL используется двумя контейнерами; каждому подключён отдельный том данных.

Поверх общих слоёв образа Docker создаёт записываемый слой конкретного контейнера. Сюда попадают изменения файлов, если для соответствующего пути не подключено отдельное хранилище. Остановка контейнера сохраняет этот слой, удаление — уничтожает. Чтобы таблицы базы переживали замену экземпляра, их хранят в отдельном томе. Сохранить образ PostgreSQL и сделать резервную копию таблиц — разные действия.

Кто выполняет команду docker run

У Docker есть клиент и служба. Docker CLI — утилита docker, которой вы вводите команды. Docker Engine управляет образами, контейнерами, сетями и томами. Клиент передаёт запрос Engine; служба создаёт нужные объекты и запускает процесс.

Если при docker run нужного образа ещё нет, Docker обычно сначала пытается скачать его из реестра образов, registry. Docker Hub — один из таких реестров. Он хранит готовые сборки, но не запускает вашу базу вместо вашего компьютера.

Docker Desktop объединяет инструменты для рабочего компьютера: Engine, CLI, Compose, графический интерфейс и необходимое окружение. Это не другое название Docker Hub. Desktop помогает запускать контейнеры, Hub помогает распространять образы.

Компьютер, на котором работает Engine, называют хостом Docker. В наших лабораториях он локальный. При работе с удалённым Engine тома и опубликованные порты создаются на удалённом хосте, хотя команду вы вводите у себя.

Контейнер и виртуальная машина

Виртуальная машина похожа на отдельный компьютер: гипервизор предоставляет ей виртуальное оборудование, а внутри загружается гостевая ОС со своим ядром. Контейнеру для каждого приложения отдельное ядро не требуется. Linux-контейнеры используют ядро своего Linux-хоста совместно.

У контейнеров общее ядро Linux; у каждой виртуальной машины своя гостевая ОС и ядро.

Ядро отделяет представление процессов, файлов и сети, а также позволяет ограничивать память и CPU. Приложения делят ресурсы хоста, а ядро изолирует их окружения.

На Windows и macOS для Linux-контейнеров нужно Linux-окружение. Docker Desktop предоставляет его через виртуализацию; на Windows в roadmap используем WSL 2. Внутри этого окружения контейнеры делят общее ядро. Виртуальные машины и контейнеры могут использоваться вместе и на серверах: они решают задачи на разных уровнях.

Почему контейнер иногда сразу заканчивает работу

В образе может находиться сервер, который постоянно ждёт запросы, или короткий скрипт. Сервер обычно оставляет контейнер работающим. Скрипт прочитал CSV, вывел результат и завершился — контейнер тоже остановился. Код выхода 0 означает успешное завершение программы.

docker start запускает прежний контейнер с его настройками и слоем изменений. docker run создаёт новый экземпляр. Именно поэтому данные, записанные только в прежний контейнер, не появляются в новом из того же образа. Эти два действия стоит различать ещё до первого запуска базы.

Один образ, два независимых экземпляра

Alpine — небольшой Linux-образ с оболочкой и базовыми утилитами. Сначала получим его, затем выполним короткую команду:

docker pull alpine:3.21
docker run --name demo alpine:3.21 echo ready
docker ps -a

pull скачал образ. run создал контейнер demo, запустил в нём echo ready, команда вывела ready и завершилась. В ps -a останется контейнер со статусом Exited (0). Число 0 означает успешное завершение программы.

Для более долгого опыта вместо echo можно запустить sleep 3600: процесс будет ждать час. Параметр -d оставляет его работать в фоне. Команда exec выполняет дополнительное действие в уже работающем контейнере:

docker run -d --name demo-live alpine:3.21 sleep 3600
docker exec demo-live sh -c 'printf hello > /tmp/note.txt'
docker exec demo-live cat /tmp/note.txt

sh -c запускает оболочку внутри контейнера; она направляет вывод printf в файл. Последняя команда напечатает hello. Второй контейнер из того же образа начнёт с исходных файлов образа, поэтому этого note.txt в нём не будет.

1. Образ скачан через docker pull. Что уже произошло?
2. Файл записан в слой контейнера без mount. Что произойдёт после stop и start того же экземпляра?

Попробуйте в учебном терминале

Выполните три задания: получите образ, запустите короткую программу и сравните файлы двух работающих экземпляров. Имена из заданий отличаются от имён в примере; это позволяет повторять оба опыта в одной сессии.

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

учебный терминалзадания 0 / 3
Введите команду. Подсказка: help покажет, что умеет этот терминал.
de@deshka:~$
ЗАДАНИЯ
  1. 1. Скачайте образ alpine:3.21.
  2. 2. Создайте контейнер greeting из alpine:3.21, выполните echo ready и сохраните завершённый контейнер.
  3. 3. Запустите left и right из alpine:3.21 с sleep 3600. Создайте /tmp/marker.txt со строкой left-only только в left.
решённые задания сохранятся в прогресс после входа
Войти, чтобы отмечатьдальше →
5.2 →Практика: установка Docker