WSL2 + Docker Desktop: как Windows перестала быть проблемой на разработческих машинах
Microsoft анонсировала WSL2 с полноценным Linux-ядром, Docker Desktop добавил интеграцию. Переводим dev-машины и смотрим что изменилось с путями и производительностью.
Microsoft анонсировала WSL2 на Build 2019 (май): полноценное Linux-ядро в Windows через легковесную VM, Docker Desktop получил нативную WSL2-интеграцию
В мае на Microsoft Build анонсировали WSL2. Не «улучшенный WSL1», а честное Linux-ядро внутри легковесной Hyper-V VM - с поддержкой системных вызовов, нормальным procfs и, что важно для нас, с рабочей файловой системой. Docker Desktop в тот же месяц объявил о грядущей интеграции с WSL2. Мы взяли это за повод попробовать снова - потому что раньше попытки перейти на Windows как dev-платформу каждый раз заканчивались одинаково.
Как было до этого
WSL1 мы пробовали ещё в 2017-м. Основная жалоба была простой: производительность на смешанных операциях с файловой системой - чудовищная. npm install или composer install внутри WSL1 на директории из Windows-раздела (/mnt/c/...) занимали в разы дольше чем то же самое на нативном Linux. Проекты с тысячами мелких файлов - а это почти любой современный Node.js или PHP-проект - превращали разработку в ожидание.
Пути были отдельным удовольствием. Volume-мауны в Docker Desktop под Windows работают через Samba-sharing или через свой драйвер, и на практике это означало регулярные конфликты со \ против /, проблемы с симлинками и периодически битые volume-маунты после перезагрузки. В итоге большинство команды работало на macOS или Linux, а те кто хотел Windows - страдали и завидовали.
Что изменилось с WSL2
Ключевое отличие WSL2 от WSL1 - не совместимость системных вызовов (хотя и это), а то что Linux-файловая система живёт внутри VM как нативный ext4-том. Операции с файлами внутри WSL2-дистрибутива идут не через трансляцию - они идут напрямую в Linux VFS. Это принципиально другая архитектура.
Практически это означает:
npm installв WSL2 на проекте сnode_modulesработает примерно с той же скоростью, что на нативном Ubuntu. Не «значительно быстрее», а сопоставимо - разница в пределах погрешности.- Docker-контейнеры, запущенные через Docker Desktop с WSL2-бэкендом, используют ту же Linux VM что и WSL2. Volume-маунт из директории WSL2 в контейнер - это маунт внутри одной и той же VM, никакого Samba.
- Симлинки работают. Просто работают. Звучит как мелочь, но для npm-пакетов и yarn workspaces это был регулярный источник боли.
Есть один нюанс который надо понимать: если проект лежит на Windows-разделе (/mnt/c/), производительность всё равно будет хуже - здесь используется 9P protocol для доступа к NTFS из Linux, и это не быстро. Рецепт простой: держи проекты внутри WSL2-файловой системы (~/projects/ в дистрибутиве), а не на C:\. Это слегка меняет привычки, но разово.
Что мы сделали на практике
Перевели несколько разработческих машин на конфигурацию: Windows 10 Insider Preview (WSL2 пока в этом канале), Ubuntu 18.04 как WSL2-дистрибутив, Docker Desktop с включённым WSL2-бэкендом.
Что проверяли:
- Монтирование кода в контейнер через
-v ~/projects/app:/app- работает без нареканий, hot-reload в webpack и nodemon реагирует нормально. - docker-compose с несколькими сервисами и bind-маунтами - собрали типовой стек (nginx, PHP-FPM, PostgreSQL, Redis), поднялся штатно. Volume-маунты не ломались при перезагрузке машины.
- Make, bash-скрипты, git - всё это живёт в WSL2-окружении и ведёт себя как Linux. Скрипты из репозитория, которые на WSL1 или голом Windows падали на первой же строке с
#!/bin/bash, здесь просто работают. - VS Code с расширением Remote - WSL открывает проект прямо в WSL2-окружении. Editor запускается на Windows, а language server, git, терминал - внутри WSL2. С точки зрения разработчика это выглядит как нормальный Linux-терминал с нормальным редактором.
Что пока не идеально
WSL2 - это ещё Insider Preview, и ряд шероховатостей чувствуется. Запуск первого WSL2-окна после загрузки машины занимает несколько секунд пока поднимается VM. Не критично, но заметно. Поддержка USB-устройств внутри WSL2 отсутствует - не нужна для нашего сценария, но если у кого-то есть железо с драйверами, это ограничение.
Сетевые вещи иногда удивляют: WSL2-дистрибутив и Windows-хост имеют разные IP-адреса (WSL2 - это NAT-интерфейс), и порты, которые слушают в WSL2, не всегда прозрачно пробрасываются в Windows. Docker Desktop это решает своим образом, но если нужно обратиться к WSL2-процессу из Windows-приложения напрямую - надо знать об этой особенности.
Куда это движется
Для команд, у которых часть людей работает на Windows - это первый случай когда Windows-машина как dev-среда не требует от человека постоянно объезжать ямы. Скрипты работают, Docker работает, пути не ломают сборку. Разработчик, который привык к Windows или у которого нет выбора, получает окружение сопоставимое с тем что на Linux-машине.
Мы не спешим рекомендовать это как стандарт - Insider Preview есть Insider Preview, и гонять её на основной рабочей машине это определённый риск. Но как вектор - понятно, и результаты первых экспериментов достаточно убедительны чтобы продолжать.