В мире кроссплатформенной разработки WPF (Windows Presentation Foundation) долгое время оставался эксклюзивной технологией Microsoft, доступной только на Windows. Однако с развитием контейнеризации и инструментов совместимости, таких как Wine, появляется возможность запускать WPF-приложения в изолированных средах Linux. Эта статья рассказывает о моем опыте запуска WPF-приложений внутри Docker-контейнеров с использованием Wine — решения.
Важное предупреждение: WPF официально не поддерживается на Linux. Данное решение является экспериментальным и рекомендуется в первую очередь для тестирования, образовательных целей или специфических сценариев. Простые приложения могут работать, но сложные интерфейсы со сложной графикой, скорее всего, столкнутся с ограничениями.
Предыстория: Путь к решению
Почему вообще стоит задумываться о запуске WPF в Docker, когда существуют современные кроссплатформенные фреймворки вроде Avalonia? Честно не знаю, но вы же читаете эту статью? Значит вам оно нужно, мне оно тоже было нужно в качестве дополнительного задания, которое мне выдали в моем техникуме по дисциплине Docker. И мне было принципиально сделать его.
Просто написав запрос в поисковик: "Как запустить WPF в Docker" я столкнулся с тем, что многие источники категорично утверждали: «You cannot run a WPF application in docker». StackOverflow пестрел ответами о невозможности такой задачи, YouTube-ролики не предлагали рабочих решений, а попытки поиска на разных языках не приносили результата.


В своих поисках я наткнулся на образ dockur/windows, но требования к KVM и огромный размер образа делали это решение непрактичным. Прорыв произошел благодаря образу docker-wine от Scotty Hardy. После многочисленных попыток, перезапусков контейнеров и анализа ошибок удалось добиться работоспособности как для .NET Framework (версии 4.7.2 и 4.8), так и для .NET Core.
Требования к системе
Для воспроизведения этого эксперимента вам понадобится:
Docker Desktop — демон Docker для управления контейнерами
X-сервер (например, Xming) — для отображения графического интерфейса приложения
Скомпилированное WPF-приложение с исполняемым
.exeфайломDotnet - установленный dotnet на хост машине нужной версии (той же что и ваше приложение). Этот пункт нужен только если вы запускаете .NET Core.
Подготовка к запуску
Убедитесь, что ваше WPF-приложение скомпилировано и содержит исполняемый файл (например,
WpfApp.exe)Можете перейти в мой репозиторий на GitHub, чтобы взять оттуда тестовые WPF приложения на Core и Framework.
Разместите ваше приложение в корневой директории проекта рядом с Dockerfile
Запустите Docker Desktop и X-сервер (Xming)
Сборка и запуск Docker-образа
В зависимости от типа вашего приложения (.NET Framework или .NET Core) используйте соответствующие инструкции.
Для .NET Framework приложений
Начнем с .NET Framework'а, так как он проще. Я смог запустить двумя разными способами через образ scottyhardy/docker-wine и через Alpine.
Начнем с образа scottyhardy/docker-wine. Скачать Dockerfile и тестовое приложение Biorhythms можно в репозитории.
FROM scottyhardy/docker-wine
# Настраиваем переменную окружения DISPLAY для подключения к X-серверу хоста
ENV DISPLAY=host.docker.internal:0
# Копируем скомпилированное WPF-приложение из локальной директории в корень контейнера
#! Мое приложение - NET Framework 4.8
# Убедитесь, что вы указали правильный путь к вашему .exe файлу
COPY /Biorhythms/bin/Debug/Biorhythms.exe .
# Запускаем приложение через Wine при старте контейнера
CMD ["wine", "Biorhythms.exe"]
После этого можно сбилдить контейнер.
docker build -f Dockerfile.docker-wine -t wpf-app .
После этого через настроенный X-сервер, появится окно с Wine. Просто подождем.

После ожидания окно закроется и откроется новое, уже с нашим WPF приложением.

Рассмотрим второй способ через Alpine. Преимущество этого способа перед первым, в том, что он меньше по размеру. Скачать Dockerfile и тестовое приложение Biorhythms можно все так же в репозитории.
# Используем образ ориентированный на легковесность и нетребовательность к ресурсам
FROM alpine:latest
# Устанавливаем Wine
RUN apk add --no-cache wine
# Копируем скомпилированное WPF-приложение из локальной директории в папку /app
#! Мое приложение - NET Framework 4.8
# Убедитесь, что вы указали правильный путь к вашему .exe файлу
COPY /Biorhythms/bin/Debug/Biorhythms.exe ./app/Biorhythms.exe
# Настраиваем переменную окружения DISPLAY для подключения к X-серверу хоста
ENV DISPLAY=host.docker.internal:0
CMD ["wine", "/app/Biorhythms.exe"]
После этого можно сбилдить контейнер.
docker build -f Dockerfile.alpine -t wpf-app .
После запуска видим то же окно с Wine, которое обновляет конфигурацию. Отличие в том, что в данном образе по умолчанию не установлен Wine Mono, который нужен для запуска WPF. Следовательно соглашаемся на просьбу его установить и нажимаем кнопку Install.

Дожидаемся установки.

После этого окно закроется и откроется новое с нашим WPF приложением. Попробуем ввести дату моего рождения, чтобы проверить работоспособность.

Программа работает, можно идти дальше.
Перейдем к .NET Core, его запустить сложнее, потому что нам понадобится dotnet, при установке dotnet внутри контейнера в Linux скачивается версия именно для Linux, а нам нужна версия для Windows, поэтому мы будем копировать dotnet с хост машины, в контейнер в wine.
Скачать Dockerfile и тестовое приложение WPFCore можно в репозитории.
FROM alpine:latest
# Устанавливаем Wine
RUN apk add --no-cache wine
# Копируем скомпилированное WPF-приложение из локальной директории в папку /app
#! Мое приложение - NET Core 8
# Убедитесь, что вы указали правильный путь к вашему .exe файлу
COPY /WPFCore/bin/Debug/net8.0-windows ./app/
# Настраиваем переменную окружения DISPLAY для подключения к X-серверу хоста
ENV DISPLAY=host.docker.internal:0
Перейдем к запуску, тут он сложнее, чем в .NET Framework'е.
# Сначала сбилдим проект
docker build -f Dockerfile.alpine-core -t core-alpine .
# Запускаем контейнер в интерактивном режиме
docker run -it --rm --name core-alpine-container core-alpine /bin/sh
# Внутри контейнера инициализируем Wine в sh, который открылся у вас в терминале
winecfg
После этого запустится знакомое окно с установкой Wine Mono. Просто устанавливаем.

Откроем отдельный терминал и скопируем dotnet с хоста в контейнер.
#! Моя версия dotnet на хост машине - NET Core 8
docker cp "C:\Program Files\dotnet" core-alpine-container:"/root/.wine/drive_c/Program Files/dotnet"
Откроется окно с Wine configuration, просто жмем OK и идем дальше.

Теперь ожидаем, когда появится надпись, что наш dotnet был успешно скопирован в контейнер.

Возвращаемся в терминал с контейнером и в sh запускаем следующую команду:
wine /app/WPFCore.exe
После этого у вас должен запустится WPF на .NET Core.

Особенности и ограничения
При работе с WPF в Wine через Docker следует учитывать следующие особенности:
Графический интерфейс может отображаться с задержками или некорректно
Ввод с клавиатуры и мыши может быть нестабильным. Рекомендуется использовать клавиши
TabиEnterдля навигации по элементам интерфейса-
Ограниченная поддержка функций — Wine не реализует все возможности WPF. Приложения с:
Сложной анимацией
Тяжелой 2D/3D графикой
Сторонними UI-библиотеками
Специфическими Windows API
скорее всего, не запустятся или будут работать с ошибками
Советы по отладке
Если ваше приложение не запускается или работает некорректно:
Используйте
winetricksдля установки дополнительных компонентов Windows, которые могут потребоваться вашему приложениюПроверяйте логи Wine для выявления отсутствующих DLL или COM-компонентов
Начинайте с простейшего WPF-приложения (одно окно с кнопкой) и постепенно усложняйте
Для .NET Core убедитесь, что версия .NET на хосте точно совпадает с требуемой версией приложения
Альтернативные решения
Хотя эксперимент с Wine и Docker может быть интересен с технической точки зрения, для реальных проектов рекомендуется рассмотреть современные кроссплатформенные альтернативы:
Avalonia UI — мощный фреймворк для создания .NET-приложений с нативным интерфейсом на Windows, Linux и macOS
.NET MAUI — официальное решение Microsoft для кроссплатформенной разработки мобильных и десктоп-приложений
Заключение
Как показала практика запуск WPF-приложений в Docker возможен, в этом нам помог Wine. Я же доволен, что смог противостоять фразам "это не возможно" и все же запустить в контейнере приложение. Однако не для учебных целей, кроме отдельных случаев такой подход вряд ли подойдет из-за множества ограничений и нестабильности.
Этот материал создан в первую очередь для образовательных целей, чтобы показать границы возможного и помочь разработчикам, столкнувшимся с похожими задачами. Если вам действительно нужно кроссплатформенное решение — обратите внимание на современные альтернативы. Надеюсь эта статья помогла вам в вашей проблеме или хотя бы была интересна. Буду рад почитать ваши комментарии.
Комментарии (4)

eeeeeeeeeeee
10.12.2025 08:01Очень хотелось бы прочитать историю, как всё к этому пришло )
И если уже речь пошла о "нестандартных решениях", не пробовали запускать .NET MAUI на Linux? (вроде как без вайна его даже запускают)

Merrcurys Автор
10.12.2025 08:01Очень хотелось бы прочитать историю, как всё к этому пришло )
Вроде упоминал в статье, что в техникуме дали дополнительное задание на смекалку, и я решил его выполнить, кровь из носа.
пробовали запускать .NET MAUI на Linux
Не пробовал, пока такой задачи не стояло)
crackedmind
для таких целей проще сделать self-contained publish, тогда в папке с приложением будет лежат копия дотнета.
Merrcurys Автор
Не знал, спасибо за совет!