Docker: как создавать образы контейнеров и развертывать приложения
В текущей реальности информационных технологий Docker стал неотъемлемым инструментом, переписывающим правила игры в области разработки и развертывания приложений. Docker — это на сегодняшний день самая популярная у айтишников платформа, используемая, чтобы быстро и эффективно создавать, доставлять и запускать всевозможные контейнированные приложения. Но давайте же разберемся, какова истинная роль Docker в современной парадигме разработки, и почему использование в этой разработке контейнеров стало не просто актуальным, но и важнейшим аспектом для разработчиков.

Определение: что вообще такое Docker
Docker — это средство, позволяющее паковать всевозможные приложения прямо вместе со всеми включенными в них зависимостями в стандартизированные контейнеры. Эти самые контейнеры легко и просто могут быть перемещены между разными средами разработки и продакшна, обеспечивая консистентность и надежность выполнения ваших приложений. Docker гарантирует изоляцию отличных процессов и ресурсов, что делает его мощным инструментом для создания, тестирования, а также развертывания всевозможных приложений в разнообразных сценариях.
Роль Docker в современной разработке
Итак, почему Docker стал неотъемлемой частью современного арсенала разработчиков? Первое, что бросается в глаза, — это преодоление проблемы «это у меня работает на моей машине». Docker обеспечивает консистентность сред разработки и продакшна, устраняя конфликты из‑за различий в окружениях. Благодаря этому вы сможете избежать ряда трудностей, которые связаны с переносом приложений и сэкономите время, затрачиваемое на разрешение конфликтов.
Важным аспектом является также масштабируемость. Docker обеспечивает гибкость в управлении ресурсами, автоматическую оркестрацию и возможность масштабирования в зависимости от потребностей проекта. Это сделало Docker незаменимым инструментом для создания микросервисных архитектур, где компоненты приложения могут быть легко масштабированы и обновлены независимо друг от друга.
Введение Docker в современную разработку смогло привнести не только консистентность и переносимость, но и существенно улучшило процессы разработки и последующего беспроблемного развертывания приложений. В следующих разделах мы более подробно рассмотрим, как создавать образы контейнеров и разворачивать приложения с использованием этой инновационной технологии.
Основы Docker
Обзор архитектуры Docker
Прежде чем мы погрузимся в детали создания Docker‑образов, важно понять основы архитектуры этой платформы. Docker использует понятную клиент‑серверную архитектуру, где клиент общается с демоном (сервером) через REST API или с помощью командной строки. Демон управляет контейнерами, образами, сетями и другими ресурсами Docker. Эта архитектура обеспечивает модульность и позволяет эффективно управлять контейнерами на хосте.

Основным элементом являются Docker‑образы — это заранее подготовленные шаблоны, которые включают в себя все необходимое для корректной и быстрой работы приложения, включая библиотеки, сам код и все зависимости, а также произведенные настройки. Эти образы используются для создания контейнеров — изолированных исполняемых единиц, в которых запускается приложение.
Контейнеры vs виртуальные машины: различия и преимущества
В отличие от традиционных виртуальных машин, контейнеры представляют собой более компактное и производительное решение. Не в пример виртуальным машинам, которые включают в себя гипервизор, операционную систему и само приложение, контейнеры устроены иначе — они используют ядро операционной системы на хосте, что снижает изоляцию и потребление ресурсов.

Главным и неоспоримым достоинством использования в разработке контейнеров является, конечно, скорость запуска. Контейнеры могут быть запущены за считанные секунды, в то время как виртуальные машины требуют значительного времени на загрузку операционной системы и других компонентов.
Экономия ресурсов также является важным аспектом. Виртуальные машины требуют больше вычислительных ресурсов из‑за дополнительного уровня виртуализации, в то время как контейнеры используют общие ресурсы и изолируют лишь процессы приложения.
Контейнеры также, что немаловажно, обеспечивают более простую оркестрацию и управление масштабированием. Их легко масштабировать, запускать и оркестрировать с использованием самых различных инструментов, таких как Docker Compose и, например, Kubernetes.
Получается, понимание основ Docker и сравнение контейнеров с виртуальными машинами дает возможность разработчикам эффективнее использовать ресурсы, ускорять развертывание и обеспечивать более гибкое управление приложениями.
Создание Docker-образов
Шаг первый: Установка Docker и основные понятия
Начнем с того, что перед тем как приняться за создание ваших Docker‑образов, вам конечно же нужно заиметь Docker на рабочей машине. Процесс установки зависит от операционной системы, используемой на устройстве, и может быть найден на официальном сайте Docker. После успешного завершения установки важно ознакомиться с основными понятиями Docker.

Ключевыми понятиями являются образы (Images) и контейнеры (Containers). Разберемся с точными определениями того и другого. Образ — это шаблон, содержащий все необходимое для запуска приложения. Контейнер — это экземпляр образа, который запущен и работает в изолированной среде. Понимание разницы между образами и контейнерами является фундаментальным для работы с Docker.
Шаг второй: Структура Dockerfile и ее ключевые элементы
Создание Docker-образа начинается с определения его структуры в файле, называемом Dockerfile. Dockerfile — это текстовый файл, содержащий инструкции для построения Docker-образа. Важно знать ключевые элементы структуры Dockerfile:
- Базовый образ (Base Image): Указывает базовый образ, на базе которого и будет создаваться новый. Например, FROM ubuntu:latest.
- Инструкции по корректной настройке зависимостей: Используйте инструкции, такие как RUN, для установки необходимых пакетов и компонентов в образ.
- Копирование файлов: Инструкция COPY используется для копирования файлов из локальной директории в образ.
- Установка переменных окружения: Инструкция ENV задает переменные окружения, необходимые для работы приложения в контейнере.
Эффективное использование этих элементов позволяет оптимизировать процесс сборки образа и минимизировать его размер.
Шаг третий: Эффективное использование инструкций Dockerfile
Освоив основы Dockerfile, важно обратить внимание на эффективное использование инструкций для оптимизации процесса создания образа. Инструкции выполняются последовательно, и Docker кеширует промежуточные результаты для ускорения сборки. Однако, при изменении инструкции, кеширование может нарушиться, что влияет на производительность.
Разумное разделение инструкций, установка зависимостей в минимальном количестве слоев и удаление ненужных данных в конце Dockerfile — ключевые моменты для создания эффективных образов.
Работа с образами контейнеров
Загрузка и обмен образами в репозитории Docker
После успешного создания Docker‑образа на локальной машине, встает вопрос его обмена с другими разработчиками или использования в развертывании на удаленных серверах. Для этого используются репозитории Docker, которые предоставляют централизованное хранилище для образов.

Чтобы загрузить образ в репозиторий Docker, используется команда docker push. Перед этим необходимо авторизоваться с учетными данными репозитория. Образ также можно загружать с репозитория на локальную машину с помощью команды docker pull. Это обеспечивает удобный обмен образами между разработчиками и поддерживает прозрачное обновление приложений в продакшене.
Версионирование образов: почему это важно
В мире разработки, где изменения — это норма, версионирование играет ключевую роль. То же самое относится и к Docker‑образам. Версионирование образов позволяет фиксировать состояние приложения в определенный момент времени, что важно для стабильности и воспроизводимости развертывания.
Образ можно пометить версией, используя теги. Например, myapp:1.0 или myapp:latest. Версионирование образов обеспечивает контроль над изменениями и управление разными версиями приложений.
Когда разработчику или системному администратору необходимо обновить приложение, они могут явно указать версию образа, избегая неожиданных изменений, связанных с обновлением до последней версии. Также это упрощает откат к предыдущим версиям в случае необходимости.
Версионирование образов — это практика, которая способствует стабильности и надежности развертывания.
Развертывание приложений с использованием Docker
Подготовка приложения для контейнеризации
Прежде, чем вы приступите к использованию в своей работе Docker для установки ваших приложений, вам следует правильно подготовить само приложение. Применение контейнеров дает преимущество, когда приложение разбито на части, что облегчает управление вложенными в него зависимостями и позволяет выполнять каждую часть изолированно. Каждая составляющая приложения должна быть готова к работе внутри контейнера.
Подготовка включает в себя:
- Определение зависимостей: Убедитесь, что все зависимости приложения установлены и указаны в Dockerfile.
- Конфигурация окружения: Приложение должно быть настроено для использования переменных окружения, что упрощает настройку в контейнере.
- Логика контейнера: Разделите приложение на слои, что обеспечит эффективную работу с Docker‑образами.
Небольшой гайд по работе с Docker Compose: как управлять контейнерными приложениями
Docker Compose — это удобный инструментарий, позволяющий определять и запускать многоконтейнерные приложения. Он использует файл конфигурации YAML для определения сервисов, сетей и других аспектов приложения. Это позволяет определить структуру всего приложения в одном файле.
Процесс использования Docker Compose включает следующие шаги:
- Описание сервисов: файл docker‑compose.yml содержит информацию о всех сервисах, которые нужны для функционирования приложения. В их число могут входить веб‑серверы, базы данных, кэш и т. д.
- Конфигурирование сервисов: для каждого сервиса устанавливаются параметры, например, образ, порты, переменные среды и зависимость от других сервисов.
- Запуск приложения: с помощью команды docker‑compose up Docker Compose создаёт и запускает все контейнеры, которые определены в конфигурационном файле.
- Масштабирование и управление: Docker Compose предоставляет простой способ масштабировать приложение и управлять жизненным циклом контейнеров.
Использовать в своей работе инструмент Docker — это значит во много раз упростить для себя и команды процесс управления и развертывания многоконтейнерных приложений, делая процесс более гибким и масштабируемым.
Заключение
В заключение, рассмотрим основные выгоды использования Docker в современной разработке и взглянем на перспективы развития этой технологии в будущем.
Основные выгоды использования Docker
- Портативность и консистентность: Docker обеспечивает создание образов, которые легко переносятся между средами разработки и продакшена. Это гарантирует консистентность окружений и устраняет проблему «работает у меня на моей машине».
- Эффективность ресурсов: Если сравнивать контейнеры с классическими машинами виртуализации, то они характеризуются более легковесной архитектурой, благодаря чему ресурсы используются грамотно и эффективно, а все процессы развертывания протекают значительно быстрее.
- Изолированное выполнение приложений: Контейнеры — это изолированное исполнение приложений, что гарантирует более высокую степень безопасности и предотвращает всевозможные конфликты между вложенными зависимостями.
- Гибкость и масштабируемость: Docker поддерживает гибкость в управлении ресурсами, а также обеспечивает легкость в масштабировании и управлении многоконтейнерными приложениями.
Перспективы развития технологии в будущем
С развитием технологий и увеличением потребностей в гибких и масштабируемых решениях, Docker продолжает оставаться ключевым инструментом в арсенале разработчика. Ожидается, что в будущем появятся новые функциональности, улучшения в производительности и инструменты управления контейнерами.
Поддержка оркестрации, такая как Kubernetes, становится все более важной, позволяя эффективно управлять кластерами контейнеров. Безопасность контейнеров также будет акцентироваться, с улучшением инструментов анализа уязвимостей и механизмов изоляции.
В целом, Docker не просто современный инструмент, но и основа для создания инновационных и гибких решений в разработке и развертывании приложений. На фоне быстрого развития облачных технологий и микросервисных архитектур, Docker остается востребованным и будет продолжать влиять на ландшафт разработки в течение многих лет вперед.
- контейнеры
- контейнеры docker
- Системное администрирование
- Виртуализация
- DevOps
Начало работы. Запуск первого контейнера Windows
В этой статье объясняется, как запустить первый контейнер Windows после настройки среды, описанной в статье Начало работы. Подготовка Windows для контейнеров. Чтобы запустить контейнер, сначала скачайте (в контейнерах, которые также называются операцией извлечения) базовый образ, который предоставляет базовый уровень служб операционной системы для контейнера. Затем создается и запускается образ контейнера, который основан на базовом образе. Дополнительные сведения см. далее в этой статье.
Извлечение базового образа контейнера
Все контейнеры создаются из образов контейнеров. Корпорация Майкрософт предоставляет для начала работы несколько образов, называемых базовыми образами (дополнительные сведения см. в статье о базовых образах контейнеров). Эти процедуры позволяют получить (скачать и установить) базовый образ Nano Server.
-
Откройте окно командной строки (например, встроенную командную строку, PowerShell или терминал Windows), а затем выполните следующую команду, чтобы скачать и установить базовый образ:
docker pull mcr.microsoft.com/windows/nanoserver:ltsc2022
Если Docker не удается запуститься при попытке извлечь образ, управляющая программа Docker может быть недоступна. Чтобы устранить данную неполадку, попытайтесь перезапустить службу Docker.
Совет Если вы увидите сообщение об ошибке с текстом no matching manifest for linux/amd64 in the manifest list entries , убедитесь, что в Docker не настроен запуск контейнеров Linux. Чтобы переключиться на контейнеры Windows в Docker, щелкните значок Docker правой кнопкой мыши и выберите Переключиться на контейнеры Windows. Чтобы использовать командную строку для переключения между контейнерами, выполните команду & $Env:ProgramFiles\Docker\Docker\DockerCli.exe -SwitchDaemon .
REPOSITORY TAG IMAGE ID CREATED SIZE microsoft/nanoserver latest 105d76d0f40e 4 days ago 652 MB
Выполнение контейнера Windows
В этом простом примере будет создан и развернут образ контейнера «Hello World». Для вашего удобства лучше выполнять эти команды в окне командной строки с повышенными привилегиями. Не используйте интегрированную среду сценариев Windows PowerShell, так как она не работает для интерактивных сеансов с контейнерами и в результате контейнеры перестают отвечать на запросы.
-
Запустите контейнер с интерактивным сеансом из образа nanoserver . Для этого введите следующую команду в окне командной строки:
docker run -it mcr.microsoft.com/windows/nanoserver:ltsc2022 cmd.exe
echo "Hello World!" > Hello.txt exit
docker ps -a
docker commit helloworld
После завершения вы получите пользовательский образ, содержащий скрипт «Привет мир». Это можно проверить с помощью команды docker images.
docker images
Ниже приведен пример выходных данных.
REPOSITORY TAG IMAGE ID CREATED SIZE helloworld latest a1064f2ec798 10 seconds ago 258MB mcr.microsoft.com/windows/nanoserver 2022 2b9c381d0911 3 weeks ago 256MB
docker run --rm helloworld cmd.exe /s /c type Hello.txt
Запуск контейнера Windows с помощью Windows Admin Center
Вы можете использовать Windows Admin Center для локального запуска контейнеров. А именно, вы можете использовать расширение «Контейнеры» своего экземпляра Windows Admin Center для запуска контейнеров. Сначала откройте узел контейнеров, которым требуется управлять, а затем в области «Сервис» выберите расширение Контейнеры. Затем откройте вкладку Образы в расширении «Контейнеры» в разделе Узел контейнеров.

Если базовый образ контейнера отсутствует для узла, выберите вариант Извлечь, чтобы открыть параметры Извлечение образа контейнера:

В разделе Извлечение образа контейнера укажите URL-адрес и тег образа. Если вы не уверены, какой образ нужно извлечь, ознакомьтесь со списком популярных образов от Майкрософт, предоставляемых в Windows Admin Center. Вы также можете указать учетные данные для извлечения образа из частного репозитория. Внеся необходимые сведения, щелкните Извлечь. Windows Admin Center запустит процесс извлечения на узле контейнеров. После завершения скачивания вы увидите новый образ на вкладке Образы.
Выберите образ для запуска и щелкните Запустить.

В меню Запуск настройте конфигурацию для контейнера, например имя контейнера, тип изоляции, порты для публикации, а также выделение памяти и ЦП. Кроме того, вы можете добавить команды запуска Docker, которые недоступны в пользовательском интерфейсе, такие как -v для постоянного тома. Дополнительные сведения о доступных параметрах запуска Docker см. в документации.
Завершив настройку контейнера, щелкните Запустить. Состояние выполняющихся контейнеров можно просмотреть на вкладке Контейнеры:
Dockerfile в Windows
Подсистема Docker содержит средства, автоматизирующие создание образов контейнеров. Хотя образы контейнеров можно создавать вручную с помощью команды docker commit , внедрение процесса автоматического создания образа предоставляет множество преимуществ, в том числе:
- Сохранение образов контейнеров в виде кода.
- Быстрое и точное воссоздание образов контейнеров для обслуживания и обновления.
- Непрерывная интеграция между образами контейнеров и циклом разработки.
За такую автоматизацию отвечают два компонента Docker — файл Dockerfile и команда docker build .
Dockerfile — это текстовый файл с инструкциями, необходимыми для создания образа контейнера. Эти инструкции включают идентификацию существующего образа, используемого в качестве основы, команды, выполняемые в процессе создания образа, и команду, которая будет выполняться при развертывании новых экземпляров этого образа контейнера.
Docker build — команда подсистемы Docker, использующая файл Dockerfile и запускающая процесс создания образа.
В этом разделе рассказывается о том, как использовать файлы Dockerfile с контейнерами Windows, а также объясняются наиболее распространенные инструкции и базовый синтаксис таких файлов.
Здесь также рассматривается концепция образов контейнеров и их слоев. Дополнительные сведения об образах и их слоях см. в документации по базовым образам контейнеров.
Полный обзор файлов Dockerfile см. в справке по Dockerfile на странице .
Базовый синтаксис
В исходной форме файл Dockerfile может быть очень простым. Следующий пример создает образ, включающий IIS и сайт «hello world». Этот пример включает комментарии (обозначенные с помощью # ), поясняющие каждый шаг. В последующих разделах этой статьи более подробно рассматриваются правила синтаксиса Dockerfile и инструкции Dockerfile.
Файл Dockerfile необходимо создавать без расширения. Чтобы сделать это в Windows, создайте файл с помощью удобного для вас редактора, а затем сохраните его, используя нотацию «Dockerfile» (вместе с кавычками).
# Sample Dockerfile # Indicates that the windowsservercore image will be used as the base image. FROM mcr.microsoft.com/windows/servercore:ltsc2019 # Metadata indicating an image maintainer. LABEL maintainer="jshelton@contoso.com" # Uses dism.exe to install the IIS role. RUN dism.exe /online /enable-feature /all /featurename:iis-webserver /NoRestart # Creates an HTML file and adds content to this file. RUN echo "Hello World - Dockerfile" > c:\inetpub\wwwroot\index.html # Sets a command or process that will run each time a container is run from the new image. CMD [ "cmd" ]
Дополнительные примеры файлов Dockerfile для Windows см. в репозитории файлов Dockerfile для Windows.
Instructions
Инструкции Dockerfile дают подсистеме Docker необходимые указания для создания образа контейнера. Эти инструкции выполняются по очереди, одна за другой. Ниже приведены примеры наиболее часто используемых инструкций в файлах Dockerfile. Полный список инструкций Dockerfile см. в справочнике по файлам Dockerfile.
FROM
Инструкция FROM задает образ контейнера, который будет применяться при создании нового образа. Например, при использовании инструкции FROM mcr.microsoft.com/windows/servercore полученный образ является производным и зависимым от базового образа ОС Windows Server Core. Если указанный образ отсутствует в системе, где выполняется процесс сборки Docker, подсистема Docker попытается скачать его из общедоступного или частного реестра образов.
Формат инструкции FROM выглядит следующим образом:
FROM
Ниже приведен пример команды FROM.
Чтобы загрузить Windows Server Core версии ltsc2019 из Реестра контейнеров (Майкрософт):
FROM mcr.microsoft.com/windows/servercore:ltsc2019
ВЫПОЛНИТЬ
Инструкция RUN задает команды, которые следует выполнить и поместить в новый образ контейнера. Эти команды могут включать такие элементы, как установка программного обеспечения, создание файлов и папок, а также создание конфигурации среды.
Инструкция RUN выглядит следующим образом:
# exec form RUN ["", "", ""] # shell form RUN
Различие между формой исполняемого файла (exec form) и формой оболочки (shell form) заключается в способе выполнения инструкции RUN . При использовании формы исполняемого файла указанная программа запускается явным образом.
Ниже приведен пример формы исполняемого файла.
FROM mcr.microsoft.com/windows/servercore:ltsc2019 RUN ["powershell", "New-Item", "c:/test"]
Полученный образ выполняет команду powershell New-Item c:/test :
docker history doc-exe-method IMAGE CREATED CREATED BY SIZE COMMENT b3452b13e472 2 minutes ago powershell New-Item c:/test 30.76 MB
В отличие от предыдущего примера здесь та же операция выполняется с использованием формы оболочки:
FROM mcr.microsoft.com/windows/servercore:ltsc2019 RUN powershell New-Item c:\test
Полученный образ содержит инструкцию RUN cmd /S /C powershell New-Item c:\test .
docker history doc-shell-method IMAGE CREATED CREATED BY SIZE COMMENT 062a543374fc 19 seconds ago cmd /S /C powershell New-Item c:\test 30.76 MB
Рекомендации по использованию инструкции RUN с Windows
В Windows при использовании инструкции RUN в формате исполняемого файла необходимо экранировать инструкции символы обратной косой черты.
RUN ["powershell", "New-Item", "c:\\test"]
Если целевая программа является установщиком Windows, чтобы запустить фактическую процедуру (автоматической) установки, необходимо извлечь программу установки, используя флаг /x: . Прежде чем выполнять какие-либо другие действия, необходимо дождаться завершения выполнения команды. В противном случае процесс будет завершен преждевременно и без установки. Дополнительные сведения см. в приведенном ниже примере.
Примеры использования инструкции RUN с Windows
В следующем примере для установки служб IIS в образе контейнера используется система DISM.
RUN dism.exe /online /enable-feature /all /featurename:iis-webserver /NoRestart
Этот пример устанавливает распространяемый пакет Visual Studio. Start-Process и параметр -Wait используются для запуска программы установки. Это гарантирует, что установка будет завершена до перехода к следующей инструкции в Dockerfile.
RUN powershell.exe -Command Start-Process c:\vcredist_x86.exe -ArgumentList '/quiet' -Wait
Подробные сведения об инструкции RUN см. в справочнике по RUN на странице .
КОПИРОВАТЬ
Инструкция COPY копирует файлы и каталоги в файловую систему контейнера. Эти файлы и каталоги должны иметь путь, являющийся относительным для Dockerfile.
Формат инструкции COPY выглядит следующим образом:
COPY
Если источник или назначение содержит пробел, заключите путь в квадратные скобки и двойные кавычки, как показано в следующем примере:
COPY ["", ""]
Рекомендации по использованию инструкции COPY с Windows
В Windows для путей назначения необходимо использовать символы косой черты. Например, здесь показаны допустимые инструкции COPY .
COPY test1.txt /temp/ COPY test1.txt c:/temp/
При этом следующий формат с обратными косыми чертами работать не будет:
COPY test1.txt c:\temp\
Примеры использования инструкции COPY с Windows
В следующем примере содержимое исходного каталога добавляется в каталог с именем sqllite в образе контейнера.
COPY source /sqlite/
В следующем примере все файлы, начинающиеся с config, добавляют в каталог c:\temp образа контейнера.
COPY config* c:/temp/
Дополнительные сведения об инструкции COPY см. в справочнике по инструкции COPY.
ADD
Инструкция ADD похожа на инструкцию COPY, но с дополнительными возможностями. Кроме копирования файлов с узла в образ контейнера, инструкция ADD также позволяет скопировать файлы из удаленного расположения с помощью задания URL-адреса.
Формат инструкции ADD выглядит следующим образом:
Если источник или назначение содержит пробел, заключите путь в квадратные скобки и двойные кавычки.
Рекомендации по выполнению инструкции ADD с Windows
В Windows для путей назначения необходимо использовать символы косой черты. Например, здесь показаны допустимые инструкции ADD .
ADD test1.txt /temp/ ADD test1.txt c:/temp/
При этом следующий формат с обратными косыми чертами работать не будет:
ADD test1.txt c:\temp\
Кроме того, в системе Linux во время копирования инструкция ADD распаковывает сжатые пакеты. В Windows эта функция недоступна.
Примеры использования инструкции ADD с Windows
В следующем примере содержимое исходного каталога добавляется в каталог с именем sqllite в образе контейнера.
ADD source /sqlite/
В следующем примере все файлы, начинающиеся с «config», добавляют в каталог c:\temp образа контейнера.
ADD config* c:/temp/
В этом примере Python для Windows скачивается в каталог c:\temp образа контейнера.
ADD https://www.python.org/ftp/python/3.5.1/python-3.5.1.exe /temp/python-3.5.1.exe
Дополнительные сведения об инструкции ADD см. в справочнике по инструкции ADD.
WORKDIR
Инструкция WORKDIR задает рабочий каталог для других инструкций Dockerfile, например RUN и CMD , а также рабочий каталог для запущенных экземпляров образа контейнера.
Формат инструкции WORKDIR выглядит следующим образом:
WORKDIR
Рекомендации по использованию инструкции WORKDIR с Windows
Если в Windows рабочий каталог содержит обратную косую черту, ее следует экранировать.
WORKDIR c:\\windows
Примеры
WORKDIR c:\\Apache24\\bin
Подробные сведения об инструкции WORKDIR см. в справочнике по WORKDIR.
CMD
Инструкция CMD задает команду по умолчанию, выполняемую при развертывании экземпляра образа контейнера. Например, если в контейнере будет размещен веб-сервер NGINX, CMD может включать инструкции для запуска этого веб-сервера, например с помощью команды nginx.exe . Если в файле Dockerfile указано несколько инструкций CMD , вычисляется только последняя из них.
Формат инструкции CMD выглядит следующим образом:
# exec form CMD [""] # shell form CMD
Рекомендации по использованию инструкции CMD с Windows
В Windows для путей к файлам, указанным в инструкции CMD , следует использовать символы косой черты или экранировать символы обратной косой черты \\ . Допустимы следующие инструкции CMD :
# exec form CMD ["c:\\Apache24\\bin\\httpd.exe", "-w"] # shell form CMD c:\\Apache24\\bin\\httpd.exe -w
Однако следующий формат без соответствующих косых черт работать не будет:
CMD c:\Apache24\bin\httpd.exe -w
Дополнительные сведения об инструкции CMD см. в справочнике по инструкции CMD.
Escape-символ
Во многих случаях инструкция Dockerfile должна занимать несколько строк. Для этого можно использовать escape-символ. Escape-символ Dockerfile по умолчанию — обратная косая черта ( \ ). Однако, поскольку обратная косая черта также является разделителем пути к файлу в Windows, использование его для разделения нескольких строк может вызвать проблемы. Чтобы их избежать, можно изменить escape-символ по умолчанию с помощью директивы анализатора. Дополнительные сведения о директивах анализатора см. в этом разделе.
В следующем примере показана инструкция RUN, которая занимает несколько строк и использует escape-символ по умолчанию.
FROM mcr.microsoft.com/windows/servercore:ltsc2019 RUN powershell.exe -Command \ $ErrorActionPreference = 'Stop'; \ wget https://www.python.org/ftp/python/3.5.1/python-3.5.1.exe -OutFile c:\python-3.5.1.exe ; \ Start-Process c:\python-3.5.1.exe -ArgumentList '/quiet InstallAllUsers=1 PrependPath=1' -Wait ; \ Remove-Item c:\python-3.5.1.exe -Force
Чтобы изменить escape-символ, поместите директиву Parser для escape-символа на первую строку Dockerfile. Это показано в следующем примере.
В качестве escape-символов можно использовать только символы: \ и ` .
# escape=` FROM mcr.microsoft.com/windows/servercore:ltsc2019 RUN powershell.exe -Command ` $ErrorActionPreference = 'Stop'; ` wget https://www.python.org/ftp/python/3.5.1/python-3.5.1.exe -OutFile c:\python-3.5.1.exe ; ` Start-Process c:\python-3.5.1.exe -ArgumentList '/quiet InstallAllUsers=1 PrependPath=1' -Wait ; ` Remove-Item c:\python-3.5.1.exe -Force
Дополнительные сведения о директиве анализатора для escape-символа см. в этом разделе.
PowerShell в Dockerfile
Командлеты PowerShell
Командлеты PowerShell можно выполнять в Dockerfile при помощи операции RUN .
FROM mcr.microsoft.com/windows/servercore:ltsc2019 RUN powershell -command Expand-Archive -Path c:\apache.zip -DestinationPath c:\
Вызовы REST
При сборе данных или файлов из веб-службы удобно использовать командлет PowerShell Invoke-WebRequest . Например, при сборке образа, включающего Python, можно задать для $ProgressPreference значение SilentlyContinue , чтобы ускорить загрузку, как показано в следующем примере.
FROM mcr.microsoft.com/windows/servercore:ltsc2019 RUN powershell.exe -Command \ $ErrorActionPreference = 'Stop'; \ $ProgressPreference = 'SilentlyContinue'; \ Invoke-WebRequest https://www.python.org/ftp/python/3.5.1/python-3.5.1.exe -OutFile c:\python-3.5.1.exe ; \ Start-Process c:\python-3.5.1.exe -ArgumentList '/quiet InstallAllUsers=1 PrependPath=1' -Wait ; \ Remove-Item c:\python-3.5.1.exe -Force
Invoke-WebRequest также работает на сервере Nano Server.
Кроме того, при помощи PowerShell можно скачивать файлы во время создания образа, используя библиотеку .NET WebClient. Это может повысить производительность скачивания. Следующий пример скачивает программное обеспечение Python, используя библиотеку WebClient.
FROM mcr.microsoft.com/windows/servercore:ltsc2019 RUN powershell.exe -Command \ $ErrorActionPreference = 'Stop'; \ (New-Object System.Net.WebClient).DownloadFile('https://www.python.org/ftp/python/3.5.1/python-3.5.1.exe','c:\python-3.5.1.exe') ; \ Start-Process c:\python-3.5.1.exe -ArgumentList '/quiet InstallAllUsers=1 PrependPath=1' -Wait ; \ Remove-Item c:\python-3.5.1.exe -Force
Сейчас Nano Server не поддерживает WebClient.
Сценарии PowerShell
В некоторых случаях удобно скопировать крипт в контейнеры, используемые при создании образа, и затем запустить его из контейнера.
Это ограничивает возможности кэширования слоев образов, а также ухудшает удобочитаемость файла Dockerfile.
Этот пример копирует сценарий с компьютера сборки в контейнер с помощью инструкции ADD . Затем этот сценарий выполняется с помощью инструкции RUN.
FROM mcr.microsoft.com/windows/servercore:ltsc2019 ADD script.ps1 /windows/temp/script.ps1 RUN powershell.exe -executionpolicy bypass c:\windows\temp\script.ps1
Команда Docker build
После создания файла Dockerfile и сохранения его на диск можно запустить docker build для создания нового образа. Команда docker build принимает несколько необязательных параметров и путь к файлу Dockerfile. Полную документацию по команде Docker build, включая список всех параметров сборки, см. в справочнике по сборке.
Формат команды docker build выглядит следующим образом:
docker build [OPTIONS] PATH
Например, следующая команда создает образ с именем «iis».
docker build -t iis .
При инициации процесса сборки в выходных данных указывается состояние и выводятся все возникающие ошибки.
C:\> docker build -t iis . Sending build context to Docker daemon 2.048 kB Step 1 : FROM mcr.microsoft.com/windows/servercore:ltsc2019 ---> 6801d964fda5 Step 2 : RUN dism /online /enable-feature /all /featurename:iis-webserver /NoRestart ---> Running in ae8759fb47db Deployment Image Servicing and Management tool Version: 10.0.10586.0 Image Version: 10.0.10586.0 Enabling feature(s) The operation completed successfully. ---> 4cd675d35444 Removing intermediate container ae8759fb47db Step 3 : RUN echo "Hello World - Dockerfile" > c:\inetpub\wwwroot\index.html ---> Running in 9a26b8bcaa3a ---> e2aafdfbe392 Removing intermediate container 9a26b8bcaa3a Successfully built e2aafdfbe392
В результате создается новый образ контейнера, который в этом примере носит имя «iis».
docker images REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE iis latest e2aafdfbe392 About a minute ago 207.8 MB windowsservercore latest 6801d964fda5 4 months ago 0 B
Дополнительные материалы и справочники
- Оптимизация файлов Dockerfile и сборка команды Docker build для Windows
- Справочник по Dockerfile
Docker. Начало

Примерно такие же эмоции я и мои коллеги испытывали, когда начинали работать с Docker. В подавляющем большинстве случаев это происходило от недостатка понимания основных механизмов, поэтому его поведение казалось нам непредсказуемым. Сейчас страсти поутихли и вспышки ненависти происходят все реже и все слабее. Более того, постепенно мы на практике оцениваем его достоинства и он начинает нам нравиться… Чтобы снизить степень первичного отторжения и добиться максимального эффекта от использования, нужно обязательно заглянуть на кухню Docker’a и хорошенько там осмотреться.
Начнем с того, для чего же нам нужен Docker:
- изолированный запуск приложений в контейнерах
- упрощение разработки, тестирования и деплоя приложений
- отсутствие необходимости конфигурировать среду для запуска — она поставляется вместе с приложением — в контейнере
- упрощает масштабируемость приложений и управление их работой с помощью систем оркестрации контейнеров.
Предыстрория
Для изоляции процессов, запущенных на одном хосте, запуска приложений, предназначенных для разных платформ, можно использовать виртуальные машины. Виртуальные машины делят между собой физические ресурсы хоста:

- процессор,
- память,
- дисковое пространство,
- сетевые интерфейсы.
На каждой ВМ устанавливаем нужную ОС и запускаем приложения. Недостатком такого подхода является то, что значительная часть ресурсов хоста расходуется не на полезную нагрузку(работа приложений), а на работу нескольких ОС.
Контейнеры
Альтернативным подходом к изоляции приложений являются контейнеры. Само понятие контейнеров не ново и давно известно в Linux. Идея состоит в том, чтобы в рамках одной ОС выделить изолированную область и запускать в ней приложение. В этом случае говорим о виртуализации на уровне ОС. В отличие от ВМ контейнеры изолированно используют свой кусочек ОС:

- файловая система
- дерево процессов
- сетевые интерфейсы
- и др.
Т.о. приложение, запущенное в контейнере думает, что оно одно во всей ОС. Изоляция достигается за счет использования таких Linux-механизмов, как namespaces и control groups. Если говорить просто, то namespaces обеспечивают изоляцию в рамках ОС, а control groups устанавливают лимиты на потребление контейнером ресурсов хоста, чтобы сбалансировать распределение ресурсов между запущенными контейнерами.
Т.о. контейнеры сами по себе не являются чем-то новым, просто проект Docker, во-первых, скрыл сложные механизмы namespaces, control groups, а во-вторых, он окружен экосистемой, обеспечивающей удобное использование контейнеров на всех стадиях разработки ПО.
Образы
Образ в первом приближении можно рассматривать как набор файлов. В состав образа входит все необходимое для запуска и работы приложения на голой машине с докером: ОС, среда выполнения и приложение, готовое к развертыванию.
Но при таком рассмотрении возникает вопрос: если мы хотим использовать несколько образов на одном хосте, то будет нерационально как с точки зрения загрузки, так и с точки зрения хранения, чтобы каждый образ тащил все необходимое для своей работы, ведь большинство файлов будут повторяться, а различаться — только запускаемое приложение и, возможно, среда выполнения. Избежать дублирования файлов позволяет структура образа.
Образ состоит из слоев, каждый из которых представляет собой неизменяемую файловую систему, а по-простому набор файлов и директорий. Образ в целом представляет собой объединенную файловую систему (Union File System), которую можно рассматривать как результат слияния файловых систем слоев. Объединенная файловая система умеет обрабатывать конфликты, например, когда в разных слоях присутствуют файлы и директории с одинаковыми именами. Каждый следующий слой добавляет или удаляет какие то файлы из предыдущих слоев. В данном контексте «удаляет» можно рассматривать как «затеняет», т.е. файл в нижележащем слое остается, но его не будет видно в объединенной файловой системе.
Можно провести аналогию с Git: слои — это как отдельные коммиты, а образ в целом — результат выполнения операции squash. Как мы увидим дальше, на этом параллели с Git не заканчиваются. Существуют различные реализации объединенной файловой системы, одна из них — AUFS.
Для примера рассмотрим образ произвольного .NET приложения MyApplication: первым слоем является ядро Linux, далее следуют слои ОС, среды исполнения и уже самого приложения.

Слои являются read only и, если в слое MyApplication нужно изменить файл, находящийся в слое dotnet, то файл сначала копируется в нужный слой, а потом в нем изменяется, оставаясь в исходном слое в первозданном виде.

Неизменяемость слоев позволяет использовать их всеми образами на хосте. Допустим MyApplication — это веб-приложение, которое использует БД и взаимодействует также с NodeJS сервером.

Совместное использование проявляется также и при скачивании образа. Первым загружается манифест, который описывает какие слои входят в образ. Далее скачиваются только те слои из манифеста, которых еще нет локально. Т.о. если мы для MyApplication уже скачали ядро и ОС, то для PostgreSQL и Node.js эти слои уже загружаться не будут.
- Образ — это набор файлов, необходимых для работы приложения на голой машине с установленным Docker.
- Образ состоит из неизменяемых слоев, каждый из которых добавляет/удаляет/изменяет файлы из предыдущего слоя.
- Неизменяемость слоев позволяет их использовать совместно в разных образах.
Docker-контейнеры
Docker-контейнер строится на основе образа. Суть преобразования образа в контейнер состоит в добавлении верхнего слоя, для которого разрешена запись. Результаты работы приложения (файлы) пишутся именно в этом слое.

Например, мы создали на основе образа с PostgreSQL сервером контейнер и запустили его. Когда мы создаем БД, то соответствующие файлы появляются в верхнем слое контейнера — слое для записи.

Можно провести и обратную операцию: из контейнера сделать образ. Верхний слой контейнера отличается от остальных только лишь разрешением на запись, в остальном это обычный слой — набор файлов и директорий. Делая верхний слой read only, мы преобразуем контейнер в образ.

Теперь я могу перенести образ на другую машину и запустить. При этом на сервере PostgreSQL можно будет увидеть БД, созданные на предыдущем этапе. Когда при работе контейнера будут внесены изменения, то файл БД будет скопирован из неизменяемого слоя с данными в слой для записи и там уже измененен.

Docker
Когда мы устанавливаем докер на локальную машину, то получаем клиент (CLI) и http-сервер, работающий как демон. Сервер предоставляет REST API, а консоль просто преобразует введенные команды в http-запросы.

Registry
Registry — это хранилище образов. Самым известным является DockerHub. Он напоминает GitHub, только содержит образы, а не исходный код. На DockerHub также есть репозитории, публичные и приватные, можно скачивать образы (pull), заливать изменения образов (push). Скачанные однажды образы и собранные на их основе контейнеры хранятся локально, пока не будут удалены вручную.

Существует возможность создания своего хранилища образов, тогда при необходимости Docker будет искать там образы, которых еще нет локально. Надо сказать, что при использовании Docker хранилище образов становится важнейшим звеном в CI/CD: разработчик делает коммит в репозиторий, запускаются тесты. Если тесты прошли успешно, то на основе коммита обновляется существующий или собирается новый образ с последующим деплоем. Причем в registry обновляются не целые образы, а только необходимые слои.

При этом важно не ограничивать восприятие образа как некой коробки в которой приложение просто доставляется до пункта назначения и потом запускается. Приложение может и собираться внутри образа (правильнее сказать внутри контейнера, но об этом чуть позже). На схеме выше сервер, занимающийся сборкой образов, может иметь только установленный Docker, а не различные среды, платформы и приложения, необходимые для сборки разных компонентов нашего приложения.
Dockerfile
Dockerfile представляет собой набор инструкций, на основе которых строится новый образ. Каждая инструкция добавляет новый слой к образу. Для примера рассмотрим Dockerfile, на основе которого мог бы быть создан образ рассмотренного ранее .NET-приложения MyApplication:
FROM microsoft/aspnetcore WORKDIR /app COPY bin/Debug/publish . ENTRYPOINT["dotnet", "MyApplication.dll"]
Рассмотрим отдельно каждую инструкцию:
- определяем базовый образ, на основе которого будем строить свой. В данном случае берем microsoft/aspnetcore — официальный образ от Microsoft, который можно найти на DockerHub
- задаем рабочую директорию внутри образа
- копируем предварительно спаблишенное приложение MyApplication в рабочую директорию внутри образа. Сначала пишется исходная директория — путь относительно контекста, указанного в команде docker build , а вторым аргументом — целевая директория внутри образа, в данном случае точка обозначает рабочую директорию
- конфигурируем контейнер как исполняемый: в нашем случае для запуска контейнера будет выполнена команда dotnet MyApplication.dll

Рассмотрим еще один Dockerfile, который демонстрирует прекрасную возможность Docker, обеспечивающую легковесность образов. Подобный файл генерирует VisualStudio 2017 для проекта с поддержкой контейнеров и он позволяет собирать образ из исходного кода приложения.
FROM microsoft/aspnetcore-build:2.0 AS publish WORKDIR /src COPY . . RUN dotnet restore RUN dotnet publish -o /publish FROM microsoft/aspnetcore:2.0 WORKDIR /app COPY --from=publish /publish . ENTRYPOINT ["dotnet", "MyApplication.dll"]
Инструкции в файле разбиты на две секции:
- Определение образа для сборки приложения: microsoft/aspnetcore-build. Данный образ предназначен для сборки, паблиша и запуска .NET приложений и согласно DockerHub с тегом 2.0 имеет размер 699 MB. Далее происходит копирование исходных файлов приложения внутрь образа и внутри него выполняются команды dotnet restore и dotnet publish с размещением результатов в директории /publish внутри образа.
- Определяется базовый образ, в данном случае это microsoft/aspnetcore, который содержит в себе только среду исполнения и согласно DockerHub с тегом 2.0 имеет размер всего 141 MB. Далее определяется рабочая директория и в нее копируется результат предыдущей стадии (ее имя указывается в аргументе —from ), определяется команда запуска контейнера и все — образ готов.
Напоследок хочу отметить, что намеренно для простоты оперировал понятием образ, рассматривая работу с Dockerfile. На самом деле изменения, вносимые каждой инструкцией происходят конечно же не в образе (ведь в нем только неизменяемые слои), а в контейнере. Механизм такой: из базового образа создается контейнер (добавляется ему слой для записи), выполняется инструкция в данном слое (она может добавлять файлы в слой для записи: COPY или нет: ENTRYPOINT ), вызывается команда docker commit и получается образ. Процесс создания контейнера и коммита в образ повторяется для каждой инструкции в файле. В итоге в процессе формирования конечного образа создается столько промежуточных образов и контейнеров, сколько инструкций в файле. Все они автоматически удаляются после окончания сборки конечного образа.
Заключение
Конечно же Docker не панацея и его использование должно быть оправдано и мотивировано не только желанием использовать современную технологию, о которой многие говорят. При этом я уверен, что Docker, примененный грамотно и к месту, может принести много пользы на всех стадиях разработки ПО и облегчить жизнь всем участникам процесса.
Надеюсь смог раскрыть базовые моменты и заинтересовать к дальнейшему изучению вопроса. Конечно же для овладения Docker одной этой статьи недостаточно, но, надеюсь, она станет одним из элементов пазла для осознания общей картины происходящего в мире контейнеров под управлением Docker.
Ссылки
- Документация Docker
- Механизм namespaces
- Механизм control groups
- Статья о Docker
- Docker
- Linux контейнеры