Содержание:
-
1.
Предыстория -
2.
Windows контейнер -
3.
В мире контейнеров Windows -
4.
Связь с Docker -
5.
Мир Windows
Начиная с Windows Server 2016 в операционной системе от Microsoft включена нативная поддержка контейнеров. Это не Linux контейнеры, это контейнеры, которые работают на Windows, и запускают Windows внутри себя.
Данный факт является результатом присоединения Microsoft к Open Container Initiative (OCI). Контейнеры в Windows позволяют запускать приложения, которые изолированы от остальной части системы в переносимых контейнерах. Эти контейнеры включают в себя все, чтобы ваше приложение было полностью функциональным. Так же как это произошло с Linux, Microsoft надеется, что контейнеры изменят характер поставки программного обеспечения для пользователей и в Windows.
Предыстория
Контейнеры являлись основой вычислений в Linux в течение целого ряда лет. Google, например, уже очень давно использует решения, основанные на контейнерах по всей своей империи, чтобы предоставлять распределенные приложения не только своим сотрудникам, но и своим пользователям по всему миру.
Тем не менее, Google не был долгое время одинок в своем увлечении контейнерными вычислениями. В какой-то момент из ниоткуда появился Docker, который в отличии от Google стандартизировал процессы доставки контейнеров, а также управления ими. Более того, Docker развивался сообществом энтузиастов в мире открытого исходного кода, что сделало его простым и очень популярным решением. С развитием проекта Docker буквально у каждого желающего появилась возможность получить скорость, гибкость и простоту управления программным обеспечением и инфраструктурой, которую предоставляют контейнеры.
Docker революция стала настолько значительной, что даже Microsoft присоединился к этой инициативе в первую очередь за счет поддержки Docker и Linux в Azure, а теперь и за счет интеграции этой технологии в Windows Server 2016. Самое интересное это то, что контейнеры Windows Server не основаны на Linux, это нечто совершенно новое. Windows контейнеры — это контейнеры, которые работают в Windows и запускают Windows внутри себя.
Причем Microsoft настолько серьезно стала относится к контейнерам, что сейчас активно участвует в Open Container Initiative (OCI), пытаясь перетягивать одеяло на себя так, как будто бы она сама придумала эту технологию.
Windows контейнер
Контейнер в Windows имеет много общего с его аналогом в Linux. Оба обеспечивают изолированную среду для запуска приложений. И там и там контейнеры используют передовые технологии изоляции для обеспечения портативной, но одновременно ограниченной среды, которая включает в себя практически все, чтобы приложение могло быть полностью функциональным.
Контейнер очень похож на виртуальную машину (ВМ) и часто рассматривается как отдельный тип виртуализации, но это два совершенно разные понятия. Да, каждый работает под управлением операционной системы (ОС), предоставляет внутри себя локальную файловую систему и может быть доступен по сети так же как физический компьютер. Тем не менее, при использовании ВМ вы имеете дело с полной и независимой ОС вместе с виртуальными драйверами устройств, управлением памятью и другими компонентами, которые добавляют к накладные расходы.
Контейнер переиспользует большее количество общих ресурсов хост-системы нежели виртуальная машина, а значит, он более легкий, быстрее разворачивается и проще масштабируется между различными датацентрами. Таким образом, контейнер может предложить более эффективный механизм для инкапсулирования приложения, обеспечивая ему при этом необходимые интерфейсы хост-системы — все из этого приводит к более эффективному использованию ресурсов и улучшению переносимости приложений.
Microsoft планирует предложить два типа контейнеров в Windows Server 2016: контейнер Windows Server и Hyper-V контейнер. Оба типа функционируют одинаковым образом, и могут быть созданы и управляются одинаково. Там, где они различаются — это в уровне изоляции, который каждый из них обеспечивает.
Контейнер Windows Server разделяет ядро с ОС работает на хост-машине, что означает, что все контейнеры, работающие на этой машине, разделяют одно и то же ядро. В то же время, каждый контейнер поддерживает свой собственный вид на операционную систему, реестр, файловую систему, IP-адреса и другие компоненты, сочетая это с изоляцией, предоставляемой каждому контейнеру при помощи процессов, пространства имен и технологий управления ресурсами.
Контейнер Windows Server хорошо подходит для ситуаций, в которых и основная ОС, и приложения в контейнерах лежат в пределах той же зоны доверия, например для приложений, которые охватывают несколько контейнеров или образуют общую службу. Тем не менее, контейнеры Windows Server обсуждаются в связи с их зависимостью от процесса обновления ОС хост-системы, который может осложнить обслуживание и препятствовать процессам. Например, патч примененный к хосту может сломать приложение, работающее в контейнере. Что еще более важно, в таких ситуациях, как многопользовательские среды, модель разделяемого ядра может раскрыть систему для уязвимостей приложений и кросс-контейнерных атак.
Hyper-V контейнер решает эти проблемы, предоставляя виртуальную машину, в которой нужно запустить контейнер Windows. При таком подходе контейнер больше не разделяет ядро хост-машины и не имеет зависимости от патчей ОС этой машины. Конечно, такой подход означает некоторую потерю скорости и эффективности упаковки, которые вы получаете с обычным контейнером в Windows Server, но взамен вы получаете более изолированную и безопасную среду.
Вне зависимости от типа контейнера, который вы используете, теперь у вас есть возможность использовать контейнеры с такими технологиями Windows как .NET или PowerShell, что не было возможно раньше. Контейнер для Windows предоставляет все необходимое для обеспечения работы приложения на любом компьютере под управлением Windows Server 2016, давая вам тот уровень переносимости, который был не доступен на протяжении большей части истории Windows. Вы можете создавать свои контейнеры локально, делать их доступными процессов для тестирования и контроля качества, а затем отправить их в команде, занимающейся продуктивом, без необходимости беспокоиться о сложных установках и конфигурациях на каждом шаге этого пути.
В мире контейнеров Windows
Ряд компонентов принимают участие в процессе создании и запуска контейнеров, начиная с хоста, на котором они должны работать. Хост может быть как физическим компьютером, так и ВМ с Windows 2016 Server. Единственное, что важно, чтобы была включена функция контейнеризации для Windows.
Вы можете разместить контейнеры на любой версии Windows: Server Full UI или же Core, которая устанавливается по умолчанию. Microsoft также представляет Nano издание для Windows Server 2016 — минимальную версию ОС, которая не включает в себя локальный графический пользовательский интерфейс или консоль.
Microsoft также добавила вложенную виртуализацию для Windows Server 2016, так что вы можете запустить Hyper-V контейнеры, если хостом является ВМ. Если вы планируете запускать такой тип контейнера, необходимо включить функцию Hyper-V на хост-ОС. Microsoft также добавляет поддержку контейнера для Windows 10, хотя только для Hyper-V контейнеров.
Как и с контейнерами Docker, вы разворачиваете контейнеры для Windows из образов. Каждый образ начинается с образа ОС контейнера — базового образа, включающего в себя операционную систему, которая будет работать внутри контейнера. В настоящее время Microsoft предоставляет два базовых образа: образ Server Core и образ Nano Server. Вы должны загрузить хотя бы один из этих образов ОС от Microsoft, прежде чем сможете развернуть контейнер.
Microsoft строго определяет, какие образы вы можете использовать с каким типом контейнера на основании хост-ОС, как описано в следующей таблице.
Хост-ОС |
Контейнер Windows Server |
Контейнер Hyper-V |
Windows Server Full UI |
Образ Server Core |
Образ Nano Server |
Windows Server Core |
Образ Server Core |
Образ Nano Server |
Windows Server Nano |
Образ Nano Server |
Образ Nano Server |
Windows 10 |
N/A |
Образ Nano Server |
Как вы можете видеть, Hyper-V контейнеры в настоящее время поддерживают только образ Nano сервера, но ваш выбор контейнеров Windows Server зависит от того, с какой версией Windows Server вы работаете.
Для этого типа контейнера, образ ОС должен также соответствовать хост-системы в отношении сборки и уровня обновления. Несоответствие может привести к непредсказуемому поведению как для контейнера, так и хоста. Это означает, что вы должны обновить образ базового контейнера ОС при обновлении ОС хоста. Это также означает, что вы не будете иметь возможность запускать Linux контейнер на Windows машине, или наоборот, и это также верно для Hyper-V контейнеров.
Образы обеспечивают высокую степень гибкости, когда речь идет о развертывании контейнеров. Вы можете создавать образы на основе существующего образа и обновлять новые образы так часто, как это необходимо. После этого вы можете развернуть один или несколько контейнеров из этого образа.
Например, предположим, что вы создаете образ, основанный на Server Core. В новый образ, вы устанавливаете приложение, которое в настоящее время находится в разработке вместе со всеми зависимостями этого приложения. Затем вы можете развернуть один или несколько контейнеров из этого образа. Каждый контейнер функционирует как песочница, которая включает все компоненты, необходимые для полной работоспособности приложения.
Образ может быть развернут так часто, как это необходимо, а также совместно использоваться любым количеством контейнеров. Вы создаете контейнеры по мере необходимости, а затем избавляетесь от них, когда вы с ними закончите. Но лучше всего то, что вы можете обновить и повторно развернуть образ в любое время, а затем создать из него новые контейнеры, которые содержат последние изменения.
Вам не нужно выбирать тип контейнера (Windows Server или Hyper-V) до тех пор, пока вы не будете готовы запустить фактический контейнер. Тип контейнера не имеет никакого отношения к тому, как вы собираете ваши образы. Образы хранятся в репозитории и доступны по запросу для разворачивания контейнеров, где и когда они необходимы, будь то контейнеры Windows Server или Hyper-V.
Связь с Docker
Помимо компании, Docker также является проектом с открытым кодом, которая облегчает процесс развертывания и управления контейнерами. Контейнеры Windows теперь являются частью этого проекта, и сообщество Docker интенсивно работает, чтобы полностью интегрировать контейнеры Windows в экосистему Docker. В рамках этой же инициативы Docker предлагает Docker Engine для Windows, и Docker Client для Windows.
Docker Engine обеспечивает функциональность, необходимую для управления Docker окружением. Например, Docker Engine позволяет автоматизировать создание контейнеров из образов. Хотя вы можете создавать образы вручную, Docker Engine предлагает целый ряд преимуществ, т.к. возможность хранения образов как кода, легкого пересоздания этих образов или включения их в цикл непрерывной интеграции в процессе разработки.
Тем не менее, Docker Engine не является частью установки Windows. Вы должны загрузить, установить и настроить его отдельно от Windows. Docker Engine работает как служба Windows. Можно настроить эту службу, используя файл конфигурации или Windows Service Control Manager (SCM). Например, вы можете установить отладку по умолчанию и параметры журнала или настроить, как Docker Engine принимает сетевые запросы. Microsoft рекомендует использовать файл конфигурации, а не SCM, но отмечает, что не каждый параметр конфигурации в файле применим к контейнерам Windows.
Docker Engine по существу делает всю рутинную работу по управлению контейнером за вас, расширяя API, необходимый для клиента Docker для взаимодействия Docker Engine. Клиент представляет собой интерфейс командной строки, который предоставляет набор команд для управления образами и контейнерами. Это те же самые команды, которые позволяют создавать и запускать контейнеры Docker в Linux. Хотя вы и не можете запустить контейнер для Windows на Linux или контейнер Linux на Windows, вы можете использовать один и тот же клиент для управления как Linux и Windows контейнерами, будь то контейнеры Windows Server или Hyper-V.
Как и с Docker Engine, вам необходимо загрузить и установить клиент Docker самостоятельно. Клиент может работать как на Windows 10 или Windows Server 2016. Вам нужно только указать клиенту Docker службу, которой необходимо начать управлять.
Мир Windows
Microsoft и Docker осталось сделать еще много работы, прежде чем контейнеры для Windows будут полностью функциональны, но то, что мы видим уже сейчас представляет собой значительный шаг вперед. Пользователям Windows, наконец, получат возможность пользоваться всеми преимуществами гибкости и переносимости, которые контейнеры предлагали миру Linux на протяжении более десяти лет.
Уровень сложностиСредний
Время на прочтение6 мин
Количество просмотров11K
Если на компьютере под Linux нужно быстренько запустить Windows или MacOS, самый простой и быстрый способ сделать это — ввести команду для скачивания и загрузки докер-контейнера с этой ОС.
В маркетплейсе RuVDS много готовых образов с установленными операционными системами. Там разные дистрибутивы Linux, Windows Server и CentOS. Но нет контейнеров с операционными системами.
Операционная система в докер-контейнере (в QEMU) не требует ручной инсталляции ОС. Всего одна команда в консоли — и контейнер Windows скачивается и запускается.
Набор контейнеров Dockur
Хороший набор докер-контейнеров с готовыми образами операционных систем в виртуальных машинах QEMU можно найти в репозитории Dockur.
Для выбора версии Windows при установке контейнера нужно изменить соответствующее значение в переменной окружения конфигурационного файла:
environment:
VERSION: "11"
В наличии следующие контейнеры Windows:
Предупреждение. Windows 8 потребляет очень много ресурсов CPU и RAM.
Есть также контейнеры MacOS, тут выбор поменьше:
Запуск через Docker Compose:
services:
macos:
image: dockurr/macos
container_name: macos
environment:
VERSION: "13"
devices:
- /dev/kvm
- /dev/net/tun
cap_add:
- NET_ADMIN
ports:
- 8006:8006
- 5900:5900/tcp
- 5900:5900/udp
volumes:
- ./macos:/storage
restart: always
stop_grace_period: 2m
Из консоли:
docker run -it --rm --name macos -p 8006:8006 --device=/dev/kvm --device=/dev/net/tun --cap-add NET_ADMIN -v ${PWD:-.}/macos:/storage --stop-timeout 120 dockurr/macos
Для выбора версии тоже следует изменить значение в переменной окружения конфигурационного файла:
environment:
VERSION: "13"
Версии MacOS перечислены в таблице выше.
Запуск контейнера Windows на сервере
Установить контейнер можно через Docker Compose, вот файл compose.yaml
, который практически идентичен файлу для MacOS:
services:
windows:
image: dockurr/windows
container_name: windows
environment:
VERSION: "11"
devices:
- /dev/kvm
- /dev/net/tun
cap_add:
- NET_ADMIN
ports:
- 8006:8006
- 3389:3389/tcp
- 3389:3389/udp
volumes:
- ./windows:/storage
restart: always
stop_grace_period: 2m
Или из командной строки:
docker run -it --rm --name windows -p 8006:8006 --device=/dev/kvm --device=/dev/net/tun --cap-add NET_ADMIN -v ${PWD:-.}/windows:/storage --stop-timeout 120 dockurr/windows
По умолчанию устанавливается Windows 11 Pro, другие версии можно указать, изменив параметр переменной окружения, как написано выше.
Дальнейший процесс полностью автоматический, нужно дождаться, пока контейнер скачается и запустится. Docker будет доступен через браузер на порту 8006.
Если зайти по нашему IP-адресу и указанному порту, мы увидим процесс скачивания ISO-образа Windows с сервера Microsoft:
Потом автоматическая установка и настройка Windows:
Это специальная версия Windows for Docker, она свободно распространяется с сайта Microsoft и требует активации для полноценной работы. Более старые версии Windows работают 30 дней без активации.
После завершения процесса в браузере откроется рабочий стол Windows:
Через браузер у нас работает система удалённого доступа к рабочему столу VNC (Virtual Network Computing), которая заметно подтормаживает, не поддерживает передачу звука и некоторых других функций. Для максимального комфорта рекомендуется настроить удалённый доступ через RDP. Собственно, этот доступ уже настроен в вышеуказанном файле compose.yaml
, в котором присутствуют такие строки:
- 3389:3389/tcp
- 3389:3389/udp
По этим портам и осуществляется удалённый доступ к системе из RDP-клиента, такого как Microsoft Remote Desktop, можно на той же физической системе.
В командной строке для запуска контейнера мы видим параметр --device=/dev/kvm
. Это указывает на использование виртуальной машины KVM (Kernel-based Virtual Machine), опенсорсной технологии виртуализации, встроенной в Linux. В частности, KVM позволяет превратить Linux в гипервизор для запуска нескольких изолированных виртуальных окружений, то есть виртуальных машин.
KVM — это часть Linux с 2006 года (с версии ядра 2.6.20), то есть в данном случае мы работаем с нативной виртуальной машиной Linux. Чтобы это стало возможным, материнская плата должна поддерживать технологию виртуализации на аппаратном уровне:
Чтобы проверить наличие поддержки KVM на сервере под Linux, можно запустить следующую команду:
sudo apt install cpu-checker
sudo kvm-ok
Если kvm-ok
выдаёт ошибку, то нужно проверить, что:
- в BIOS включены соответствующие расширения виртуализации (Intel VT-x, VT-d или AMD SVM),
- включена «вложенная виртуализация», если контейнер запускается внутри виртуальной машины.
К сожалению, большинство облачных провайдеров не разрешают вложенную виртуализацию на своих VPS:
Поэтому Windows в докер-контейнере запустится только на выделенном сервере или на домашнем сервере/ПК.
Если kvm-ok
не выдаёт никакой ошибки, но контейнер всё равно сообщает об отсутствии KVM-устройства, причиной может быть проблема с правами, в качестве решения можно добавить параметр privileged: true
в файл compose
(или sudo
в команду docker).
KVM обеспечивает виртуальной машине доступ к USB-устройствам и другим аппаратным ресурсам. Он позволит даже редактировать BIOS, как в примере выше.
По умолчанию, контейнеру Windows выделяется два ядра CPU и 4 ГБ RAM, это минимальные требования для запуска Windows 11. Чтобы изменить объём выделяемых ресурсов, следует добавить следующие строчки в конфигурационный файл:
environment:
RAM_SIZE: "8G"
CPU_CORES: "4"
Увеличение объёма дискового пространства со стандартных 64 ГБ (по умолчанию) до 100 ГБ:
environment:
DISK_SIZE: "100G"
Виртуальная машина будет занимать столько места на диске, сколько реально занимает контейнер с файлами, а не максимальное указанное значение.
Добавить несколько дисков:
environment:
DISK2_SIZE: "32G"
DISK3_SIZE: "64G"
volumes:
- ./example2:/storage2
- ./example3:/storage3
Зачем это нужно
Распространённая причина запуска Windows в контейнере — если у нас чисто линуксовое (или яблочное) окружение, вокруг нет ни одного компьютера под Windows, но срочно понадобилось запустить какую-то специфическую программу, которая работает только под Windows. В окружении виртуализации типа Wine эта программа не полностью функциональна. Например, старая утилита для редактирования BIOS (как AMIBCP на скриншоте) запускается под Wine, но не даёт реально изменять значения BIOS, то есть не сохраняет образ ROM:
Конечно, можно установить на ПК мультизагрузчик и вторую ОС или запустить виртуальную машину, но это тоже непростой и многоступенчатый процесс: сконфигурировать гипервизор, выделить аппаратные ресурсы.
Копия Windows в контейнере — самый простой и быстрый способ, если срочно нужна эта ОС. И самое удобное то, что не нужно проходить через процесс инсталляции системы вручную, потому что она устанавливается автоматически и сразу готова к работе. Вся процедура скачивания и запуска контейнера занимает несколько минут.
Другие наборы контейнеров
Кроме перечисленных выше, в репозитории Dockur есть и другие наборы докер-контейнеров, а также программы, полезные для самохостинга:
- Windows для ARM64,
- сервер Samba SMB,
- Dnsmasq,
- strfry, рилей-сервер Nostr,
- casa, операционная система CasaOS для самохостинга (личное облако или домашний дата-центр),
- statping — страничка с красивыми графиками, аналитикой и плагинами, всё для мониторинга сайтов и приложений,
- lemmy — агрегатор ссылок и форум, аналог Reddit или Hacker News, только для децентрализованной сети будущего, где у каждого пользователя свой сервер.
Windows на виртуальном сервере
Хотя KVM не работает на VPS, в маркетплейсе RUVDS есть четыре образа с установленной системой Windows Server 2019 и специализированным программным обеспечением:
- METATRADER 5 (MT5) – SERVER CORE с торговым терминалом MT5,
- SQL EXPRESS – SERVER CORE c бесплатной редакцией SQL Server 2019 и SQL Server Management Studio 18.4. Максимальный размер БД в этой редакции ограничен 10 ГБ,
- сервер Minecraft,
- VPN L2TP — позволяет сразу после установки шаблона подключаться к серверу по VPN, целиком меняя IP-адрес подключившегося.
Если выбрать такой образ — мы получаем готовую лицензированную Windows и настроенный софт.
Кроме того, при ручной конфигурации сервера в конфигураторе есть возможность выбрать несколько версий серверной ОС Windows для установки:
- Windows Server 2022.
- Windows Server 2019.
- Windows Server 2016.
- Windows Server 2012 R2.
- Windows Server Core 2022.
Есть и готовые тарифы с Windows:
Самая дешёвая Windows 2012 R2 стоит 588 руб. в месяц (470 руб. при оплате за год).
С 2023 года у российских пользователей возникли проблемы с покупкой Windows в условиях санкций. В такой ситуации выбор VPS с предустановленной Windows или докер-контейнер с официальным образом — легальный выход из ситуации.
Кстати, таким же удобным способом в Docker/QEMU можно запускать и Linux-контейнеры.
© 2025 ООО «МТ ФИНАНС»
Telegram-канал со скидками, розыгрышами призов и новостями IT 💻
Welcome to the Windows Containers GitHub Repository
This repository is managed by the Windows Containers platform team and is dedicated to tracking features and issues related to Windows Containers. We monitor this repository to engage with our community, address questions, discuss customer scenarios, and consider feature requests.
Getting Started
Are you new to Windows Containers?
- Start by setting up your local environment and running your first Windows container. Follow our documentation here for a step-by-step guide.
- Next, explore our training module to learn how to deploy, manage, monitor, and operate Windows containers.
Product Updates
Stay informed about the latest features and improvements by visiting the Windows Container Blog.
For open-source tools that enhance the Windows Containers experience, visit the Windows Container Tools repository. We encourage you to test the tools, provide feedback, and contribute to the development of Windows Container Tools.
Troubleshooting
Encountering issues with Windows Containers? Microsoft offers a comprehensive set of resources for troubleshooting Windows Containers:
- Windows Containers Troubleshooting Guide: This guide provides troubleshooting information for common issues encountered while working with Windows Containers.
- Windows Containers Troubleshooting Training Modules: This training module offers a guided troubleshooting learning path for various aspects of Windows Containers.
- Windows Containers Troubleshooting Workshop: This lab teaches advanced techniques for configuring, troubleshooting, and debugging Windows containers.
- Windows Containers Networking Troubleshooting This article highlights step-by-step instructions for addressing common networking issues.
Issues
For specific bugs or issues related to the Windows Container platform, please use the Issues tracker on this GitHub repository. Issues without clear reproduction steps or that remain inactive for more than two weeks will be closed.
Contributing
This project welcomes contributions and suggestions. Most contributions require you to agree to a
Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us
the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com.
When you submit a pull request, a CLA bot will automatically determine whether you need to provide
a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions
provided by the bot. You will only need to do this once across all repos using our CLA.
This project has adopted the Microsoft Open Source Code of Conduct.
For more information see the Code of Conduct FAQ or
contact opencode@microsoft.com with any additional questions or comments.
Tags:
Windows, Docker, Linux
Когда вы начнете работать с контейнерами, вы увидите много сходства между контейнером и виртуальной машиной; но, по сути, это два совершенно разных понятия. Контейнеры собираются изменить способ разработки Windows-разработок в следующем году, и они уже лежат в основе большой работы по ускорению процесса доставки. Мы объясним, как использовать функцию Windows Containers.
Введение
Контейнеры Windows революционизируют виртуализацию и процесс DevOps.
С Windows Server 2016 Microsoft представляет новую функцию под названием Windows Containers. Организации, которые обновляют свои серверы до этой новой операционной системы, смогут использовать контейнеры прямо из разработки в производственную среду.
Мы не будем углубляться в концепцию контейнеров, но в этой серии расскажем, как создавать, запускать, конвертировать и управлять вашими контейнерами Windows.
Основы Windows Containers
Прежде чем начать практическую сторону Windows Containers, мы должны вкратце осветить основы этой новой функции.
Контейнеры упаковывают программное обеспечение внутри полной файловой системы, которая содержит все, что нужно для запуска: код, среда выполнения, системные инструменты и системные библиотеки. Это гарантирует, что он всегда будет работать одинаково, независимо от среды, в которой он работает. Для достижения этой цели Windows использует изоляцию пространства имен, управление ресурсами и технологические процессы, чтобы ограничить файлы, сетевые порты и запущенные процессы, к которым может обращаться каждый контейнер, чтобы приложения, работающие в контейнерах, не могли взаимодействовать или видеть другие запущенные приложения в ОС хоста или в других контейнерах.
Виртуальные машины против контейнеров
Виртуальная машина является автономной и имеет собственную операционную систему, собственные приложения и собственные ресурсы (память, процессор и т. д.). Следующая схема показывает три виртуальных машины, размещенных на одном и том же физическом узле. Каждая виртуальная машина использует свою собственную ОС, библиотеки и т. Д. В результате они занимают значительное количество памяти.
Архитектура виртуальных машин
Довольно часто разработчикам приходится очень быстро тестировать приложения с разными версиями. Затем они должны попросить команду IT Ops развернуть одну или несколько машин (виртуальных или физических): это трудоемкий процесс. VM также потребляют значительные ресурсы, такие как память и пространство для хранения. Вот почему контейнеры удивительно полезны для процесса DevOps:
Архитектура контейнеров
Контейнеры, напротив, не содержат никакой операционной системы, поэтому они потребляют меньше ресурсов, чем виртуальные машины на физическом хосте. Контейнеры просто используют хост-операционную систему, включая ядро и библиотеки, поэтому им не нужно загружать полную ОС.
Таким образом, преимущества контейнеров Windows заключаются в следующем:
- Когда вы развертываете контейнер в рабочей среде, процесс отката очень прост. Вам просто нужно изменить сценарий развертывания и переустановить образ контейнера. Представьте себе процесс отката с виртуальными машинами? Вы должны перестроить всю машину (или вернуться к предыдущему состоянию или резервной копии).
- Время запуска для контейнера Windows короче, чем у виртуальной машины.
- Компактность использования облачных сценариев
Наконец, философия контейнера — это «одна услуга на контейнер»,
Windows Server Containers против Hyper-V Containers
Microsoft включает два разных типа контейнера. Первый тип основан на образовании Windows Server Core и называется контейнером Windows Server. Второй называется контейнером Hyper-V и основана на образовании Windows Nano Server. Контейнеры Hyper-V расширяют изоляцию, предоставляемую контейнерами Windows Server, запустив каждый контейнер в высоко оптимизированной виртуальной машине, чтобы обеспечить полную безопасную изоляцию. Ядро хоста контейнера не используется совместно с другими контейнерами Hyper-V. Если весь код, запущенный на хосте, надежен, то изоляция, предоставляемая контейнерами Windows, скорее всего, будет адекватной. Но если мы не доверяем коду, то контейнеры Hyper-V обеспечивают тот же уровень изоляции, что и виртуальные машины, но со многими преимуществами стандартных контейнеров.
Обратите внимание, что контейнеры Hyper-V управляются только Docker, а виртуальные машины Hyper-V управляются традиционными инструментами, такими как Hyper-V Manager. На практике загрузка Hyper-V контейнеров занимает больше времени, чем контейнеры Windows Server, но они намного быстрее, чем виртуальная машина с полной ОС (даже на Nano Server).
Docker
В октябре 2014 года Microsoft Corp и Docker объявили о стратегическом партнерстве, которое обеспечит гибкость, переносимость и безопасность платформы Docker для Windows Server.
Контейнеры Windows Server 2016, работающие от Docker Engine
Необходимо понимать, что Windows Server 2016 не может запускать контейнеры Linux в формате Docker, а только контейнеры Windows. Зачем? Поскольку для Linux-контейнеров требуются API-интерфейсы Linux из ядра-хозяина, а для контейнеров Windows Server требуются API-интерфейсы Windows для ядра Windows-хоста.
Однако процесс управления контейнерами Linux и Windows строго идентичен. Следующая схема описывает платформу Docker:
Платформа Docker
Ниже приведен краткий обзор жаргонов Windows Containers с их значением:
- Container Host: физическая или виртуальная компьютерная система, настроенная с использованием функции Windows Containers
- Container Image: Изображение контейнера содержит базовую операционную систему, приложение и все зависимости приложения, которые необходимы для быстрого развертывания контейнера.
- Container OS Image: Изображение операционной системы контейнера — это среда операционной системы.
- Container Registry: изображения контейнеров хранятся в реестре контейнеров и могут быть загружены по требованию. Это место, где публикуются изображения контейнеров. Реестр может быть удаленным или локальным.
- Docker Engine: Это ядро платформы Docker. Облегченное время выполнения контейнера, которое создает и запускает ваш контейнер.
- Docker file: файлы Docker используются разработчиками для создания и автоматизации создания изображений контейнеров. С файлом Docker демон Docker может автоматически создавать образ контейнера.
Docker предоставляет центральный репозиторий, называемый Docker Hub (https://hub.docker.com/), общедоступный реестр контейнерных приложений, поддерживаемый Docker. Контейнерные изображения могут быть опубликованы непосредственно в этом репозитории для совместного использования с сообществом Docker. На Docker Hub уже много изображений. Например:
- SQL
- WordPress
- IIS
- …
Вы можете запустить частный репозиторий локально. Посредством этого URL-адреса Microsoft имеет собственный публичный и официальный репозиторий: https://hub.docker.com/u/microsoft/
Контейнеры Windows на практике
Перед развертыванием контейнеров Windows вы должны подготовить свою среду с некоторыми предварительными условиями. Для этого вы можете использовать физическую или виртуальную машину, это зависит от вас. В нашем случае мы будем использовать виртуальную машину со следующими характеристиками:
- Система под управлением Windows Server 2016 (или Windows 10). Это самая важная предпосылка. Советуем вам работать с версией Datacenter из-за лицензирования (больше информации в конце статьи). Вы можете использовать Windows Server Core для своего контейнера, а не версию Windows, которая включает полный пользовательский интерфейс.
- Разрешения администратора на хосте контейнера
- Минимальное свободное пространство для хранения изображений и сценариев развертывания
- Ваш сервер должен быть современным
Хорошо, давайте начнем с установки функции Windows Containers на хосте контейнера. Для выполнения этой задачи запустите следующую команду PowerShell:
PS C:\Users\Administrator> Install-WindowsFeature Containers
Success Restart Needed Exit Code Feature Result
———— ——————— ————— ———————
True Yes SuccessRest... {Containers}
WARNING: You must restart this server to finish the installation process.
Чтобы применить изменения с помощью командлета Restart-Computer, необходимо перезапустить:
PS C:\Users\Administrator> Restart-Computer
Затем проверьте, что новая функция включена:
PS C:\Users\Administrator> Get-WindowsFeature containers
Display Name Name Install State
—————— —— ———————
[X] Containers Containers Installed
Контейнеры Windows тесно связаны с Docker; вы должны установить Docker Engine на хост контейнера. Для достижения этой цели у вас есть две возможности:
Первым из них является развертывание Docker из репозитория PSGallery:
PS C:\Users\Administrator> Install-Module -Name DockerMsftProvider -Repository PSGallery -Force
NuGet provider is required to continue
PowerShellGet requires NuGet provider version ‘2.8.5.201’ or newer to interact with NuGet-based repositories. The NuGet
provider must be available in ‘C:\Program Files\PackageManagement\ProviderAssemblies’ or
‘C:\Users\Administrator\AppData\Local\PackageManagement\ProviderAssemblies’. You can also install the NuGet provider by
running ‘Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force’. Do you want PowerShellGet to install
and import the NuGet provider now?
[Y] Yes [N] No [S] Suspend [?] Help (default is «Y»):
PS C:\Users\Administrator> Install-Package -Name docker -ProviderName DockerMsftProvider
The package(s) come(s) from a package source that is not marked as trusted.
Are you sure you want to install software from ‘DockerDefault’?
[Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is «N»): Y
Install-Package : KB3176936 or later is required for docker to work
At line:1 char:1
+ Install-Package -Name docker -ProviderName DockerMsftProvider
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (Microsoft.Power....InstallPackage:InstallPackage) [Install-Package],
Exception
+ FullyQualifiedErrorId : RequiredWindowsUpdateNotInstalled,Install-Package,Microsoft.PowerShell.PackageManagement
.Cmdlets.InstallPackage
Докер для Windows Server 2016 требует обновления «KB3176936». Его можно загрузить с веб-сайта Центра обновления Windows, а затем установить вручную:
http://www.catalog.update.microsoft.com/search.aspx?q..
Или вы можете выполнить эту задачу с помощью утилиты sconfig. Затем выберите число 6:
===============================================================================
Server Configuration
===============================================================================
1) Domain/Workgroup: Domain: get-cmd.Local
2) Computer Name: SRV1
3) Add Local Administrator
4) Configure Remote Management Enabled
5) Windows Update Settings: DownloadOnly
6) Download and Install Updates
7) Remote Desktop: Enabled (more secure clients only)
8) Network Settings
9) Date and Time
10) Telemetry settings Basic
11) Windows Activation
12) Log Off User
13) Restart Server
14) Shut Down Server
15) Exit to Command Line
Windows загрузит и установит обновления:
Microsoft (R) Windows Script Host Version 5.812
Copyright (C) Microsoft Corporation. All rights reserved.
Search for for (A)ll updates or (R)ecommended updates only? a
Searching for all applicable updates...
Downloading updates...
Второй способ — установить версию Docker для разработки, чтобы иметь новейшие функции. Вы должны скачать Docker прямо с официального сайта. Используйте командлет Invoke-WebRequest:
PS > Invoke-WebRequest «https://master.dockerproject.org/windows/amd64/docker-1.14.0-dev.zip» -OutFile «$env:TEMP\docker.zip» –UseBasicParsing
Затем извлеките архив с помощью командлета Expand-Archive:
PS > Expand-Archive -Path «$env:TEMP\docker.zip» -DestinationPath $env:ProgramFiles
Теперь вы можете создать переменную окружения:
PS > $env:path += «;$env:ProgramFiles\Docker» PS > $existingMachinePath = [Environment]::GetEnvironmentVariable(«Path»,[System.EnvironmentVariableTarget]::Machine) PS > [Environment]::SetEnvironmentVariable(«Path», $existingMachinePath + «;$env:ProgramFiles\Docker», [EnvironmentVariableTarget]::Machine) |
Чтобы закончить, установите Docker в качестве службы Windows. Итак, запустите следующую команду для регистрации файла dockerd.exe:
PS > dockerd —register-service |
После установки сервис может быть запущен:
PS > Start-Service Docker
WARNING: Waiting for service ‘Docker Engine (Docker)’ to start...
PS > Get-Service -name «docker*»
Status Name DisplayName
——— —— ——————
Running docker Docker Engine
Чтобы отобразить информацию о докере, выполните следующие действия:
PS C:\> docker info Containers: 0 Running: 0 Paused: 0 Stopped: 0 Images: 0 Server Version: 1.14.0-dev Storage Driver: windowsfilter Windows: Logging Driver: json-file Plugins: Volume: local Network: l2bridge l2tunnel nat null overlay transparent Swarm: inactive Default Isolation: process Kernel Version: 10.0 14393 (14393.0.amd64fre.rs1_release.160715-1616) Operating System: Windows Server 2016 Datacenter OSType: windows Architecture: x86_64 CPUs: 1 Total Memory: 1.933 GiB Name: SRV1 ID: VB3B:IGYN:GEFL:6ML7:OQJM:GMCJ:HDNU:Z57W:SWYI:Z2I3:WZKG:O2L4 Docker Root Dir: C:\ProgramData\docker Debug Mode (client): false Debug Mode (server): false Registry: https://index.docker.io/v1/ Experimental: false Insecure Registries: 127.0.0.0/8 Live Restore Enabled: false |
Итак, хост контейнера запущен и работает, поэтому мы можем развернуть наш первый Windows Container! В первом примере мы будем развертывать контейнер IIS, запускаем следующую команду:
PS > Docker run -d -p 8080:80 —name iis microsoft/iis
Unable to find image ‘microsoft/iis:latest’ locally
latest: Pulling from microsoft/iis
c480435b7cba: Downloading [==> ] 220.1 MB/4.175 GB
2acd7c473906: Downloading [=============> ] 240.1 MB/922.1 MB
a837699b27ea: Download complete
e4e8167eafc5: Download complete
0344b06e0e62: Download complete
Ниже приведен синтаксис команды Docker:
PS > docker run PUBLIC_PORT:PRIVATE_CONTAINER_PORT CONTAINER_NAME IMAGE
Контейнеры используют концепцию PAT (Port Address Translation). Это означает, что вы должны открывать порты контейнера через хост контейнера. В нашем примере Docker свяжет контейнер порта номер 80 с номером 8080 контейнера порта. Затем, когда мы попытаемся открыть веб-сайт IIS, расположенный внутри контейнера, я буду использовать открытый порт 8080.
Параметр «Name» добавляет дружественное имя в контейнер. Это не обязательно, но может быть полезно для последующего управления вашими контейнерами.
Наконец, вы должны указать имя образа контейнера. Здесь мы выбираем образ IIS, предоставленный Microsoft.
Когда я запускаю команду, Windows проверяет, доступно ли изображение локально (на хосте контейнера). Если нет, то Docker извлекает изображение из концентратора Docker.
PS > Docker run -d -p 8080:80 —name iis microsoft/iis
Unable to find image ‘microsoft/iis:latest’ locally
…
Когда это будет сделано, ваш Windows Container будет запущен. Наш хост контейнера имеет следующий IP-адрес: 192.168.0.132, поэтому мой веб-сайт IIS доступен с 192.168.0.132:8080
Контейнер IIS
Дальнейшая работа
Image2Docker
Допустим, у вас есть сервер, который был любовно собран вручную и который вы хотите контейнеризировать? Ну, вы можете использовать модуль PowerShell «Image2Docker», доступный в GitHub: https://github.com/docker/communitytools-image2docker.., который передает рабочие нагрузки приложений Windows из виртуальных машин на изображения Docker. Таким образом, вы можете легко конвертировать службы Windows в контейнеры Windows, такие как: сайты IIS, DNS, DHCP, …
Лицензирование
Официальный сайт содержит относительно небольшую информацию о лицензировании, но в соответствии с Техническим паспортом лицензирования Windows Server 2016 Standard Edition предоставляет права на до 2 контейнеров Hyper-V, когда все физические ядра на сервере лицензированы и контейнеры Windows Server неограничены для обоих выпусков.
Заключение
Контейнеры Windows уже меняют способы организации систем и предоставления услуг. Контейнеры начинают играть все более важную роль для разработчиков и операционных систем, чтобы не тратить слишком много времени на развертывание приложений.
Контейнерные технологии не новы в мире Linux, но для Microsoft это революция. Важно срочно найти время, чтобы понять все аспекты реализации контейнеров в вашей организации.
В этой статье мы видели, как развернуть наш первый контейнер Windows. Вы скоро заметите, что контейнеры замечательны для разработчиков и администраторов, поскольку контейнеризация обеспечивает большую гибкость в использовании и упрощает развертывание. Есть еще много вещей, которые нужно сказать о контейнерах, поэтому в следующих статьях мы объясним:
- Какие нужны команды Docker для начала работы с Docker,
- Как найти и загрузить изображения контейнеров,
- Как использовать контейнеры Hyper-V,
- Как создать собственное изображение Контейнера,
- Как конвертировать службы Windows для работы в контейнере Windows
Надеюсь, что эта статья поможет вам расширить свои знания о контейнерах Windows.
You can run any application in Docker as long as it can be installed and executed unattended, and the base operating system supports the app. Windows Server Core runs in Docker which means you can run pretty much any server or console application in Docker.
TL;DR
Update! For a full walkthrough on Dockerizing Windows apps, check out my book Docker on Windows and my Pluralsight course Modernizing .NET Apps with Docker.
Check out these examples:
- openjdk:windowsservercore — Docker image with the Java runtime on Windows Server Core, by Docker Captain Stefan Scherer
- elasticsearch:nanoserver — Docker image with a Java app on Nano Server
- kibana:windowsservercore — Docker image with a Node.js app on Windows Server Core
- nats:nanoserver — Docker image with a Go app on Nano Server
- nerd-dinner — Docker image with an ASP.NET app on Windows Server Core
- dotnetapp — Docker image with a .NET Core app on Nano Server
The 5 Steps
Lately I’ve been Dockerizing a variety of Windows apps — from legacy .NET 2.0 WebForms apps to Java, .NET Core, Go and Node.js. Packaging Windows apps as Docker images to run in containers is straightforward — here’s the 5-step guide.
1. Choose Your Base Image
Docker images for Windows apps need to be based on microsoft/nanoserver
or microsoft/windowsservercore
, or on another image based on one of those.
Which you use will depend on the application platform, runtime, and installation requirements. For any of the following you need Windows Server Core:
- .NET Framework apps
- MSI installers for apps or dependencies
- 32-bit runtime support
For anything else, you should be able to use Nano Server. I’ve successfully used Nano Server as the base image for Go, Java and Node.js apps.
Nano Server is preferred because it is so drastically slimmed down. It’s easier to distribute, has a smaller attack surface, starts more quickly, and runs more leanly.
Being slimmed down may have problems though — certain Windows APIs just aren’t present in Nano Server, so while your app may build into a Docker image it may not run correctly. You’ll only find that out by testing, but if you do find problems you can just switch to using Server Core.
Unless you know you need Server Core, you should start with Nano Server. Begin by running an interactive container with
docker run -it --rm microsoft/nanoserver powershell
and set up your app manually. If it all works, put the commands you ran into a Dockerfile. If something fails, try again with Server Core.
Derived Images
You don’t have to use a base Windows image for your app. There are a growing number of images on Docker Hub which package app frameworks on top of Windows.
They are a good option if they get you started with the dependencies you need. These all come in Server Core and Nano Server variants:
- microsoft/iis — basic Windows with IIS installed
- microsoft/aspnet — ASP.NET installed on top of IIS
- microsoft/aspnet:3.5 — .NET 3.5 installed and ASP.NET set up
- openjdk — OpenJDK Java runtime installed
- golang — Go runtime and SDK installed
- microsoft/dotnet — .NET runtime and SDK installed.
A note of caution about derived images. When you have a Windows app running in a Docker container, you don’t connect to it and run Windows Update to apply security patches. Instead, you build a new image with the latest patches and replace your running container. To support that, Microsoft release regular updates to the base images on Docker Hub, tagging them with a full version number (10.0.14393.693
is the current version).
Base image updates usually happen monthly, so the latest Windows Server Core and Nano Server images have all the latest security patches applied. If you build your images from the Windows base image, you just need to rebuild to get the latest updates. If you use a derived image, you have a dependency on the image owner to update their image, before you can update yours.
If you use a derived image, make sure it has the same release cadence as the base images. Microsoft’s images are usually updated at the same time as the Windows image, but official images may not be.
Alternatively, use the Dockerfile from a derived image to make your own “golden” image. You’ll have to manage the updates for that image, but you will control the timescales. (And you can send in a PR for the official image if you get there first).
2. Install Dependencies
You’ll need to understand your application’s requirements, so you can set up all the dependencies in the image. Both Nano Server and Windows Server Core have PowerShell set up, so you can install any software you need using PowerShell cmdlets.
Remember that the Dockerfile will be the ultimate source of truth for how to deploy and run your application. It’s worth spending time on your Dockerfile so your Docker image is:
- Repeatable. You should be able to rebuild the image at any time in the future and get exactly the same output. You should specify exact version numbers when you install software in the image.
- Secure. Software installation is completely automated, so you should make sure you trust any packages you install. If you download files as part of your install, you can capture the checksum in the Dockerfile and make sure you verify the file after download.
- Minimal. The Docker image you build for your app should be as small as possible, so it’s fast to distribute and has a small surface area. Don’t install anything more than you need, and clean up any installations as you go.
Adding Windows Features
Windows features can be installed with Add-WindowsFeature
. If you want to see what features are available for an image, start an interactive container with docker run -it --rm microsoft/windowsservercore powershell
and run Get-WindowsFeature
.
On Server Core you’ll see that .NET 4.6 is already installed, so you don’t need to add features to run .NET Framework applications.
.NET is backwards-compatible, so you can use the installed .NET 4.6 to run any .NET application, back to .NET 2.0. In theory .NET 1.x apps can run too. I haven’t tried that.
If you’re running an ASP.NET web app but you want to use the base Windows image and control all your dependencies, you can add the Web Server and ASP.NET features:
RUN Add-WindowsFeature Web-server, NET-Framework-45-ASPNET, Web-Asp-Net45
Downloading Files
There’s a standard pattern for installing dependencies from the Internet — here’s a simple example for downloading Node.js into your Docker image:
ENV NODE_VERSION="6.9.4" `
NODE_SHA256="d546418b58ee6e9fefe3a2cf17cd735ef0c7ddb51605aaed8807d0833beccbf6"
WORKDIR C:/node
RUN Invoke-WebRequest -OutFile node.exe "https://nodejs.org/dist/v$($env:NODE_VERSION)/win-x64/node.exe" -UseBasicParsing; `
if ((Get-FileHash node.exe -Algorithm sha256).Hash -ne $env:NODE_SHA256) {exit 1} ;
The version of Node to download and the expected SHA-256 checksum are captured as environment variables with the ENV
instruction. That makes it easy to upgrade Node in the future — just change the values in the Dockerfile and rebuild. It also makes it easy to see what version is present in a running container, you can just check the environment variable.
The download and hash check is done in a single RUN
instruction, using Invoke-WebRequest
to download the file and then Get-FileHash
to verify the checksum. If the hashes don’t match, the build fails.
After these instructions run, your image has the Node.js runtime in a known location — C:\node\node.exe
. It’s a known version of Node, verified from a trusted download source.
Expanding Archives
For dependencies that come packaged, you’ll need to install them as part of the RUN
instruction. Here’s an example for Elasticsearch which downloads and uncompresses a ZIP file:
ENV ES_VERSION="5.2.0" `
ES_SHA1="243cce802055a06e810fc1939d9f8b22ee68d227" `
ES_HOME="c:\elasticsearch"
RUN Invoke-WebRequest -outfile elasticsearch.zip "https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-$($env:ES_VERSION).zip" -UseBasicParsing; `
if ((Get-FileHash elasticsearch.zip -Algorithm sha1).Hash -ne $env:ES_SHA1) {exit 1} ; `
Expand-Archive elasticsearch.zip -DestinationPath C:\ ; `
Move-Item c:/elasticsearch-$($env:ES_VERSION) 'c:\elasticsearch'; `
Remove-Item elasticsearch.zip
It’s the same pattern as before, capturing the checksum, downloading the file and checking the hash. In this case, if the hash is good the file is uncompressed with Expand-Archive
, moved to a known location and the Zip file is deleted.
Don’t be tempted to keep the Zip file in the image, “in case you need it”. You won’t need it — if there’s a problem with the image you’ll build a new one. And it’s important to remove the package in the same RUN
command, so the Zip file is downloaded, expanded and deleted in a single image layer.
It may take several iterations to build your image. While you’re working on it, it’s a good idea to store any downloads locally and add them to the image with
COPY
. That saves you downloading large files every time. When you have your app working, replace theCOPY
with the proper download-verify-deleteRUN
pattern.
Installing MSIs
You can download and run MSIs using the same approach. Be aware that not all MSIs will be built to support unattended installation. A well-built MSI will support command-line switches for any options available in the UI, but that isn’t always the case.
If you can install the app from an MSI you’ll also need to ensure that the install completed before you move on to the next Dockerfile instruction — some MSIs continue to run in the background. This example from Stefan Scherer’s iisnode Dockerfile uses Start-Process ... -Wait
to run the MSI:
RUN Write-Host 'Downloading iisnode' ; \
$MsiFile = $env:Temp + '\iisnode.msi' ; \
(New-Object Net.WebClient).DownloadFile('https://github.com/tjanczuk/iisnode/releases/download/v0.2.21/iisnode-full-v0.2.21-x64.msi', $MsiFile) ; \
Write-Host 'Installing iisnode' ; \
Start-Process msiexec.exe -ArgumentList '/i', $MsiFile, '/quiet', '/norestart' -NoNewWindow -Wait
3. Deploy the Application
Packaging your own app will be a simplified version of step 2. If you already have a build process which generates an unattended-friendly MSI, you can can copy it from the local machine into the image and install it with msiexec
:
COPY UpgradeSample-1.0.0.0.msi /
RUN msiexec /i c:\UpgradeSample-1.0.0.0.msi RELEASENAME=2017.02 /qn
This example is from the Modernize ASP.NET Apps — Ops Lab from Docker Labs on GitHub. The MSI supports app configuration with the RELEASENAME
option, and it runs unattended with the qn
flag.
With MSIs and other packaged deployment options (like Web Deploy) you need to choose between using what you currently have, or changing your build output to something more Docker friendly.
Web Deploy needs an agent installed into the image which adds an unnecessary piece of software. MSIs don’t need an agent, but they’re opaque, so it’s not clear what’s happening when the app gets installed. The Dockerfile isn’t an explicit deployment guide if some of the steps are hidden.
An xcopy
deployment approach is better, where you package the application and its dependencies into a folder and copy that folder into the image. Your image will only run a single app, so there won’t be any dependency clashes.
This example copies an ASP.NET Web app folder into the image, and configures it with IIS using PowerShell:
RUN New-Item -Path 'C:\web-app' -Type Directory; `
New-WebApplication -Name UpgradeSample -Site 'Default Web Site' -PhysicalPath 'C:\web-app'
COPY UpgradeSample.Web /web-app
If you’re looking at changing an existing build process to produce your app package, you should think about building your app in Docker too. Consolidating the build in a multi-stage Dockerfile means you can build your app anywhere without needing to install .NET or Visual Studio.
See Dockerizing .NET Apps with Microsoft’s Build Images on Docker Hub.
4. Configure the Entrypoint
When you run a container from an image, Docker starts the process specified in the CMD
or ENTRYPOINT
instruction in the Dockerfile.
Modern app frameworks like .NET Core, Node and Go run as console apps — even for Web applications. That’s easy to set up in the Dockerfile. This is how to run the open source Docker Registry — which is a Go application — inside a container:
CMD ["registry", "serve", "config.yml"]
Here registry
is the name of the executable, and the other values are passed as options to the exe.
ENTRYPOINT
andCMD
work differently and can be used in conjunction. See how CMD and ENTRYPOINT interact to learn how to use them effectively.
Starting a single process is the ideal way to run apps in Docker. The engine monitors the process running in the container, so if it stops Docker can raise an error. If it’s also a console app, then log entries written by the app are collected by Docker and can be viewed with docker logs
.
For .NET web apps running in IIS, you need to take a different approach. The actual process serving your app is w3wp.exe
, but that’s managed by the IIS Windows service, which is running in the background.
IIS will keep your web app running, but Docker needs a process to start and monitor. In Microsoft’s IIS image they use a tool called ServiceMonitor.exe
as the entrypoint. That tool continually checks a Windows service is running, so if IIS does fail the monitor process raises the failure to Docker.
Alternatively, you could run a PowerShell startup script to monitor IIS and add extra functionality — like tailing the IIS log files so they get exposed to Docker.
5. Add a Healthcheck
HEALTHCHECK is one of the most useful instructions in the Dockerfile and you should include one in every app you Dockerize for production. Healthchecks are how you tell Docker if the app inside your container is healthy.
Docker monitors the process running in the container, but that’s just a basic liveness check. The process could be running, but your app could be in a failed state — for a .NET Core app, the dotnet
executable may be up but returning 503
to every request. Without a healthcheck, Docker has no way to know the app is failing.
A healthcheck is a script you define in the Dockerfile, which the Docker engine executes inside the container at regular intervals (30 seconds by default, but configurable at the image and container level).
This is a simple healthcheck for a web application, which makes a web request to the local host (remember the healthcheck executes inside the container) and checks for a 200
response status:
HEALTHCHECK CMD powershell -command `
try { `
$response = iwr http://localhost:80 -UseBasicParsing; `
if ($response.StatusCode -eq 200) { return 0} `
else {return 1}; `
} catch { return 1 }
Healthcheck commands need to return 0
if the app is healthy, and 1
if not. The check you make inside the healthcheck can be as complex as you like — having a diagnostics endpoint in your app and testing that is a thorough approach.
Make sure your
HEALTHCHECK
command is stable, and always returns0
or1
. If the command itself fails, your container may not start.
Any type of app can have a healthcheck. Michael Friis added this simple but very useful check to the Microsoft SQL Server Express image:
HEALTHCHECK CMD ["sqlcmd", "-Q", "select 1"]
The command verifies that the SQL Server database engine is running, and is able to respond to a simple query.
There are additional advantages in having a comprehensive healthcheck. The command runs when the container starts, so if your check exercises the main path in your app, it acts as a warm-up. When the first user request hits, the app is already running warm so there’s no delay in sending the response.
Healthchecks are also very useful if you have expiry-based caching in your app. You can rely on the regular running of the healthcheck to keep your cache up-to date, so you could cache items for 25 seconds, knowing the healthcheck will run every 30 seconds and refresh them.
Summary
Dockerizing Windows apps is straightforward. The Dockerfile syntax is clean and simple, and you only need to learn a handful of instructions to build production-grade Docker images based on Windows Server Core or Nano Server.
Following these steps will get you a functioning Windows app in a Docker image — then you can look to optimizing your Dockerfile.