запуск gui приложений в docker
Как запустить любое ПО с графическим интерфейсом в Docker?
Вы, конечно, прекрасно знаете, что такое docker и контейнеры и даже как развернуть модель машинного обучения в docker? Но есть еще один интересный вопрос: как запустить и открыть любое приложение с графическим интерфейсом в docker? Похоже, это не так просто. Но сейчас мы со всем разберемся…
В статье мы пройдем этот процесс, выполнив несколько этапов.
Запуск контейнера в docker в режиме графического интерфейса.
Запуск любого ПО с графическим интерфейсом в контейнере.
Первым делом установим docker в компьютере, используя такую команду:
yum install docker
Затем нужно запустить и включить службу «Docker». Делается это следующими командами:
systemctl start docker
systemctl enable docker
Теперь добавляем образ:
docker pull centos:8
Здесь мы добавляем образ операционной системы Centos 8-й версии.
Теперь запустим контейнер Docker…
Теперь нужно установить firefox в контейнере:
Для этого используем команду
Как думаете, будет работать наш firefox или нет? Правильно! Конечно же, нет.
Видите здесь ошибку с переменной окружения DISPLAY? Нужно задать эту переменную окружения.
Переходим на localhost и выполняем следующие команды (чтобы продолжить, нам нужно создать каталог, а затем Dockerfile):
Здесь мы создали каталог doraemon и внутри него Dockerfile.
Внутри Dockerfile нужно ввести следующие команды:
Эта точка в конце тоже важна для выполнения всех команд, так что не забываем ставить ее:
Образ firefox находится среди образов docker в списке отображения:
Теперь для доступа к firefox вводим:
и после выполнения этой команды вот что у нас получится:
Вот и все, теперь firefox запускается в контейнере Docker.
Записки программиста
Осилил запуск GUI-приложений в Docker
Как мы совсем недавно уже выясняли, есть целый ряд проблем, которые можно решить запихиванием приложений в Docker-контейнеры, в том числе десктопных приложений. Никакой хакер не поломает вас через браузер. Настроенную систему можно быстро разложить у нового сотрудника или на своем новом ноуте. Всякий мусор, необходимый только одной программе, можно изолировать от остальной системы и снести одной командой. Никаких конфликтов зависимостей. Можно попытаться обновить программу, и если что-то в новой версии сломалось, просто перезапустить контейнер без коммита. Можно даже запускать браузер на одной машине, IDE на другой, а рулить всем этим с ноутбука, пробросив на него X11! Самое интересное, что запускать GUI приложения в Docker оказалось на удивление просто.
Примечание: В этой заметке используются наработки из поста Зачем нужен Docker и практика работы с ним. Вам может захотеться прочитать его прежде, чем следовать далее. Или перечитать, если успели подзабыть содержание.
Docker, как мы выясняли, правильно использовать не по те-еретическому принципу «по приложению на контейнер, потому что так правильно™», а беря за основу baseimage. Это значит, что контейнер для нас мало чем отличается от VDS, и то же самое пробрасование X11 должно работать. Другой вопрос, что делать со звуком? Но эту проблему мы тоже скоро решим. А пока что давайте попробуем запустить в контейнере веб-браузер Chromium хотя бы без звука.
Запускаем контейнер, используя созданный ранее образ baseimage-ssh:
Заходи в контейнер:
Пытаемся поставить x11-apps. В моем случае система внезапно сообщила, что слыхом не слыхивала о таких чудесах, поэтому пришлось скопировать файл /etc/apt/sources.list с хост-системы. После этого все получилось:
После установки xauth в гостевой системе все заработало. Пробуем кое-что посерьезнее:
Chromium у меня так просто тоже не стал запускаться, сказав:
Беглое гугление привело меня в обсуждение в группах Google, благодаря которому, а также благодаря приведенным в нем ссылкам, я понял, что это такая багофича Chromium при работе во всяких изолированных окружениях, и что правильно запускать его так:
Следуте однако отметить, что шрифты могут вас шокировать. Вам может захотеться сначала сказать:
Теперь имеем Chromium, как Chromium. Так и не скажешь, что под Docker запущен.
На первый взгляд, в контейнере как-то без разницы, под рутом ты сидишь или нет. Но под рутом можно случайно удалить или испортить файлы, которые удалять или портить не хотелось, и придется откатываться к последнему коммиту, потеряв все другие сделанные изменения. Поэтому на всякий случай заведем нового пользователя:
Появится одна или несколько строчек вроде таких:
Переключаемся на юзера:
Для каждой ранее уведенной строчечки говорим:
В дальнейшем так далать не понадобится, все сохраняется в файлики.
В гостевой системе:
Запускаем paprefs, во вкладке Network Server ставим галочку Enable network access to local sound devices, а также Don’t require authentication. Затем:
У меня как-то не с первого раза получилось, но в итоге все заработало без необходимости перезагружать Ubuntu.
Теперь пробрасываем порт на гостевую систему:
В гостевой системе говорим:
… и звук пошел! Самое главное теперь — не забудьте сделать commit!
Как оказалось, моя любимая IntelliJ IDEA таким образом также прекрасно запускается. Похоже, можно без проблем запускать в Docker-контейнерах практически любые приложения, кроме, возможно, чего-то вроде игр. Если вдруг кому-то интересно, размер экспортированного образа с IDE, компилятором Scala, SBT, а также кучей джавных/скальных библиотек, скопированных с хост-системы, получился 9 Гб без сжатия и 5.4 Гб после сжатия. Накладных расходов на виртуализацию замечено не было, я даже несколько раз сравнивал скорость компиляции проекта в хост-системе и в Docker — никакой разницы.
А какие GUI-приложения вы пробовали запускать в Docker и с какими проблемами при этом столкнулись?
linux-notes.org
Запуск GUI-приложения в Docker
Хочу поведать историю о том, как я запустил GUI-приложение в Docker. некоторые спросят, зачем? Ну есть много причин, вот некоторые из них:
Запуск GUI-приложения в Docker
Начну с теории и закончу примерами.
Архитектура X window system 101
В *NIX системах, приложение GUI имеет роль «X-клиента». Каждый раз, когда он перерисовывает свое содержимое, последовательность графических команд кодируется все в X протокол используя библиотеку (обычно Xlib) и передается в сокет X11. На другом конце, X-сервер считывает такие команды из сокета и отображает их на дисплей:
Контейнерезированные (Containerizing) GUI приложения
Взглянув на архитектуру X window системы, ясно то, что для того, чтобы наши контейнеризованные графические приложения могли рисовать на экране, нам нужно предоставить ему доступ к сокету X11 (запись), и нам нужен X-сервер для использования и рендеринга графики команд на экран.
Мы можем подойти к этой проблеме с двух сторон:
Первый подход — это тот, который проще реализовать, он работает из коробки и клиенты VNC доступны. В то же время мы должны учитывать, что xvfb создает представление в памяти дисплея, а VNC сохраняет в памяти последнюю обновленную область, поэтому в худшем случае мы получаем размер буфера кадра, выделенного дважды в каждый экземпляр докер-контейнера.
Совместное использование сокета X11 хоста с контейнером — это гораздо более модульное решение, которое позволяет использовать более компактный файл Docker, и он позволяет владельцу X-сервера переключать реализацию в соответствии с ее потребностями (возможно, X-сервер нашего хоста может быть даже самой xvfb).
Для начала, установим вспомогательное ПО:
И так, сейчас я приведу несколько примеров использования docker чтобы запустить графическое ПО внутри докер-контейнера. Самый простой способ сделать это, это выполнить:
Это самые простые способы для запуска.
Поддержка 3D hardware acceleration:
Поддержка звука (Audio):
Поддержка Webcam:
Используем date/time как и на хосте:
PS: Некоторые дистрибутивы не используют /etc/localtime, чтобы установить часовой пояс, в этих случаях вам нужно будет проверить, как он это делает и «реплицировать» в контейнер.
Проброс конфигов в контейнер:
Подключаем Video-game controller:
Это были примеры запусков. Сейчас приведу наглядные примеры….
-=== Запуск mysql-workbench в Docker ===-
После чего, я создам машину для тестов, буду использовать docker-machine:
Машина создана, подключаемся к ней:
Внутри созданной докер-машины, создаем:
Где нужно изменить «ENV DISPLAY :0» строку на свой «DISPLAY», чтобы узнать его, выполните:
Получите вывод (Если у вас MacOS X):
Получите вывод (Если у вас Linux. Проверял на CentOS 6):
Ну что, создаем контейнер:
Запускаем контейнер и прокидываем в него сокет. Контейнер автоматически стартует MySQL-Workbench при запуске:
PS: Можно прописать переменную:
Потом запуск будет проходить вот так:
Честно сказать, у меня не получилось запустить данный контейнер на моем macbook, получил ошибку:
Дубль 2, пробую выполнить все тоже, но на CentOS 6:
ИЛИ, для всех юзеров:
Но это не верное решение, берем свой eth0 ИП:
Так же, пробросим переменную для дисплея:
После этого, запускаю:
Вылезли другие ошибки… Посидел пару часов, я исправил ошибки на маке (описание решения, в самом низу статьи), ну а сейчас — я запускаю контейнер:
Или (Но 1-й вариант лучше как по мне):
Шикарно! Все заработало!
-=== Запуск FireFox в Docker ===-
Существует несколько различных вариантов запуска GUI-приложений внутри Docker контейнера:
Самый простой способ — заключается в том, чтобы разделить мой сокет X11 с контейнером и использовать его напрямую. Идея довольно проста, и вы можете легко попробовать попробовать запустить контейнер Firefox, используя следующий файл Docker:
И вот что получилось:
Данный пример приводился на CentOS 6, но у меня есть еще MacOS X и я бы хотел все же подружить все это дело!
Ставим пакет для MacOS X:
Открываем натройки, переходим во вкладку «security» и выставляем все галочки (2 шт):
Хочу добавить следующее, я много перерыл в интернете, но мало что полезного нашел. И да, вот как у меня выглядят конфигы ssh.
Приведу еще пример.
-=== Запуск spotify в Docker ===-
PS: У меня тут используется несколько интерфейсов, но я взял ИП с eth1.
Не буду собирать контейнер с Dockerfile, возьму готовый имедж:
Я тут пробросил звуковое устройство во внутрь самого контейнера.
Вот это шайтаны додумались)))
На маке я пока не понял как это сделать 🙁
-=== Запуск wireshark в Docker ===-
PS: У меня тут используется несколько интерфейсов, но я взял ИП с eth1.
Или посмотреть все ИП на всех интерфейсах:
Не буду собирать контейнер с Dockerfile, возьму готовый имедж:
Вот и все, статья «Запуск GUI-приложения в Docker» завершена.
Добавить комментарий Отменить ответ
Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.
Docker: запуск графических приложений в контейнерах
Строго говоря, Docker не был создан для подобного рода вещей, а именно запуска графических приложений. Однако, время от времени в темах про Docker звучат вопросы о том, нельзя ли запустить GUI-приложение в контейнере. Причины могут быть разные, но чаще всего, это желание сменить излишне громоздкую виртуальную машину на что-то полегче, не потеряв в удобстве и сохранив при этом достаточный уровень изоляции.
Это небольшой обзор способов запуска графических приложений в контейнерах Docker.
Оглавление
Монтирование устройств
Один из самых простых способов заставить контейнер говорить и показывать — это дать ему доступ к нашему экрану и звуковым устройствам.
Приставка «unix» к DISPLAY здесь для явного указания использования unix-сокетов, но чаще всего в этом нет необходимости.
Ошибка авторизации
При запуске можно столкнуться с ошибкой вида:
Такое происходит, когда расширение Xsecurity блокирует неавторизованные подключения к X-серверу. Решить эту проблему можно, например, разрешив все локальные несетевые подключения:
Или ограничиться разрешением только для root-пользователя:
В большинстве случаев этого должно быть достаточно.
Другим вариантом будет дать контейнеру возможность самостоятельно авторизовываться на X-сервере с помощью заранее подготовленного и смонтированного Xauthority-файла. Создать такой можно с помощью утилиты xauth, которая способна извлекать и экспортировать данные для авторизации. Загвоздка, однако, в том, что такая авторизационная запись содержит в себе имя хоста, на котором запущен X-сервер. Просто скопировать ее в контейнер бесполезно — запись будет проигнорирована при попытке локального подключения к серверу. Решить эту проблему можно по-разному. Опишу пару способов.
Подмена кода соединения. Первые два байта в каждой записи из Xauthority-файла содержат код соответствия семейству соединений (TCP/IP, DECnet, локальные соединения). Если этому параметру присвоить специальное значение FamilyWild (код 65535 или 0xffff), то запись будет соответствовать любому экрану и может быть использована для любого соединения (то есть имя хоста не будет иметь значения):
А что со звуком?
В итоге
Суммируя, команда для запуска контейнера с графическим приложением выглядит примерно так:
Или, для Docker версии ниже 1.2:
Пример №1
Я подумал, что для проверки графики и звука подойдет какой-нибудь аудиоплеер с графическим интерфейсом и выбрал DeaDBeeF в качестве подопытного. Для запуска нам не понадобиться ничего, кроме образа с установленным плеером.
Теперь можно запустить его и послушать, например, радио (если решите попробовать — учтите, что плеер запустится на полной громкости):
Результатом должен стать работающий плеер
А звук?
После изменения настроек PulseAudio следует перезапустить:
Здесь можно увидеть, что аудиосервер «слушает» на unix-сокете (unix:/run/user/1000/pulse/native), 4713-м TCP и TCP6 портах (стандартный порт для PulseAudio).
Для того, чтобы X-приложения в контейнере подключались к нашему pulse-серверу нужно указать его адрес в переменной окружения PULSE_SERVER:
Здесь «172.17.42.1» — это адрес моего docker-хоста. Узнать этот адрес можно, например, так:
То есть строка «tcp:172.17.42.1:4713» говорит, что подключиться к pulse-серверу можно по IP-адресу 172.17.42.1, где он слушает TCP-порт 4713.
Аудиоданные при этом будут передаваться по зашифрованному каналу.
Пример №2
Как и в предыдущем примере опишем образ плеера DeaDBeF c ssh-сервером. Я буду исходить из того, что все описанные выше предварительные настройки PulseAudio проведены, а значит остается только приступить к созданию docker-образа.
Код установки плеера будет повторят код из примера ранее. Нам лишь остается добавить установку openssh-сервера.
На этот раз кроме Dockerfile создадим еще один файл — entrypoint.sh. Это скрипт для «точки входа», т.е. он будет выполняться каждый раз при запуске контейнера. В нем мы будем создавать пользователя со случайным паролем, настраивать переменную окружения PULSE_SERVER и запускать ssh-сервер.
Порт и адрес pulse-сервера будем передавать в качестве параметров при запуске контейнера, чтобы иметь возможность поменять их на нестандартные (не забыв о значениях по умолчанию).
Запустим контейнер, не забыв указать хост PulseAudio (порт я опущу, так как у меня он стандартный), и назовем его «dead_player»:
Узнать пароль пользователя для подключения можно с помощью команды docker logs :
Для подключения по ssh можно использовать адрес как самого контейнера, так и адрес docker-хоста (при этом порт подключения будет отличаться от стандартного 22-го; в данном случае это будет 2222 — тот, который мы указали при запуске контейнера). Узнать IP контейнера можно с помощью команды docker inspect :
Подключение к контейнеру:
Или через docker-шлюз:
Наконец, после авторизации, можно расслабиться и послушать музыку:
Subuser
Subuser позволяет запускать программы в изолированных контейнерах docker, беря на себя всю работу, связанную с созданием и настройкой контейнеров, поэтому пользоваться им могут даже люди, ничего не знающие о docker. Во всяком случае, такова идея проекта. Для каждого приложения-контейнера при этом устанавливаются ограничения в зависимости от его назначения — ограниченный доступ к директориям хоста, к сети, звуковым устройствам и т.д. По сути, subuser реализует удобную обертку над описанным здесь первым способом запуска графических приложений, так как запуск осуществляется с помощью монтирования нужных директорий, устройств и т.д.
К каждому создаваемому образу прилагается файл permissions.json, который определяет настройки доступа для приложения. Так, например, выглядит этот файл для образа vim:
Subuser имеет репозиторий (на данный момент — небольшой) готовых приложений, список которых можно увидеть с помощью команды:
Добавить приложение из репозитория можно так:
Эта команда установит приложение, назвав его firefox-flash, основанное на одноименном образе из репозитория по умолчанию.
Запуск приложения выглядит так:
Кроме использования стандартного репозитория, можно создавать и добавлять свои собственные subuser-приложения.
Проект довольно молодой и пока выглядит сыроватым, но свою задачу он выполняет. Код проекта можно найти на github: subuser-security/subuser
Пример №3
/.subuser-repo сойдет. В ней следует инициализировать git-репозиторий:
Здесь же создадим директорию для DeaDBeef:
Структура директории для subuser-образа выглядит следующим образом:
Итак, подготовив структуру каталога, остается создать два файла: SubuserImagefile и permissions.json.
SubuserImagefile практически ничем не будет отличаться от приведенного ранее Dockerfile:
В permissions.json опишем параметры доступа для нашего плеера. Нам понадобиться экран, звук и интернет:
Закоммитим изменения в нашем импровизированном subuser-репозитории:
Теперь можно установить плеер из локального репозитория:
Наконец, запустить его можно с помощью следующей команды:
Удаленный рабочий стол
Раз уж контейнер так похож на виртуальную машину, а взаимодействие с ним напоминает сетевое, то в голову сразу приходит решение в виде систем удаленного доступа, таких как: TightVNC, Xpra, X2Go и т.п.
Пример №4
Что касается того, что мы будем ставить, то можно, конечно, в контейнер установить полноценную графическую оболочку вроде LXDE, XFCE, или даже Gnome с KDE. Но мне это показалось излишним для условий данного примера. Нам хватит и OpenBox.
В контейнере кроме x2go-сервера также понадобится ssh-сервер. Поэтому код будет во многом похож на приведенный в примере №2. В той части, где ставится плеер, openssh-сервер, и сервер pulseaudio. То есть останется только добавить x2go-сервер и openbox:
Также немного изменим скрипт entrypoint.sh. Нам теперь нет необходимости настраивать переменную окружения PULSE_SERVER, поэтому от этого кода можно избавиться. Кроме того, пользователя для подключения следует добавить в группу x2gouser, иначе он не сможет запустить x2go-сессию:
Запустим контейнер в режиме демона:
После подключения можно запустить плеер через меню openbox (правый клик мышью) и проверить его работоспособность:
Но это уже совсем другая история.
Добавлю еще, что X2Go позволяет запускать одиночные приложения, так, как если бы они запускались на локальной машине. Для этого надо в клиенте в настройках «Session type» выбрать «Single application» и в «Command» прописать путь к исполняемому файлу. При этом в контейнере даже нет необходимости устанавливать графическую среду — достаточно иметь X2Go-сервер и желаемое приложение.
Графические приложения в Docker
Система управления контейнерами docker нацелена на то, чтобы процессы в ней работали без графического интерфейса. Однако иногда надо использовать её не совсем по назначению, например, запускать приложения, которые в обычном режиме будут работать в режиме без интерфейса, но для отладки надо посмотреть что они делают и что выводят.
В этой небольшой статье мы разберемся как запустить графическое приложение в Docker в операционных системах семейства Linux. Мы будем подключать наш основной X сервер к контейнеру.
Графические приложения в Docker
Первым делом надо сделать небольшое изменение для хоста, иначе, хост не разрешит приложению контейнера подключаться к X серверу. Создаем файл /tmp/docker.xauth:
А затем помещаем в него данные для аутентификации:
Эти строки можно добавить в
/.xinitrc, чтобы файл аутентификации создавался автоматически при запуске X сервера:
Теперь всё готово к запуску контейнера docker с gui. В контейнер мы примонтируем этот файл, UNIX сокет X сервера и передадим переменные, которые помогут приложениям в контейнере это всё найти. Для примера запустим gimp:
Если вы хотите запустить более сложную программу, например браузер Google Chrome, то вам понадобиться подключить ещё и поддержку аппаратного ускорения видео, а также звук: