Лекция 1. Введение в Docker и контейнеризацию
Лекция 1. Введение в Docker и контейнеризацию
Дисциплина: системное администрирование. Редакция от 8 октября 2026 года.
Docker помогает упаковывать приложения, переносить их окружение и управлять запуском. В этой лекции основные понятия рассматриваются на примере небольшого веб-сервиса: от скачивания готового образа до сборки собственной версии сайта.
Результаты изучения
После изучения материала необходимо уметь:
- Объяснять различие между образом, контейнером и виртуальной машиной.
- Создавать, останавливать, повторно запускать и удалять контейнер.
- Проверять его состояние, читать логи и выполнять диагностическую команду.
- Объяснять запись публикации порта и выбирать адрес доступа.
- Определять, какие данные сохраняются после удаления контейнера.
- Собирать простой образ по Dockerfile и заменять контейнер новой версией.
Рабочая среда Docker на Windows: основные определения
Docker Desktop — приложение, которое предоставляет среду запуска Docker на рабочем компьютере, интерфейс управления и интеграцию с Windows. Docker Engine — система, которая создаёт контейнеры, управляет их запуском, сетями и хранилищами. Её фоновая служба называется Docker daemon: она продолжает работать, когда окно терминала закрыто.
Docker CLI — клиент командной строки, запускаемый командой docker. CLI отправляет запросы Engine через API, программный интерфейс управления. Поэтому установленная команда docker и работающий Engine — разные части системы. Термин «хост» далее означает среду, относительно которой выполняется действие: для опубликованного порта Desktop это компьютер Windows, а для Linux-процессов и их ядра — Linux-среда Desktop.
| Понятие | Назначение | Учебный пример |
|---|---|---|
| Терминал | Окно для ввода и отображения текста | Windows Terminal |
| Оболочка — shell | Разбирает введённую строку и запускает команды | PowerShell в Windows; sh внутри Alpine |
| CLI | Клиент для обращения к Docker Engine | docker ps запрашивает список контейнеров |
| Daemon | Фоновая служба, исполняющая запросы управления | Создаёт контейнер по запросу run |
| WSL 2 | Среда Windows для запуска Linux с настоящим Linux-ядром в управляемой виртуализированной среде | Docker Desktop может использовать backend WSL 2; Ubuntu для Bash устанавливается отдельно |
Студент
↓ ввод команды
Windows Terminal → PowerShell → Docker CLI
↓ запрос API
Docker Engine / daemon
↓ запуск
Linux-контейнер в среде Docker Desktop
Нажатие кнопки в Docker Desktop и ввод команды CLI являются разными способами управления объектами Docker. В этой практике команды позволяют явно видеть имя объекта и параметры операции. Выбор backend, доступность Engine и место выполнения команды проверяются в следующем разделе.
Для самопроверки: Почему закрытие PowerShell обычно не останавливает контейнер, запущенный с -d? Какой компонент продолжает им управлять?
Windows и Docker Desktop: выбор среды работы
Учебные примеры запускают Linux-контейнеры через Docker Desktop на Windows. Windows-контейнеры — другой режим; образы nginx:alpine и alpine относятся к Linux. В терминале проверяются доступ к Engine и выбранный режим:
На хосте: PowerShell или Bash.
docker version
docker context show
docker info --format '{{.OSType}}'
Ожидается ответ linux. При ошибке соединения сначала проверяется, что Docker Desktop запущен. Windows Terminal — приложение терминала: открытая вкладка может содержать PowerShell или Bash Ubuntu, и это определяет синтаксис команд.
| Место выполнения | Что запускается | Пример пути |
|---|---|---|
| PowerShell в Windows | Docker CLI и команды PowerShell | C:\Users\student\docker-lesson1 |
| Ubuntu в WSL 2 с интеграцией Docker Desktop | Docker CLI и Bash-команды | /home/student/docker-lesson1 |
| Оболочка внутри контейнера | Linux-команды контейнерного окружения | /data, /usr/share/nginx/html |
Для Bash-примеров используется терминал пользовательского дистрибутива WSL 2, а не системный дистрибутив docker-desktop. В Docker Desktop включается интеграция выбранного дистрибутива: Settings → Resources → WSL Integration. Наличие backend WSL 2 само по себе не означает наличие Ubuntu с рабочей интеграцией. В PowerShell Docker можно использовать без Ubuntu. Подробнее: Docker Desktop и WSL 2.
PowerShell- и Bash-варианты выполняются на выбор. При обращении к одному Docker Engine они используют общие контейнеры, сети и тома: повторное выполнение второго варианта может вызвать конфликт имён. В этих примерах Windows-папка и отдельная папка /home в WSL содержат разные наборы файлов. Через /mnt/c или /mnt/f WSL может обращаться к той же Windows-папке; это не новая копия проекта. Основной маршрут практики ниже — PowerShell и папки Windows. Bash-блоки показывают альтернативный синтаксис. При выборе Bash необходимые папки и файлы также готовятся заранее: Windows-проект можно открыть через /mnt/c или /mnt/f, а отдельный Linux-проект — через Проводник по пути \\wsl.localhost к своему дистрибутиву и редактор. Для сборки терминал должен быть открыт в папке соответствующего Dockerfile; путь Windows C:\… нельзя вставлять в Bash как Linux-путь. Docker context show показывает выбранный контекст, а docker info — сведения о сервере. Имена контекстов в Windows и WSL могут отличаться даже при обращении к одному Engine; совпадение имени контекста само по себе также не доказывает совпадение серверов.
Как читать блоки команд
| Действие | Bash / WSL | PowerShell |
|---|---|---|
| Перенос команды | Обратная косая черта \ в конце строки | Одна строка либо обратный апостроф `; после него не должно быть пробелов |
| HTTP-запрос | curl URL | curl.exe URL — явный запуск утилиты, независимо от алиаса curl |
| Создание каталога | В Linux-примере каталог готовится заранее | Создать папку в Проводнике |
| Просмотр файла | cat FILE | Get-Content FILE |
| Пауза | sleep 10 | Start-Sleep -Seconds 10 |
| Текущий каталог | $PWD | (Get-Location).Path |
| Подготовка файлов | Содержимое сохраняется в указанном файле | Создать файл в редакторе и сохранить в папке проекта |
Команды Dockerfile и исходный код программы не являются командами PowerShell. В блоках с пометкой «внутри контейнера» сохраняется Linux-синтаксис: например, после docker exec -it … sh команды cat, ps и exit выполняются контейнерной оболочкой. Строка после docker … sh -c также обрабатывается Linux-оболочкой внутри контейнера, даже если Docker CLI запущен из PowerShell.
В PowerShell 5.1 символы && и || вне строки аргумента не поддерживаются как Bash-операторы. Встроенные двойные кавычки в аргументах внешних программ тоже могут передаваться иначе, чем в PowerShell 7. Ниже PowerShell-примеры используют простые аргументы; сложные Bash-блоки выполняются в WSL, а не копируются без изменений в PowerShell.
Подготовка папок и файлов средствами Windows
Папки создаются в Проводнике. В нужной папке выбирается «Открыть в терминале» и вкладка PowerShell; если терминал открылся в другом месте, расположение проверяется через Get-Location. Dockerfile, .dockerignore, HTML и исходники создаются в обычном редакторе и сохраняются в указанную папку. Команды создания папок и записи файлов PowerShell в этой лекции не требуются.
В Проводнике включается показ расширений: файл должен называться Dockerfile, а не Dockerfile.txt, и .dockerignore, а не .dockerignore.txt. В редакторе выбирается UTF-8; для скриптов и конфигурации предпочтительно без BOM. Если Блокнот добавляет .txt, при сохранении выбирается тип «Все файлы» и проверяется итоговое имя в Проводнике. Для Linux shell-скриптов также выбирается LF; иначе возможны ошибки /bin/sh^M или not found. Перед сохранением учебного примера проверяется, что файл не содержит чужой работы.
1. Зачем нужна контейнеризация
При переносе приложения с компьютера разработчика на сервер требуется воспроизвести его окружение. Приложению могут понадобиться конкретная версия языка, библиотеки, системные пакеты и конфигурация. На сервере уже могут работать другие программы с несовместимыми зависимостями. В результате одни и те же исходные файлы ведут себя по-разному в разработке, тестировании и эксплуатации.
Окружение можно устанавливать вручную или описывать средствами управления конфигурацией, например Ansible. Другой способ — выделять приложениям отдельные виртуальные машины. Контейнеризация решает задачу упаковки иначе: файлы приложения и его пользовательские зависимости включаются в образ, а приложение запускается в изолированном окружении.
Контейнеризация — способ запуска приложений в изолированных окружениях на основе механизмов операционной системы. Linux-контейнеры используют ядро Linux среды, в которой они запущены.
Образ помогает воспроизводить пользовательское окружение, но сам по себе не гарантирует одинаковую работу всей системы. Значение имеют параметры запуска, права доступа, внешние базы данных, сеть, архитектура процессора и совместимость ядра. Например, пароль к базе данных и её адрес задаются для конкретной среды, а не обязательно входят в образ.
Для администратора контейнеризация полезна при развёртывании сервисов, создании тестовых окружений, разделении зависимостей и автоматизации доставки новых версий приложения.
2. Образ, контейнер и реестр
Для первого запуска достаточно различать три основных объекта.
| Объект | Значение | Пример |
|---|---|---|
| Образ — image | Неизменяемый шаблон файловой системы и параметров запуска | nginx:alpine |
| Контейнер — container | Созданный из образа экземпляр со своей конфигурацией, состоянием и записываемым слоем | lesson1-web |
| Реестр — registry | Сервис хранения и распространения образов | Docker Hub |
Образ содержит файлы приложения, библиотеки и метаданные. Он не является работающим процессом. Из одного образа можно создать несколько контейнеров с разными именами, сетевыми параметрами и хранилищами. Контейнер остаётся объектом Docker и после остановки главного процесса, пока не будет удалён.
Образ задаёт основу окружения. Контейнер — конкретный экземпляр, созданный из этой основы. Скачивание образа, создание контейнера и запуск процесса являются отдельными действиями.
В имени nginx:alpine часть nginx обозначает репозиторий образа, а alpine — тег варианта. В обычной конфигурации полное имя — docker.io/library/nginx:alpine. Репозиторий группирует варианты образа внутри реестра. Если тег не указан, используется latest; это обычная метка, которая не гарантирует последнюю версию приложения.
Тег — изменяемая метка для выбора образа. Digest — идентификатор содержимого, обычно записанный как sha256:…; в ссылке на образ он указывается после @. Image ID из локального списка и digest ссылки на образ не следует считать одним полем. Для фиксации проверенного выпуска выбирают ссылку с digest, а для учебных сборок далее используются понятные теги версий.
Теги могут указывать на новое содержимое со временем. Для контролируемых выпусков выбирают проверенные версии, а для фиксации конкретного содержимого используют digest. В учебных примерах nginx:alpine выбран как компактный образ знакомого HTTP-сервера.
3. Контейнер и виртуальная машина
Виртуальная машина получает виртуальное оборудование и запускает собственную гостевую ОС с собственным ядром. Контейнер изолирует процессы и их окружение средствами операционной системы. Его файловая система может содержать пользовательское окружение Alpine или Ubuntu, но отдельное ядро Linux в обычном контейнере не загружается.
| Свойство | Виртуальная машина | Linux-контейнер |
|---|---|---|
| Основа изоляции | Виртуальный компьютер | Процессы и их окружение |
| Ядро | Собственное гостевое ядро | Общее ядро среды запуска |
| Запуск | Включает загрузку гостевой ОС | Включает подготовку окружения и запуск процесса |
| Применение | Отдельные серверные ОС и инфраструктурные границы | Упаковка, запуск и замена приложений |
Контейнеры обычно быстрее запускаются и требуют меньше дополнительных ресурсов, поскольку каждому не нужна отдельная гостевая ОС. Это не означает, что само приложение расходует меньше памяти или CPU. Контейнер и ВМ предоставляют разные границы изоляции; выбор зависит от задачи.
Эти технологии часто используют вместе: на виртуальном сервере устанавливают Docker Engine и запускают контейнеры. Для Linux-контейнеров через Docker Desktop на Windows или macOS ядро предоставляет виртуализированная Linux-среда. Поэтому «ядро хоста контейнера» не обязательно означает ядро компьютера, на котором открыт терминал Docker CLI.
4. Первый запуск веб-сервиса
Для начала запускается Docker Desktop. В выбранном терминале проверяются docker version и docker info --format '{{.OSType}}'. Ожидается linux. Требования установки проверяются по официальной инструкции Docker Desktop. Наличие приложения не требует устанавливать отдельный Docker Engine в Ubuntu WSL.
Порядок работы с практическими разделами
Каждый эксперимент проходит семь шагов: определить понятия → объяснить задачу на примере → подготовить папки и файлы → выполнить команды → проверить ожидаемый результат → объяснить причину результата → ответить на вопрос для самопроверки. Подготовка выполняется Проводником и редактором; команды Docker вводятся в указанной оболочке. Практика продолжается после проверки предыдущего шага, а не после простого копирования блока.
Если результат отличается, фиксируются команда, текст ошибки, состояние контейнера и выбранная среда. Затем используется соответствующий диагностический раздел. Для отчёта достаточно сохранить команды, существенную часть вывода и объяснение: какой объект изменился и почему.
Программа, процесс и сервис
Программа — исполняемый код и необходимые ему файлы. Процесс — запущенный экземпляр программы со своим состоянием, памятью и идентификатором PID. Один файл программы может использоваться несколькими процессами. Наличие программы в образе ещё не означает, что она выполняется.
Сервис — программа или согласованная группа процессов, предоставляющая функцию другим программам или пользователям. Веб-сервис обычно остаётся запущенным и ждёт запросов. Главный процесс контейнера должен продолжать работу: если он завершится, контейнер остановится. Принцип foreground означает, что основной процесс остаётся активным, а не запускается в фоне из оболочки, которая сразу заканчивает работу. Параметр Docker -d отделяет терминал клиента от контейнера; он не требует переводить приложение внутри контейнера в background.
В примерах используется nginx — веб-сервер. Он получает запрос по HTTP, протоколу обмена между клиентом и веб-сервером, и отдаёт файл страницы. HTML — язык разметки этой страницы; браузер отображает её, а curl.exe выводит полученное содержимое в терминал. Nginx может создавать несколько процессов, поэтому «один сервис» не означает строго «один процесс».
Образ содержит программу nginx и файлы страницы
↓ docker run
В контейнере работают процессы nginx
↓ запрос браузера или curl.exe
Nginx возвращает HTML-страницу
Для самопроверки: Почему скачанный образ nginx сам по себе не обслуживает HTTP-запросы? Чем -d отличается от завершения главного процесса?
4.1. Условия выполнения
Учебная среда — Windows с запущенным Docker Desktop в режиме Linux containers. Команды выполняются в PowerShell либо Bash в интегрированном WSL. Для скачивания образов нужен доступ к реестру. Sudo относится к отдельной серверной установке Linux и не добавляется перед docker в PowerShell.
Команды Docker выполняются в выбранном терминале Windows или WSL, кроме блока, явно обозначенного как работа внутри контейнера. Примеры этой лекции образуют последовательность. Перед началом проверяется, что имя lesson1-web и порт 8080 свободны. Ранее созданные объекты с важными данными не удаляются ради выполнения примера.
На хосте: PowerShell или Bash.
docker version
docker info
docker ps -a
Ожидаемый результат: docker version выводит сведения о клиенте и сервере; docker info показывает параметры Docker Engine. В docker ps -a не должно быть прежнего контейнера lesson1-web. Наличие команды docker само по себе не означает доступность демона.
Как читать команду Docker и имена объектов
Командная строка читается слева направо. После docker выбирается действие. Для run параметры Docker находятся перед именем образа; после образа могут идти команда контейнера и её аргументы. Параметр — именованная настройка операции; аргумент — переданное ей значение. Кавычки объединяют текст с пробелами в один аргумент. Следующая запись — схема синтаксиса: IMAGE заменяется именем образа, а квадратные скобки обозначают необязательные части и не вводятся буквально в терминал.
docker run [параметры Docker] IMAGE [COMMAND] [ARGUMENTS]
| Часть учебной команды | Значение |
|---|---|
| docker run | Создать новый контейнер и запустить его |
| --name lesson1-web | Дать контейнеру имя lesson1-web |
| -d | Продолжить работу контейнера без удержания текущего терминала |
| -p 127.0.0.1:8080:80 | Настроить публикацию порта |
| nginx:alpine | Выбрать образ; это не имя контейнера |
Запись nginx:alpine обозначает репозиторий и тег образа. lesson1-web — выбранное имя конкретного контейнера. Container ID — идентификатор, который Docker присваивает контейнеру; он изменяется при создании нового экземпляра. Image ID — идентификатор образа. Команды start, stop, logs и exec обычно получают имя или ID контейнера, а run и build работают с образами в соответствии со своим назначением. Для ясности учебные команды используют полные имена контейнеров.
Например, в строке docker run --rm alpine echo done параметры --rm относятся к Docker, alpine — образ, echo — программа контейнера, done — её аргумент. После имени образа строка уже не разбирается как набор параметров Docker. Готовый образ nginx задаёт собственную команду запуска, поэтому она не повторяется в первом run.
Для самопроверки: Какой объект получает имя lesson1-web и какой выбирается записью nginx:alpine? Что изменит повторный run, а что делает start?
4.2. Скачивание образа
На хосте: PowerShell или Bash.
docker pull nginx:alpine
docker image ls nginx
Ожидаемый результат: Docker скачивает необходимые слои либо сообщает, что образ актуален. В списке образов появляется nginx с тегом alpine. Колонки REPOSITORY и TAG описывают имя, IMAGE ID — локальный идентификатор. Контейнер на этом шаге ещё не создаётся.
Запуск и готовность — разные шаги. Команды выполняются последовательно, с проверкой результата каждого шага. Ответ docker run -d или docker start ещё не означает, что приложение готово принимать HTTP. При первом Connection refused нужно подождать несколько секунд и повторить запрос. Если ответ не появляется, проверяются docker ps -a и docker logs для этого контейнера. Для образа с HEALTHCHECK ожидается healthy, а не только running; проверка состояния повторяется через inspect. Сетевой запрос проверяет именно указанный адрес и порт.
IP-адрес, порт и localhost
IP-адрес определяет сетевой адрес назначения. Порт позволяет выбрать приложение или точку приёма соединений на этом адресе. Порт относится к транспортному протоколу: TCP и UDP имеют отдельные пространства портов. В учебном nginx-примере используется HTTP через TCP. Слушающий процесс ожидает подключения к выбранному адресу и порту.
Loopback — сетевой путь обратно в ту же среду. Адрес 127.0.0.1 — IPv4 loopback; имя localhost обычно указывает на loopback-адрес, включая IPv6 ::1. Далее используется явный IPv4-адрес, чтобы адрес запроса совпадал с адресом публикации. Localhost внутри контейнера относится к этому контейнеру, а в браузере Windows — к компьютеру Windows.
Браузер Windows или curl.exe
↓ HTTP-запрос к 127.0.0.1:8080
Публикация порта Docker Desktop
↓ передача запроса на TCP 80 контейнера
Процесс nginx
↓ чтение index.html и HTTP-ответ
Клиент получает HTML
В записи -p 127.0.0.1:8080:80 слева находится адрес и порт Windows-хоста, справа — порт приложения внутри контейнера. Публикация не перенастраивает nginx слушать 8080. Если приложение не запущено или не слушает порт 80, одна публикация не создаст работоспособный сервис.
Для самопроверки: Почему в адресе браузера используется 8080, а nginx внутри контейнера продолжает слушать 80? Почему localhost другого контейнера не ведёт к nginx?
4.3. Создание контейнера и публикация порта
Bash / WSL:
docker run --name lesson1-web -d \
-p 127.0.0.1:8080:80 nginx:alpine
docker ps --filter name=lesson1-web
curl http://127.0.0.1:8080
PowerShell:
docker run --name lesson1-web -d -p 127.0.0.1:8080:80 nginx:alpine
docker ps --filter name=lesson1-web
curl.exe http://127.0.0.1:8080
docker run создаёт новый контейнер и запускает его. --name задаёт имя, -d запускает контейнер в фоне. В записи -p 127.0.0.1:8080:80 адрес 127.0.0.1 относится к хосту, 8080 — порт хоста, 80 — порт nginx внутри контейнера.
Ожидаемый результат: run выводит идентификатор контейнера; в docker ps виден статус Up; curl возвращает HTML стандартной страницы nginx. В колонке PORTS отражается публикация 127.0.0.1:8080->80/tcp.
При удалённом подключении к серверу curl выполняется на этом сервере. Адрес 127.0.0.1 в браузере личного компьютера относится к самому компьютеру. Наличие контейнера на удалённом сервере не меняет значение localhost.
Docker Desktop на Windows. Опубликованный порт открывается из Windows-браузера по http://127.0.0.1:8080. Внутри контейнера localhost означает сам контейнер. Для обращения из контейнера к сервису Windows-хоста используется host.docker.internal и порт этого сервиса. Для связи контейнеров используются их сетевые имена. Bridge и veth принадлежат Linux-среде Docker Desktop, а не обычным интерфейсам Windows. IP контейнера не является основным адресом доступа из Windows. Документация сети.
Для самопроверки: Какой путь прошёл HTTP-запрос после первого запуска? Какие команды помогут отличить недоступный Engine от работающего контейнера с неготовым nginx?
4.4. Первые сообщения об ошибках
| Симптом | Что проверить |
|---|---|
| Cannot connect to the Docker daemon | Запущен ли демон и к какому Engine обращается клиент |
| Permission denied при доступе к Docker socket | Разрешён ли пользователю доступ; для обычной серверной установки — запуск через sudo |
| Имя контейнера уже используется | docker ps -a: остановленный контейнер тоже сохраняет имя |
| Порт уже занят | Другой сервис или контейнер на хосте может использовать 8080 |
| curl не получает ответ | Статус контейнера, логи, публикацию порта и правильный адрес хоста |
5. Диагностика, остановка и удаление
Ввод, вывод и чтение результатов диагностики
| Поток | Определение | Пример |
|---|---|---|
| stdin — стандартный ввод | Данные, передаваемые процессу на вход | Команды, вводимые в интерактивную оболочку |
| stdout — стандартный вывод | Обычный вывод процесса | Текст результата или сообщения о работе |
| stderr — стандартный вывод ошибок | Отдельный поток диагностических сообщений | Предупреждение или сообщение об ошибке |
stdout и stderr обычно отображаются в одном окне терминала, но являются разными потоками. Запись сообщения в stderr сама по себе не означает остановку процесса. Лог — последовательность сообщений о событиях; Docker может собирать stdout/stderr контейнера через настроенный драйвер. Файл журнала внутри контейнера не обязательно автоматически появляется в docker logs.
Для диагностики сравниваются состояние объекта, конфигурация и сообщения приложения. Следующая строка — учебный пример вывода docker ps; ID и длительность на каждом компьютере будут другими.
CONTAINER ID IMAGE STATUS PORTS NAMES
abc123def456 nginx:alpine Up 20 seconds 127.0.0.1:8080->80/tcp lesson1-web
| Колонка | Что она сообщает |
|---|---|
| CONTAINER ID | Идентификатор конкретного контейнера |
| IMAGE | Образ, из которого он создан |
| STATUS | Состояние и время работы; это не доказательство успешного HTTP-ответа |
| PORTS | Публикации портов и сведения о контейнерных портах |
| NAMES | Имена контейнеров |
docker ps по умолчанию перечисляет работающие контейнеры, docker ps -a — также остановленные. Полный JSON из inspect — структурированные сведения в форме пар «поле — значение». На первом этапе в нём ищутся State, Config и NetworkSettings, а не запоминается весь вывод. Код завершения — числовой результат закончившейся команды или процесса — подробно рассматривается во второй лекции.
Для самопроверки: Если в logs есть сообщение об ошибке, как проверить, остановился ли контейнер? Доказывает ли статус Up доступность страницы?
5.1. Логи и конфигурация
На хосте: PowerShell или Bash.
docker logs --tail 20 lesson1-web
docker inspect lesson1-web
docker port lesson1-web
Ожидаемый результат: logs показывает сообщения запуска и обработки запросов; inspect выводит JSON с состоянием, образом, сетью и точками подключения; port показывает адрес и порт публикации. Конкретные сообщения зависят от версии образа.
docker logs читает доступный журнал stdout и stderr с учётом используемого драйвера логирования. Для наблюдения за новыми строками используется docker logs -f lesson1-web. Выход по Ctrl+C прекращает наблюдение и оставляет контейнер работающим.
5.2. Дополнительный процесс внутри контейнера
На хосте: PowerShell или Bash.
docker exec -it lesson1-web sh
exec запускает дополнительный процесс в работающем контейнере. -i оставляет ввод открытым, -t выделяет псевдотерминал. В данном образе используется оболочка sh.
Следующий блок выполняется внутри контейнера:
hostname
cat /etc/os-release
ps
exit
Ожидаемый результат: видны имя контейнерного окружения, сведения об Alpine и процессы, доступные внутри контейнера. exit завершает добавленную оболочку; основной процесс nginx продолжает работать. Файл /etc/os-release описывает пользовательское окружение образа, а не отдельное ядро контейнера.
5.3. Остановка и повторный запуск
Bash / WSL:
docker stop lesson1-web
docker ps --filter name=lesson1-web
docker ps -a --filter name=lesson1-web
docker start lesson1-web
curl http://127.0.0.1:8080
PowerShell:
docker stop lesson1-web
docker ps --filter name=lesson1-web
docker ps -a --filter name=lesson1-web
docker start lesson1-web
curl.exe http://127.0.0.1:8080
Ожидаемый результат: после stop контейнер исчезает из обычного docker ps, но остаётся в docker ps -a со статусом Exited. start запускает тот же контейнер с прежней конфигурацией; сайт снова отвечает.
run создаёт новый контейнер. start запускает существующий остановленный контейнер. stop завершает работу, сохраняя объект контейнера. rm удаляет этот объект.
5.4. Удаление
На хосте: PowerShell или Bash.
docker stop lesson1-web
docker rm lesson1-web
docker ps -a --filter name=lesson1-web
docker image ls nginx
Ожидаемый результат: контейнера больше нет, но образ nginx:alpine остаётся локально. Имя lesson1-web освободилось. Оно будет использовано далее для контейнера собственного сайта.
Для одноразовых задач применяется --rm: Docker автоматически удаляет контейнер после завершения процесса. Этот параметр не удаляет исходный образ. Принудительное rm -f не заменяет корректную остановку сервисов, которым нужно завершить запись данных.
При работе из Windows docker exec … uname -a показывает Linux-ядро среды Docker Desktop. Команда uname -a непосредственно в PowerShell может отсутствовать и не является способом проверить ядро Windows.
6. Как Docker выполняет команды
Docker — платформа и набор инструментов для сборки, распространения образов и управления контейнерами. Docker Engine включает демон, API и клиент командной строки. При выполнении docker ps клиент обращается к API, а демон возвращает сведения о контейнерах.
Основная схема управления: Docker CLI → Docker API → Docker daemon. Клиент может обращаться к локальному или удалённому Docker Engine.
При запуске контейнера dockerd координирует нижележащие компоненты, включая containerd и OCI runtime, обычно runc. Результат — процесс с подготовленным окружением и ограничениями. Подробности этих компонентов относятся к внутреннему устройству платформы; для базовой диагностики прежде всего нужно различать клиент и доступный ему демон.
Linux предоставляет два ключевых механизма. Namespaces изменяют представление процесса о ресурсах: например, о дереве процессов, сети и точках монтирования. Cgroups учитывают и ограничивают потребление ресурсов группами процессов, включая память и CPU.
| Механизм | Основной вопрос | Пример |
|---|---|---|
| Namespaces | Какие ресурсы видит процесс? | Контейнер видит собственную таблицу процессов |
| Cgroups | Какие ресурсы он может потреблять? | Контейнер получает ограничение памяти |
Перечень возможностей Linux не означает, что все пространства имён одинаково используются в любой конфигурации. Например, сопоставление пользователей через user namespaces настраивается отдельно; модели rootful, userns-remap и rootless имеют различия.
По умолчанию контейнеру не выделяется фиксированная доля ресурсов. Если лимиты не заданы, он конкурирует с другими процессами за ресурсы среды запуска. Docker предоставляет параметры ограничения, например --memory и --cpus.
Работа контейнера связана с его главным процессом, обычно PID 1 внутри PID namespace. Завершение главного процесса останавливает контейнер. При docker stop сначала посылается сигнал корректного завершения, а после истечения времени ожидания при необходимости применяется принудительное завершение. Подробная обработка сигналов рассматривается во второй лекции.
7. Сетевая доступность сервиса
Процесс nginx слушает порт 80 внутри контейнера. Этот факт не создаёт автоматическую публикацию порта на хосте. Сетевой доступ задаётся отдельно. Инструкция EXPOSE в образе документирует предполагаемый порт и сама по себе не заменяет -p.
| Параметр | Значение |
|---|---|
| -p 127.0.0.1:8080:80 | Порт контейнера доступен через localhost Docker-хоста |
| -p 8080:80 | Порт публикуется на всех адресах хоста по умолчанию; фактический доступ зависит от сети и фильтрации |
| -p 80:8080 | Порт 80 хоста направляется на порт 8080 контейнера; это не соответствует стандартному слушателю nginx на 80 |
В первом примере выбран loopback-адрес, поскольку изучение команд не требует открывать сервис во внешнюю сеть. Для удалённых пользователей нужен другой способ предоставления доступа, выбранный с учётом конфигурации сервера.
В пользовательской bridge-сети контейнеры могут обращаться друг к другу по именам без публикации их портов на хосте. Подробные примеры сетей, DNS и взаимодействия нескольких сервисов приведены во второй лекции.
Пути Windows и Linux. Источник bind mount в PowerShell — существующий Windows-путь, например C:\Users\student\docker-lesson1\bind-site. Назначение в контейнере остаётся Linux-путём /data или /usr/share/nginx/html. В WSL путь /mnt/c обозначает диск C:, а /home — Linux-файловую систему дистрибутива. Docker Desktop предоставляет контейнерам доступ к файлам Windows. Named volume управляется Docker, его не следует искать как обычную папку проекта в Проводнике. Bind mounts.
8. Данные и жизненный цикл контейнера
Изменения файлов в обычных каталогах контейнера попадают в его записываемый слой — writable layer. Остановка и повторный запуск сохраняют этот слой. Удаление контейнера удаляет слой: новый контейнер из прежнего образа не получает старые изменения.
| Место хранения | Назначение | После удаления контейнера |
|---|---|---|
| Writable layer | Изменения конкретного экземпляра | Удаляется вместе с контейнером |
| Named volume | Постоянное хранилище, управляемое Docker | Сохраняется, пока том не удалён отдельно |
| Bind mount | Подключение конкретного пути Docker-хоста | Файлы остаются по пути хоста |
Для проверки постоянства создаётся отдельный учебный том. Перед началом имя lesson1-data должно быть свободно. Команды выполняются на хосте:
Bash / WSL:
docker volume create lesson1-data
docker run --rm \
--mount type=volume,src=lesson1-data,dst=/data \
alpine sh -c 'echo lesson 1 data > /data/note.txt'
docker run --rm \
--mount type=volume,src=lesson1-data,dst=/data,ro \
alpine cat /data/note.txt
PowerShell:
docker volume create lesson1-data
docker run --rm --mount type=volume,src=lesson1-data,dst=/data alpine sh -c 'echo lesson 1 data > /data/note.txt'
docker run --rm --mount type=volume,src=lesson1-data,dst=/data,ro alpine cat /data/note.txt
Ожидаемый результат: второй контейнер выводит lesson 1 data. Первый контейнер к этому моменту уже удалён благодаря --rm, но файл сохранён в именованном томе. Оба временных контейнера удаляются; том остаётся до завершающей очистки.
Bind mount используется, когда контейнеру нужен конкретный файл или каталог хоста, например конфигурация. Если запись не требуется, подключение задаётся только для чтения. Выбор типа хранения и права доступа подробно рассматриваются во второй лекции.
Постоянные данные отделяют от заменяемого контейнера. Наличие volume не является резервной копией: удаление или повреждение данных внутри тома требует отдельной защиты и восстановления.
9. Собственный образ статического сайта
Dockerfile, исходные файлы, образ и слои
Исходные файлы проекта — материалы, из которых готовится приложение: в этом примере index.html. Dockerfile — текстовое описание действий сборки, а не готовый образ и не команда PowerShell. Сборка создаёт образ по этому описанию и доступным входным файлам. Контекст сборки — набор файлов, доступный сборщику; точка в команде build означает текущую папку.
Папка docker-lesson1
Dockerfile + index.html
↓ docker build
Образ lesson1-site:1.0
↓ docker run
Контейнер lesson1-web с процессами nginx
Слой образа описывает изменения файловой системы относительно предыдущих слоёв: добавление, изменение или удаление файлов. Базовый nginx-образ уже содержит программу и её окружение. COPY добавляет учебную страницу. Docker объединяет слои в доступную контейнеру файловую систему и предоставляет отдельный записываемый слой экземпляра.
Записываемый слой контейнера — изменения данного экземпляра
----------------------------------------------------------
Слой с index.html, добавленный при сборке учебного образа
----------------------------------------------------------
Слои базового nginx-образа — nginx, библиотеки, окружение
Не каждая инструкция Dockerfile добавляет файловый слой: часть инструкций задаёт метаданные запуска. Редактирование файла в контейнере не переписывает исходный Dockerfile или образ. Редактирование index.html в папке проекта тоже не меняет готовый образ до новой сборки. В разделе о выпуске версии эти различия проверяются на одном сайте. Образы и слои в документации Docker.
Для самопроверки: Что нужно повторить после изменения исходного index.html, чтобы новый контейнер получил обновлённую страницу? Почему старая страница может оставаться в уже запущенном контейнере?
9.1. Подготовка файлов
Dockerfile описывает сборку образа. Для простого сайта достаточно выбрать базовый nginx-образ и добавить index.html. Для подготовки файлов используются Проводник и редактор. Используется отдельный учебный каталог; если он уже существует с другими файлами, для примера выбирается новый путь.
Windows: в Проводнике создать папку docker-lesson1 в удобном месте. В ней редактором создать index.html и Dockerfile. После сохранения файлов открыть PowerShell в этой папке.
Файл index.html: создать или открыть в редакторе, сохранить следующее содержимое.
<h1>Docker: first site</h1>
Файл Dockerfile: создать или открыть в редакторе, сохранить следующее содержимое.
FROM nginx:alpine
COPY index.html /usr/share/nginx/html/index.html
Ожидаемый результат: в выбранной папке docker-lesson1 должны находиться два файла: index.html и Dockerfile. FROM задаёт базовый образ, COPY добавляет страницу в каталог nginx.
9.2. Сборка и запуск
Bash / WSL:
docker build -t lesson1-site:1.0 .
docker run --name lesson1-web -d \
-p 127.0.0.1:8080:80 lesson1-site:1.0
curl http://127.0.0.1:8080
PowerShell:
docker build -t lesson1-site:1.0 .
docker run --name lesson1-web -d -p 127.0.0.1:8080:80 lesson1-site:1.0
curl.exe http://127.0.0.1:8080
Сборка выполняется из каталога, где подготовлены Dockerfile и index.html. Точка обозначает текущий каталог как контекст сборки — набор файлов, доступных builder. lesson1-site:1.0 — имя и тег нового образа.
Ожидаемый результат: сборка завершается успешно, новый контейнер получает имя lesson1-web, а curl выводит страницу Docker: first site. Контейнер с этим именем из раздела 5 уже удалён; сейчас создаётся другой экземпляр из собственного образа.
9.3. Выпуск новой версии
Шаг 1 — редактор Windows: изменить index.html и сохранить страницу.
Файл index.html: создать или открыть в редакторе, сохранить следующее содержимое.
<h1>Docker: updated site</h1>
Шаг 2 — терминал в той же папке: собрать образ и заменить контейнер.
docker build -t lesson1-site:1.1 .
curl.exe http://127.0.0.1:8080
docker stop lesson1-web
docker rm lesson1-web
docker run --name lesson1-web -d -p 127.0.0.1:8080:80 lesson1-site:1.1
curl.exe http://127.0.0.1:8080
Ожидаемый результат: сразу после новой сборки работающий контейнер всё ещё отдаёт первую страницу. Только после его замены контейнером из lesson1-site:1.1 появляется Docker: updated site. Изменение файлов на хосте и сборка образа сами по себе не обновляют уже созданный контейнер.
Этот пример иллюстрирует воспроизводимое обновление: изменить исходники, собрать образ, создать новую версию контейнера. Ручная правка через docker exec не входит в исходный образ и теряется при пересоздании. Для реального сервиса также планируются перерыв в работе, проверка новой версии и возможность отката.
RUN, CMD, ENTRYPOINT, кеш сборки, .dockerignore и многоэтапные сборки подробно рассматриваются во второй лекции. На этом этапе важно различать сборку образа и запуск контейнера.
Для самопроверки: Какие действия изменили исходники, какие создали новый образ, а какие заменили контейнер? Почему сборка версии 1.1 не обновила работающую версию 1.0 автоматически?
10. Базовые правила безопасной эксплуатации
- Запускать образы из проверенных источников и управлять их обновлением.
- Публиковать только необходимые порты; для локальных примеров выбирать loopback.
- Отделять постоянные данные от writable layer и планировать резервное копирование.
- Не выдавать --privileged и запись в каталоги хоста без обоснованной необходимости.
- Защищать Docker daemon и не передавать его socket недоверенным приложениям.
- По возможности запускать приложение непривилегированным пользователем и ограничивать ресурсы.
На отдельном Linux-сервере в обычной rootful-конфигурации доступ к Docker daemon предоставляет широкие возможности управления этим сервером. Членство в Linux-группе docker следует рассматривать как привилегированный доступ. Для Docker Desktop на Windows группа docker из Linux-инструкции не является способом настройки Windows-учётной записи; доступ к Desktop и подключённым каталогам управляется средствами Windows и Docker Desktop. Контейнерная изоляция не устраняет уязвимости приложения и не заменяет управление правами.
Завершение учебного сценария
Следующие команды выполняются после всех примеров и удаляют только созданные ими объекты. Удаление lesson1-data уничтожает учебный файл note.txt. Исходные файлы сайта остаются в каталоге docker-lesson1.
На хосте: PowerShell или Bash.
docker stop lesson1-web
docker rm lesson1-web
docker volume rm lesson1-data
docker image rm lesson1-site:1.0 lesson1-site:1.1
docker ps -a --filter name=lesson1-web
docker volume ls --filter name=lesson1-data
Ожидаемый результат: контейнер, учебный том и два собственных образа удалены. Готовые базовые образы nginx и alpine могут оставаться локально. Общая очистка Docker-хоста для завершения этого сценария не требуется.
11. Задания для самопроверки
Задание 1. После docker stop lesson1-web команда docker ps не показывает контейнер. Нужно ли снова выполнять docker run? Какая команда позволит проверить, сохранился ли контейнер?
Ответ. Состояние проверяется через docker ps -a. Остановленный контейнер запускается командой docker start. Повторный run создавал бы новый объект и при прежнем имени вызвал бы конфликт.
Задание 2. Один файл записан в writable layer, второй — в named volume. Контейнер остановлен, затем удалён. Какие данные сохранятся на каждом шаге?
Ответ. После остановки сохраняются оба файла. После удаления контейнера записываемый слой удаляется, а файл в именованном томе остаётся. Отдельное удаление тома уничтожит и этот файл.
Задание 3. Nginx слушает порт 80 внутри контейнера. Требуется доступ только с Docker-хоста через порт 8080. Правильна ли запись -p 80:8080?
Ответ. Нет. Нужна запись -p 127.0.0.1:8080:80. Слева задаются адрес и порт хоста, справа — порт контейнера.
Задание 4. Образ сайта пересобран с новой страницей. Почему уже работающий контейнер продолжает отдавать старую страницу?
Ответ. Контейнер создан из прежнего образа. Новая сборка не меняет его автоматически. Для обновления создаётся контейнер из новой версии образа.
Задание 5. Внутри контейнера /etc/os-release сообщает Alpine. Доказывает ли это наличие отдельного ядра Alpine?
Ответ. Нет. Файл описывает пользовательское окружение. Системные вызовы обслуживает ядро Linux среды запуска контейнера.
12. Краткий конспект и переход к следующей лекции
- Образ — шаблон файлов и параметров запуска; контейнер — созданный из него экземпляр.
- Linux-контейнеры разделяют ядро среды запуска; виртуальная машина имеет гостевое ядро.
- run создаёт и запускает; stop останавливает; start повторно запускает; rm удаляет.
- ps, logs, inspect и exec помогают определить состояние и причины проблем.
- Публикация порта задаётся отдельно от порта, который слушает приложение.
- Постоянные данные сохраняются в отдельных хранилищах, а не только в writable layer.
- Новая версия приложения оформляется новой сборкой образа и заменой контейнера.
- Namespaces изолируют представление ресурсов, cgroups учитывают и ограничивают их использование.
Во второй лекции рассматриваются пользовательские сети и DNS, типы хранения и права доступа, структура Dockerfile, кеш сборки, PID 1, сигналы, проверки работоспособности и автоматический перезапуск. Основой этих тем служит выполненный здесь жизненный цикл одного сервиса.
Приложение. Docker Engine на отдельном Ubuntu Server
К Windows с Docker Desktop этот способ установки не относится. Apt, systemctl и usermod ниже выполняются на отдельном Linux-сервере. В PowerShell они не используются, а в интегрированном WSL для учебных примеров не требуется второй Docker Engine.
Установка через официальный apt-репозиторий включает удаление конфликтующих пакетов, добавление ключа и источника пакетов, установку компонентов и проверку запуска. Пример предназначен для учебной Ubuntu Server; перед применением проверяется поддержка версии ОС в официальной инструкции Docker.
Сначала удаляют конфликтующие пакеты, если они были установлены из других источников:
sudo apt remove $(dpkg --get-selections docker.io docker-compose docker-compose-v2 docker-doc docker-buildx podman-docker containerd runc | cut -f1)
Добавление официального ключа и репозитория Docker:
sudo apt update
sudo apt install -y ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
sudo tee /etc/apt/sources.list.d/docker.sources > /dev/null <<EOF
Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}")
Components: stable
Architectures: $(dpkg --print-architecture)
Signed-By: /etc/apt/keyrings/docker.asc
EOF
sudo apt update
Установка Docker Engine, CLI, containerd и плагинов Buildx и Compose:
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
Проверка службы и запуск тестового контейнера:
sudo systemctl status docker
sudo docker run hello-world
Для выполнения docker без sudo в обычной rootful-конфигурации пользователя можно добавить в группу docker. Членство в этой группе предоставляет привилегии, сопоставимые с root-доступом к хосту, поэтому такое изменение требует осознанного управления доступом.
sudo usermod -aG docker $USER
# затем требуется новый вход в сеанс пользователя
Для серверов с повышенными требованиями безопасности следует отдельно изучить rootless mode и модель прав Docker daemon.
Источники и дополнительная литература
Официальная документация Docker и спецификации OCI раскрывают понятия и команды, рассмотренные в лекции. Инструкция установки, параметры запуска и положения безопасности проверены по документации при подготовке этой редакции.
- Docker Documentation. Get started / Docker concepts. https://docs.docker.com/get-started/
- Docker Documentation. Docker Engine. https://docs.docker.com/engine/
- Docker Documentation. What is a container? https://docs.docker.com/get-started/docker-concepts/the-basics/what-is-a-container/
- Docker Documentation. What is an image? https://docs.docker.com/get-started/docker-concepts/the-basics/what-is-an-image/
- Docker Documentation. Networking overview. https://docs.docker.com/engine/network/
- Docker Documentation. Port publishing and mapping. https://docs.docker.com/engine/network/port-publishing/
- Docker Documentation. Storage. https://docs.docker.com/engine/storage/
- Docker Documentation. Docker Engine security. https://docs.docker.com/engine/security/
- Docker Documentation. Rootless mode. https://docs.docker.com/engine/security/rootless/
- Docker Documentation. Building best practices. https://docs.docker.com/build/building/best-practices/
- Docker Documentation. Install Docker Engine on Ubuntu. https://docs.docker.com/engine/install/ubuntu/
- Open Container Initiative. Runtime Specification. https://specs.opencontainers.org/runtime-spec/
- Open Container Initiative. Image Format Specification. https://specs.opencontainers.org/image-spec/
- Poulton, Nigel. Docker Deep Dive. Fourth Edition. Packt Publishing, 2025. 312 p. ISBN 9781837028344.
Примечание об актуальности
Установочные инструкции, поддерживаемые версии ОС и параметры Docker со временем обновляются. Для установки и обновления используется официальная документация соответствующей версии продукта. Основные термины лекции согласованы с моделью Docker Engine и OCI.