Docker Desktop – это прекрасный обслуживаемый способ использования Docker в MacOS или Windows, но для нестандартных сценариев он оставляет желать лучшего.
И недавно я столкнулся с одним таким сценарием, который для вас может показаться относительно типичным. Я занимаюсь разработкой под MacOS, но поскольку у моего MacBook Pro всего 16ГБ оперативной памяти, мне захотелось использовать свой игровой ПК, у которого её 32ГБ, в качестве удалённого Docker-хоста. Сколько нас хакеров, нердов и гиков в течение дня трудится (обычно) на ноутбуках MacBook, а после работы садится за кастомные ПК с Windows, чтобы пострелять пришельцев?
Тут вы можете подумать, что всё это довольно знакомо, а значит и поставленную цель достичь будет несложно. Как бы не так. Оказалось, что заставить Docker работать в качестве хоста локальной сети в Windows весьма проблематично – для этого придётся прибегнуть к ряду специфических приёмов.
Дисклеймер: я отнюдь не являюсь администратором Windows. Мне хорошо известно, что сегодня эта ОС позволяет реализовывать почти всё то же, что системы семейства *nix в плане конфигурации, настройки сервисов и так далее. Но я полностью признаю, что не знаком с современными лучшими техниками для реализации этого.Я также не рекомендую использовать описываемую мной далее конфигурацию в любых критически важных проектах или продакшене.
▍ В двух словах
- Установите WSL 2, затем в нём установите в качестве демона Docker.
- Настройте этого демона на прослушивание
0.0.0.0:2375
. - Тут вы поймёте, что WSL принудительно привязывает его к
localhost
, а не к0.0.0.0
, что бы вы ни делали. - Подключите TCP-прокси, выполняющийся в пользовательском пространстве Windows, чтобы привязаться к
0.0.0.0:2375
и использовать его для переброса трафика наlocalhost:2375
. - Проверьте возможность подключения с внешнего хоста.
▍ Docker Desktop: чего делать нельзя
Docker Desktop предлагает элементарный способ сделать вашу машину Windows хостом Docker (по крайней мере, так может показаться): простая галочка в пункте конфигурации. Можно подумать, что этого вполне достаточно, но здесь есть подвох: Docker будет привязан только к
Localhost:2375
, а не к 0.0.0.0:2375
. То есть использование данной опции сделает Docker доступным только на локальной машине, но никак не для других узлов вашей сети.
Примечание: Docker Desktop содержит эту функциональность для того, чтобы делать текущие версии демона доступными для легаси CLI-клиентов docker
. Вот только для наших целей это оказывается бесполезным.
Поначалу я этого не понимал и использовал вышеназванную галочку, безуспешно пытаясь обратиться к Docker с другой машины сети. В стремлении понять, что я делаю не так, я заглянул в Windows Resource Monitor. Там я обнаружил, что приложение Docker Desktop прослушивает порт 2375
, но привязано только к localhost
, в связи с чем не может получать трафик из других узлов сети.После этого я сделал то, что сделал бы любой рассудительный человек – спросил Google. В одной из найденных мной статей по настройке Docker говорилось, что можно управлять этим поведением, изменяя конфигурацию JSON, представленную в приложении Docker Desktop. Так что я добавил в конфигурацию Docker следующее:
{ "hosts": ["tcp://0.0.0.0:2375"]
}
Затем я отключил фаервол в Windows и антивирусном ПО, просто чтобы исключить этот элемент как возможную причину в случае неудачи. После перезапуска Docker я снова зашёл во вкладку Network в Resource Monitor и посмотрел, что привязано к порту
2375
. Да, это Docker Desktop, всё хорошо, но он всё равно привязан только к Localhost
! Даже при правильной конфигурации, описанной в документации, это приложение в Windows просто отказывается привязываться ко всем сетевым интерфейсам, становясь, по сути, бесполезным во всех случаях, за исключением самых тривиальных.▍ Использование подсистемы Windows для Linux
После провала ещё нескольких попыток я из досады решил полностью снести Docker в Windows и повторно установить только его демона в WSL. После установки и настройки я подумал, что мог бы раскрыть этого демона из WSL для сетевого доступа, получив, наконец, хоть какие-то возможности.
Как же я ошибался.
Кто не в курсе, “WSL” означает “Windows Subsystem for Linux” и, возможно, является самым удивительным решением, какое разработчики из Misrosoft встраивали в свой флагманский продукт. Первая версия WSL добавляла хуки/оболочки непосредственно в ядро Windows, чтобы при выполнении скомпилированным бинарником Linux системных вызовов к тому, что он считает ядром Linux, ядро Windows принимало эти вызовы и перенаправляло или повторно реализовывало их логику «в стиле Windows», создавая для бинарника Linux иллюзию выполнения в родной среде. Представьте себе виртуализацию без необходимости использования гипервизора или установки другой ОС.Установка демона под Linux проблем не вызывает. Docker предоставляет прекрасную документацию для этого процесса и руководство по дальнейшим действиям. Обоим этим гайдам я следовал при установке Ubuntu 20.04 в WSL 2. Получилось довольно просто. Однако, поскольку запуск WSL несколько отличается от запуска типичного дистрибутива Linux, у вас не будет рабочего
Как обычно, это решение оказалось не идеальным. Через какое-то время в Microsoft решили исправить ряд обнаруженных недочётов, выпустив WSL v2, чрезвычайно легковесную и полностью прозрачную виртуальную машину Windows, которая предоставляла всё те же возможности, но реализованные иначе. У второй версии были некоторые свои недочёты относительно первой, но на сегодня рекомендуемым выбором чаще является именно она.
Для использования WSL вам понадобится Windows 10, желательно последней сборки. При этом вам может потребоваться Pro Edition или более продвинутая версия (не уверен, поддерживается ли WSL в версии Home). Подробнее об установке этой оболочки читайте здесь.
systemd
, поэтому для автозапуска демона Docker потребуется найти другой способ.Разобравшись с установкой и настройкой, вы сможете запускать демона Docker вручную выполнением
dockerd
от имени корневого пользователя.Однако, если вы загляните во вкладку Network в Windows Resource Monitor, то
dockerd
там не увидите. Вместо этого он будет находиться под процессом wslhost
, привязанном только к локальной петле. Что бы вы ни делали, WSL не позволит вам раскрыть находящиеся внутри него процессы напрямую для сети. То есть мы всё равно ограничены локальным loopback.Так что для реализации задуманного нам потребуется дополнительная магия. Как насчет TCP-прокси?
▍ Установка прокси перед Docker: перебор безумных решений
Тогда стало понятно, что просто нет способа, который бы позволил мне раскрыть Docker для всей сети напрямую, поэтому я решил организовать перед ним TCP-прокси. Я рассуждал так: «Если docker CLI будет просто слепо передавать трафик туда-сюда, то никакой разницы не заметит».
Какой же тогда нужно организовать прокси? У меня был опыт работы с HAProxy, но у этого проекта нет версии для Windows. Мне же нужно было что-то, работающее в пользовательском пространстве Windows, так что этот вариант отпадал.
Единственным другим знакомым мне прокси-сервером был Envoy, поэтому я посетил их сайт в поиске доступной сборки для Windows. Оказалось, что «документация» предписывает для запуска Envoy в Windows компилировать его из исходного кода (так было на тот момент; надеюсь, в будущем это изменится), а у меня не было ни времени, ни терпения для установки среды разработки Windows только ради одной сборки Envoy. Эта идея казалась безумной.
Порывшись на их сайте, я нашёл соответствующий вопрос в FAQ, ведущий на эту страницу с исполняемыми файлами для скачивания. Но тут есть проблема: все файлы представлены в виде образов Docker. То есть мне для запуска Docker нужен Docker?
Полная бессмыслица. Тогда я решил заглянуть в релизы на GitHub – безуспешно. Затем я начал читать раздел “issues” проекта, надеясь, что кто-то уже обращался с вопросом о получении скомпилированного релиза для Windows.
К сожалению, самым полезным ответом на запрос о предоставлении скомпилированных бинарников Envoy для Windows оказался этот:
Смотрите раздел envoyproxy. Мы не предоставляем исполняемые файлы, но вы можете извлечь их из контейнера docker.Эта тема продолжалась, и ниже были даны ссылки на документацию и инструмент для скачивания Envoy на машины Linux. Однако ни в одной документации не нашлось каких-либо упоминаний Windows (на момент написания статьи), что делало все эти ответы полностью бессмысленными.
Так что мне оставалось лишь идти и дербанить образ Docker.
▍ Нечестивые действия над образами Docker
На мой взгляд, использование Windows для разработки и просто работы в терминале по-прежнему представляет боль. Это очень неудобный процесс, не говоря уже о том, что мне пришлось бы переустановить кучу всяких программ и настроить тонну других, просто чтобы добиться достойного рабочего потока.
Так что я решил вытащить официальный Envoy Docker Image for Windows из Docker Hub со своего Mac (используя Docker Desktop, который задействовал более 80% памяти, только чтобы достать образы):
$ docker pull envoyproxy/envoy-windows
Using default tag: latest
Error response from daemon: manifest for envoyproxy/envoy-windows:latest not found: manifest unknown: manifest unknown
Ну хорошо, Docker, пусть будет сложно. Попробуем просто прописать в качестве тега последнюю вышедшую версию:
$ docker pull envoyproxy/envoy-windows:v1.18.2
v1.18.2: Pulling from envoyproxy/envoy-windows
4612f6d0b889: Downloading
5ff1512f88ec: Downloading
ecaafce5c67e: Pulling fs layer
d507bef22a1e: Waiting
9bdb36426121: Waiting
e5b3f220cc68: Waiting
e5410c30e7a9: Waiting
4b47829da3b1: Waiting
35eb096aecb4: Waiting
68a2a4ec685d: Waiting
9c1c360fc8b3: Waiting
a08a596feca8: Waiting
image operating system "windows" cannot be used on this platform
И-и-и-и, облом. Docker не позволяет даже вытащить образ, если между операционными системами хоста и контейнера есть разночтения.
Разразившись рядом проклятий, я всё же решил не сдаваться. Я вспомнил, что образы Docker – это просто большие tar-архивы, поэтому у меня должно получиться скачать простой образ tar с Docker Hub и, теоретически, куда-нибудь его распаковать для просмотра файловой системы того, что, в ином случае, являлось бы образом Windows.
Оказалось, это не так уж просто. В извлечении образа Docker задействованы многие кастомные заголовки и токены, так что вручную делать это проблематично. К счастью, в ходе поисков мне попался скрипт из проекта Moby, который делал именно то, что было нужно. Я извлёк этот скрипт и выполнил его для получения образа Envoy под Windows:
$ ./script.sh win envoyproxy/envoy-windows:v1.18.2
Downloading 'envoyproxy/envoy-windows:v1.18.2@v1.18.2' (12 layers)...
<snip>
Download of images into 'win' complete.
Use something like the following to load the result into a Docker daemon:
tar -cC 'win' . | docker load
Примечание: если вы получите ошибку, утверждающую ‘mapfile’ not found
, возможно, нужно обновить версию Bash. MacOS по умолчанию поставляется со старой версией, отстающей на два старших релиза. Альтернативный вариант – выполнить этот скрипт на машине WSL, где может быть установлена более новая версия Bash.
Теперь можно просмотреть созданный скриптом каталог win/
:$ ls win
Permissions Size User Date Modified Name
drwxr-xr-x - jah 4 May 15:42 1a5606bb70dc20fb56456b2583d295bdd2e847c0617da3da68d152bdd6a10b78
drwxr-xr-x - jah 4 May 15:42 4e6cb5497aca4d83d2b91ef129fa823c225b0c76cefd88f5a96dd6c0fccdd6c7
drwxr-xr-x - jah 4 May 15:42 6bfb8784732bcc28ef5c20996dbe6f15d3a004bf241ba59575b8af65de0a0aaf
drwxr-xr-x - jah 4 May 15:42 3712aa599c08d0fb31285318af13e44d988391806d2460167643340c4f3a7123
drwxr-xr-x - jah 4 May 15:42 698765937dc05ffcc458d8c2653563450bc169a724c62ed6a2c58f23c054b0ff
drwxr-xr-x - jah 4 May 15:42 a4c3f3e7cef6cd7492338a26b7b307c0cd26e29379655f681d402c1eeaf595b6
drwxr-xr-x - jah 4 May 15:42 b93d56fb00e644574bb7c2df769bb383d7fa351730393d46239078026bbc8efc
.rw-r--r-- 3.7k jah 4 May 15:42 b775d72f61762e116864ab49adc8de32045e001efd1565c7ed3afe984d6e07f0.json
drwxr-xr-x - jah 4 May 15:42 c42480d1b057b159309c4e55553ba75d84c21dc6c870f7ed77b0744c72e755f5
.rw-r--r-- 3.7k jah 4 May 15:40 d00ba7ba582355550f5e42f453d99450754df890dec22fc86adb2520f3f81da2.json
drwxr-xr-x - jah 4 May 15:42 d59df72a9d52b10ca049b2b6b1ce5b94f6ebb8a100ec71cea71ec7d8c0369383
drwxr-xr-x - jah 4 May 15:43 d8067d34f431844ea7a3068d31cdb9254f1fcb93bcaf1c182ceebdec17c8d1fc
drwxr-xr-x - jah 4 May 15:42 ea8955ac8603cc8dbb34e70e0922b59271522839db7d626e0f79f45b954c0d12
drwxr-xr-x - jah 4 May 15:42 ec233e633fbbcbaf9d6f7ba3496ebc676f9b70ac4b95ba1127c466723976f55a
.rw-r--r-- 1.2k jah 4 May 15:43 manifest.json
.rw-r--r-- 51 jah 4 May 15:43 repositories
Повозившись немного с каждым каталогом и распаковав в каждом из них layer.tar, я, наконец, нашёл то, что искал:
$ cd 3712aa599c08d0fb31285318af13e44d988391806d2460167643340c4f3a7123
$ tar xf layer.tar && chmod -R 777 * && tree .
tree .
.
├── Files
│ ├── Documents\ and\ Settings -> [Error\ reading\ symbolic\ link\ information]
│ └── Program\ Files
│ └── envoy
│ └── envoy.exe
├── Hives
│ ├── DefaultUser_Delta
│ ├── Sam_Delta
│ ├── Security_Delta
│ ├── Software_Delta
│ └── System_Delta
├── VERSION
├── json
└── layer.tar
4 directories, 10 files
Вот оно! Мы нашли envoy.exe!
Скопировав envoy.exe из контейнера архива tar, теперь я мог написать файл конфигурации для проксирования TCP-трафика с
0.0.0.0:2375
в локальный loopback на одном порту. Конфигурация получилась такой:static_resources:
listeners:
- name: docker-proxy
address:
socket_address:
address: 0.0.0.0
port_value: 2375
protocol: TCP
filter_chains:
filters:
- name: envoy.filters.network.tcp_proxy
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy
cluster: docker-actual
stat_prefix: docker-proxy
clusters:
- name: docker-actual
connect_timeout: 1s
type: STATIC
load_assignment:
cluster_name: docker-actual
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: 172.25.65.236
port_value: 2375
protocol: TCP
admin:
address:
socket_address:
address: 0.0.0.0
port_value: 9901
Важно: при каждом запуске WSL присваивает себе новый адрес IPv4. Я пока не выяснил, как заставить её всегда использовать одинаковый адрес. Так что вам потребуется получать IP-адрес WSL через выполнение ifconfig eth0
из оболочки WSL и подставлять свой вместо того, что приведён в моём примере конфигурации. Это нужно будет делать каждый раз при перезагрузке машины или остановке и старте WSL.
▍ Запускаем
Подготовив Envoy, можно всё запускать и приступать к тестированию. На своей машине с Windows я открыл в WSL оболочку, откуда вручную запустил Docker:
$ sudo dockerd --tls=false &
После в другом окне терминала я запустил сеанс Powershell и Envoy:
PS J:\envoy> .\envoy.exe -c .\envoy.yaml
Если всё сработает должным образом, то вы увидите, что
wslhost
привязан к локальной петле на порту 2375
, а envoy.exe привязан к “IPv4 unspecified”
также на порту 2375.Теперь я, наконец-то, мог задействовать в качестве Docker-хоста компьютер с мощным оборудованием. Оставалось лишь экспортировать переменную среды и использовать её.
$ export DOCKER_HOST=<ip of windows box>
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
Работает!
▍ Выводы
На всякий случай повторюсь, что всё проделанное мной никогда не следует делать в продакшене. Это был мой отдельный случай в собственной сети. Меня интересовало исключительно удобство разработки и тестирования.
Описанная здесь настройка требует немало ручной работы. При каждой перезагрузке хоста вам потребуется выяснять внутренний IPv4 адрес для WSL, изменять эту запись в конфигурации Envoy, запускать
dockerd
в WSL и снова запускать envoy.exe для подключения. Сейчас я делаю всё это сам, так как машину с Windows перезагружать мне приходится нечасто. И всё же я хочу найти способ автоматизировать выполнение всего этого процесса при загрузке компьютера. Думаю, что это можно реализовать с помощью файла .BAT
, вызываемого через “Запланированную задачу” (см. «Планировщик задач») при каждом запуске компьютера до стадии авторизации.Весь проделанный путь оказался сложнее, чем должен был. Здесь мы столкнулись и с отказом Windows Docker Desktop признавать конфигурацию
host
, и с заявлением проекта Envoy о том, что у них есть релиз под Windows, который оказалось столь сложно извлечь, а также с тем, что Microsoft по умолчанию не позволяет раскрывать для сети процессы в WSL, привязанные к портам. Есть объективный повод критиковать все три причастные компании за излишнее усложнение вещей, которые должны быть простыми. При этом также нужно признать, что всё проделанное мной оказалось бы невозможным, если бы не прекрасная работа, которую люди из вышеупомянутых компаний проделали для создания превосходных инструментов, позволяющих таким как я реализовывать подобные «безумные» приёмы.Однако признаю, что удалять Docker Desktop из Windows было необязательно, поскольку установленный в WSL демон всё равно оказался привязан только к локальной петле. Теоретически должна быть возможность проделать всё это без использования WSL (минус извлечение образа Envoy, для чего необходима последняя версия Bash). Но ключевое слово здесь «теоретически» — я не пробовал сделать это с помощью Docker Desktop для Windows и понятия не имею, какие ещё проблемы могут возникнуть, если пойти этим путём.
Закончу тем, что всего этого можно было избежать, если бы:
- Apple ставили в свои MacBook Pro больше 16ГБ ОЗУ или;
- Docker не требовал целую виртуальную машину с выделенными ресурсами для «имитации» контейнеров в MacOS.
Но мы ведь живём не в идеальном мире.
RUVDS | Community в telegram и уютный чат
Комментарии (12)
amkartashov
24.10.2022 18:17+5эээ
netsh interface portproxy add v4tov4 listenaddress=0.0.0.0 listenport=2375 connectaddress=127.0.0.1 connectport=2375 netsh advfirewall firewall add rule name="Open Port 2375 for Docker Desktop" dir=in action=allow protocol=TCP localport=2375
aytugan
24.10.2022 20:58+3Логично.
А вообще топикстартеру можно было на виндоусе под hyper-v виртуалку поднять, и в ней докер поставить. Было бы всё нативно и без WSL. Захотелось поиграться - засуспендил виртуалку на диск чтобы память высвободить, поигрался - запустил её снова.Samuel_Leonardo
24.10.2022 22:23+2wsl2 и есть по сути виртуалка под hyper-v, если бы автор разобрался в инструменте, который он использует, то быстро бы понял что докер тут не причем,
он вполне верно слушает порты в виртуальной сети, а то что у него пробрасывается порт на 127.0.0.1 в винде уже заслуга wsl2,
и он бы быстро нашел подобные команды, как указали выше,
ну и wsl2 также без проблем останавливается и память высвобождаетсяElvenSailor
25.10.2022 10:46Да, но нет.
Докер на WSL2 сам устанавливает параметры для VM, какие считает нужным. Например, ты захотел урезать количество RAMы для докера, а при следующем запуске он бац! - вернул обратно. Ну и сеть там по умолчанию настроена по-нанайски.
Намного удобнее воткнуть роль Hyper-V, в ней поставить удобный тебе линукс, хочешь с гуём, хочешь - без гуя, выдать ей памяти и ядер - сколько нужно, сделать нормальный virtual switch без всякого мерзкого NAT'a, и гонять хоть докер, хоть не-докер, любую линуксовую штуку (или две, три, N, на сколько памяти хватит).
При этом вовсю юзать плюшку Dynamic Memory (если у тебя там внутри не SQL).
Единственное - нормальная роль Hyper-V есть только в редакциях винды Enterprise, Pro, or Education. Но, думаю, для человека, который разрабочтик, или админ, это не является проблемой.
Samuel_Leonardo
25.10.2022 10:55+1Память можно ограничить
https://learn.microsoft.com/en-us/windows/wsl/wsl-config#configuration-setting-for-wslconfig,
а так же вернуть не задействованную память обратно хосту
https://devblogs.microsoft.com/commandline/memory-reclaim-in-the-windows-subsystem-for-linux-2/
но да, если нужна полноценная виртуалка с более гибкой настройкой и возможности hyper-v manager
лучше использовать их
OptimumOption
25.10.2022 06:12Это же первая мысль, которая должна приходить человеку разумному! Но... почему то всегда начинаются танцы и пляски с попытками заставить работать что то на чём то, что изначально для этого не предназначено... Прямо конкурс гиков-проктологов какой-то, прости-господи...
fedorro
25.10.2022 12:15Вообще если речь про игровой компьютер, то Hyper-V, WSL и пр — снижают производительность игр, сами MS, об этом пишут. Поэтому для докера лучше менее дерзкий виртуализатор запускать, типа VMWare или VirtualBox, за одно не знать вот этих проблем с сетью. Единственный смысл от WSL — то что туда можно видеокарту с винды прокинуть, и запускать докеры для машинного обучения и тд.
Vadimio
24.10.2022 19:27systemd уже поддерживается в wsl2
https://devblogs.microsoft.com/commandline/systemd-support-is-now-available-in-wsl/
alisherrakhimov
25.10.2022 19:25Жаль что только на windows 11, скорее на 10 не добавят(((
QuAzI
25.10.2022 21:26С уровнем "поддержки" от форточки проще реально в линух на "лишнем" ПК бутаться и не страдать с "когда-нибудь поддержат". Либо поднять одну полноценную виртуалку с линухом и в нём всё нормально делать. W11 выглядит как очередная "версия ради концепта", которую лучше скипнуть, как было с ME, Vista и 8.
WondeRu
25.10.2022 01:51+3Проще было поставить ubuntu как вторую ОС и загружаться в нее, там ставить человеческие докеры. В свое время я намучался на wsl, больше всего бесило потребление CPU, ноутбук пытался взлететь. Сейчас полностью на ubuntu, забываю windows как ужасный сон.
unlnkd
Предложу свой костыль, которым пользуюсь.
Работаю на Macbook Air m1 с 16 GB. Хотелось иметь дома лабу вне облаков, где можно было бы поднимать свои гипервизоры, виртуалки, докер хосты, но доступной не только из дома, но и из кафе. Можно было бы и под MacOS, но на тот момент VirtualBox не мог в m1 (вроде бы вот-вот только заявили в 7.х).
Есть старый Core i7-4770 CPU, 32 GB, 512 GB SSD с работающей лицензионной Windows 10 Pro, которую не хочется удалять, а иметь возможность периодически использовать. Системник стоит в уголке, не шумит вентиляторами, управляется по RDP.
Цель: гипервизор в виде ВМ с вложенной (nested) виртуализацией, чтобы дальше можно было с помощью vagrant-а и т.д. разворачивать следующие виртуалки для докеров и других кластеров.
Сначала думал поднять VirtualBox с nested-виртуализацией. Оказалось, что nested не работает с процессорами Intel ниже 5-го поколения, хотя все nested галочки в интерфейсе спокойно нажимались.
Думал, что Hyper-V + Vagrant спасут ситуацию, но box-ы из vagrant cloud-а всё равно не заводились в режиме nested.
Поставил Hyper-V + GUI. Установил руками Centos 7 в виде ВМ, назначил её роль гипервизора (virtualbox 6 + vagrant), выделил ей максимум ресурсов (с учетом ограничений Hyper-V). Включил в powershell нужные кнопки, чтобы включить для этой ВМ вложенную виртуализацию. Создал прозрачный Virtual Switch, чтобы иметь возможность получения адресов из внутренней сети по DHCP для последующих виртуалок внутри гипервизора. Здесь тоже не обошлось без дополнительного колдовства в настройках powershell для Virtual Switch, благо документация есть.
Результат: Mikrotik в виде шлюза, Windows по RDP с гипервизором, доступным по SSH, виртуалки разных ролей и конфигураций, докер хосты, виртуалка в роли wireguard-шлюза, которая коннектится к хосту в AWS, через которую осуществляется доступ в лабу из кафе. И всё это доступно для управления и конфигурирования на каждом шаге. Плюс вы**анный мозг.