Пользователь
0,0
рейтинг
20 октября 2014 в 15:51

Администрирование → Docker: запуск графических приложений в контейнерах

Строго говоря, Docker не был создан для подобного рода вещей, а именно запуска графических приложений. Однако, время от времени в темах про Docker звучат вопросы о том, нельзя ли запустить GUI-приложение в контейнере. Причины могут быть разные, но чаще всего, это желание сменить излишне громоздкую виртуальную машину на что-то полегче, не потеряв в удобстве и сохранив при этом достаточный уровень изоляции.

Это небольшой обзор способов запуска графических приложений в контейнерах Docker.

Оглавление



Монтирование устройств


Один из самых простых способов заставить контейнер говорить и показывать — это дать ему доступ к нашему экрану и звуковым устройствам.

Для того, чтобы приложения в контейнере могли подключиться к нашему экрану можно воспользоваться доменными сокетами Unix для X11, которые, обычно, лежать в директории /tmp/.X11-unix. Сокеты можно расшарить, смонтировав эту директорию с помощью параметра -v. Также необходимо настроить переменную окружения DISPLAY, которая указывает приложениям экран для вывода графики. Так как выводить мы будем на наш экран, то достаточно скопировать значение DISPLAY хостовой машины. Обычно, это :0.0 или просто :0. Пустое имя хоста (перед двоеточием) подразумевает локальное соединение с использованием самого эффективного транспорта, что в большинстве случаев означает доменные сокеты Unix — как раз то, что нам нужно:

$ docker run -e DISPLAY=unix$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix <image>

Приставка «unix» к DISPLAY здесь для явного указания использования unix-сокетов, но чаще всего в этом нет необходимости.

Ошибка авторизации


При запуске можно столкнуться с ошибкой вида:

No protocol specified
Error: cannot open display: unix:0.0

Такое происходит, когда расширение Xsecurity блокирует неавторизованные подключения к X-серверу. Решить эту проблему можно, например, разрешив все локальные несетевые подключения:

$ xhost +local:

Или ограничиться разрешением только для root-пользователя:

$ xhost +si:localuser:root

В большинстве случаев этого должно быть достаточно.

Для тех, кто не ищет легких путей
Другим вариантом будет дать контейнеру возможность самостоятельно авторизовываться на X-сервере с помощью заранее подготовленного и смонтированного Xauthority-файла. Создать такой можно с помощью утилиты xauth, которая способна извлекать и экспортировать данные для авторизации. Загвоздка, однако, в том, что такая авторизационная запись содержит в себе имя хоста, на котором запущен X-сервер. Просто скопировать ее в контейнер бесполезно — запись будет проигнорирована при попытке локального подключения к серверу. Решить эту проблему можно по-разному. Опишу пару способов.

Подмена имени хоста. Идея проста. Извлекаем авторизационную запись с помощью xauth list, меняем имя хоста на другое (нужно придумать заранее) и экспортируем получившийся ключ в Xauthority-файл, который затем монтируем в контейнер:
$ DOCKER_CONTAINER_HOSTNAME=foobar
$ xauth list $DISPLAY | sed -e "s/$HOSTNAME/$DOCKER_CONTAINER_HOSTNAME/" | xargs xauth -f /tmp/.docker.Xauthority add
$ docker run -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix \
    -v /tmp/.docker.Xauthority -e XAUTHORITY=/tmp/.docker.Xauthority -h $DOCKER_CONTAINER_HOSTNAME <image>

Подмена кода соединения. Первые два байта в каждой записи из Xauthority-файла содержат код соответствия семейству соединений (TCP/IP, DECnet, локальные соединения). Если этому параметру присвоить специальное значение FamilyWild (код 65535 или 0xffff), то запись будет соответствовать любому экрану и может быть использована для любого соединения (то есть имя хоста не будет иметь значения):
$ xauth nlist $DISPLAY | sed -e 's/^..../ffff/' | xauth -f /tmp/.docker.Xauthority nmerge -
$ docker run -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix \
    -v /tmp/.docker.Xauthority -e XAUTHORITY=/tmp/.docker.Xauthority <image>

Подсмотрено на stackoverflow.

А что со звуком?


Подключение звуковых устройств также не составляет большого труда. В версиях Docker до 1.2 их можно смонтировать с помощью параметра -v, при этом контейнер должен быть запущен в привилегированном режиме:

$ docker run -v /dev/snd:/dev/snd --privileged <image>

В Docker 1.2 был добавлен специальный параметр --device для подключения устройств. К сожалению, на данный момент (версия 1.2), --device в качестве значения может принимать только одно устройство за раз, а значит придется явно перечислять их все. Например:

$ docker run --device=/dev/snd/controlC0 --device=/dev/snd/pcmC0D0p --device=/dev/snd/seq --device=/dev/snd/timer <image>

Возможно, функция обработки всех устройств в директории через --device будет добавлена в будущих релизах (на github есть соответствующий запрос).

В итоге


Суммируя, команда для запуска контейнера с графическим приложением выглядит примерно так:

$ docker run -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY=unix$DISPLAY \
    --device=/dev/snd/controlC0 --device=/dev/snd/pcmC0D0p \
    --device=/dev/snd/seq --device=/dev/snd/timer <image>

Или, для Docker версии ниже 1.2:

$ docker run -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY=unix$DISPLAY \
    -v /dev/snd:/dev/snd --privileged <image>

Пример №1


Я подумал, что для проверки графики и звука подойдет какой-нибудь аудиоплеер с графическим интерфейсом и выбрал DeaDBeeF в качестве подопытного. Для запуска нам не понадобиться ничего, кроме образа с установленным плеером.

Dockerfile:
FROM debian:wheezy

ENV DEBIAN_FRONTEND noninteractive

RUN apt-get update

RUN apt-get install -yq wget

# установка deadbeef
RUN wget -P /tmp 'http://sourceforge.net/projects/deadbeef/files/debian/0.6.2/deadbeef-static_0.6.2-2_amd64.deb' \
 && dpkg -i /tmp/deadbeef-static_0.6.2-2_amd64.deb || true \
 && apt-get install -fyq --no-install-recommends \
 && ln -s /opt/deadbeef/bin/deadbeef /usr/local/bin/deadbeef \
 && rm /tmp/deadbeef-static_0.6.2-2_amd64.deb

# будем запускать проигрыватель вместе с контейнером
ENTRYPOINT ["/opt/deadbeef/bin/deadbeef"]

Соберем образ:

$ docker build -t deadbeef .

Теперь можно запустить его и послушать, например, радио (если решите попробовать — учтите, что плеер запустится на полной громкости):

$ docker run --rm -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY=unix$DISPLAY \
    --device=/dev/snd/controlC0 --device=/dev/snd/pcmC0D0p --device=/dev/snd/seq --device=/dev/snd/timer \
    deadbeef http://94.25.53.133/ultra-128.mp3

Результатом должен стать работающий плеер


SSH -X


И это все, что вам нужно! Ну, почти. Параметр -X при создании ssh соединения включает перенаправление X11, что позволяет отображать на локальной машине графическое приложение, запущенное на удаленной. В данном случае под удаленной машиной можно понимать docker-контейнер.

В контейнере при этом должен быть установлен и запущен ssh-сервер. Также следует удостовериться, что в настройках сервера разрешено перенаправление X11. Проверить это можно заглянув в /etc/ssh/sshd_config и поискав параметр X11Forwarding (или его синонимы: ForwardX11, AllowX11Forwarding), который должен быть установлен в yes:

X11Forwarding yes

А звук?


В ssh нет «волшебной» опции для перенаправления звука. Но настроить его все-таки возможно. Например, с помощью звукового сервера PulseAudio, для которого можно разрешить клиентский доступ «извне» (например, из контейнера). Проще всего это сделать через paprefs. Установив paprefs надо зайти в настройки PulseAudio и на вкладке «Network Settings» поставить галочку напротив «Enable network access to local sound devices» (включение сетевого доступа к локальным звуковым устройствам). Там же можно найти опцию «Don't require authentication» (не требовать авторизации). Включение этой опции разрешит неавторизованный доступ к серверу, что может упростить настройку docker-контейнеров. Для авторизованного же доступа необходимо скопировать в контейнер файл ~/.pulse-cookie.

После изменения настроек PulseAudio следует перезапустить:

$ sudo service pulseaudio restart
или
$ pulseaudio -k && pulseaudio --start

В некоторых случаях может потребоваться перезагрузка. Проверить принялись ли настройки можно с помощью команды pax11publish, вывод которой должен выглядеть примерно так:

Server: <...>unix:/run/user/1000/pulse/native tcp:<hostname>:4713 tcp6:<hostname>:4713
Cookie: <...>

Здесь можно увидеть, что аудиосервер «слушает» на unix-сокете (unix:/run/user/1000/pulse/native), 4713-м TCP и TCP6 портах (стандартный порт для PulseAudio).

Для того, чтобы X-приложения в контейнере подключались к нашему pulse-серверу нужно указать его адрес в переменной окружения PULSE_SERVER:

$ PULSE_SERVER=tcp:172.17.42.1:4713

Здесь «172.17.42.1» — это адрес моего docker-хоста. Узнать этот адрес можно, например, так:

$ ip route | awk '/docker/ { print $NF }'
172.17.42.1

То есть строка «tcp:172.17.42.1:4713» говорит, что подключиться к pulse-серверу можно по IP-адресу 172.17.42.1, где он слушает TCP-порт 4713.

В общем случае такой настройки достаточно. Отмечу только, что при использовании вышеописанного метода весь звук будет передаваться в открытом виде (нешифрованном), что в случае использования контейнера на локальном компьютере не имеет особого значения. Но при желании этот трафик можно и зашифровать. Для этого PULSE_SERVER следует настроить на любой свободный порт на localhost (например: «tcp:localhost:64713»). В результате аудиопоток будет идти на локальный порт 64713, который в свою очередь можно пробросить на 4713-й порт хостовой машины с помощью ssh -R:

$ ssh -X -R 64713:localhost:4713 <user>@<hostname>

Аудиоданные при этом будут передаваться по зашифрованному каналу.

Пример №2


Как и в предыдущем примере опишем образ плеера DeaDBeF c ssh-сервером. Я буду исходить из того, что все описанные выше предварительные настройки PulseAudio проведены, а значит остается только приступить к созданию docker-образа.

Код установки плеера будет повторят код из примера ранее. Нам лишь остается добавить установку openssh-сервера.

На этот раз кроме Dockerfile создадим еще один файл — entrypoint.sh. Это скрипт для «точки входа», т.е. он будет выполняться каждый раз при запуске контейнера. В нем мы будем создавать пользователя со случайным паролем, настраивать переменную окружения PULSE_SERVER и запускать ssh-сервер.

Dockerfile:
FROM debian:wheezy

ENV DEBIAN_FRONTEND noninteractive

RUN apt-get update

RUN apt-get install -yq wget

# установка deadbeef
RUN wget -P /tmp 'http://sourceforge.net/projects/deadbeef/files/debian/0.6.2/deadbeef-static_0.6.2-2_amd64.deb' \
 && dpkg -i /tmp/deadbeef-static_0.6.2-2_amd64.deb || true \
 && apt-get install -fyq --no-install-recommends \
 && ln -s /opt/deadbeef/bin/deadbeef /usr/local/bin/deadbeef \
 && rm /tmp/deadbeef-static_0.6.2-2_amd64.deb

# минимальная установка pulseaudio
RUN apt-get install -yq --no-install-recommends pulseaudio

RUN apt-get install -yq \
      pwgen \
      openssh-server

# создаем директорию необходимую для запуска ssh-сервера
RUN mkdir -p /var/run/sshd

ADD entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh

EXPOSE 22

ENTRYPOINT ["/entrypoint.sh"]

Порт и адрес pulse-сервера будем передавать в качестве параметров при запуске контейнера, чтобы иметь возможность поменять их на нестандартные (не забыв о значениях по умолчанию).

entrypoint.sh:
#!/bin/bash

# формируем переменную окружения PULSE_SERVER
PA_PORT=${PA_PORT:-4713}
PA_HOST=${PA_HOST:-localhost}
PA_SERVER="tcp:$PA_HOST:$PA_PORT"

# имя пользователя для подключения
DOCKER_USER=dockerx

# генерируем пароль пользователя
DOCKER_PASSWORD=$(pwgen -c -n -1 12)
DOCKER_ENCRYPTED_PASSWORD=$(perl -e 'print crypt('"$DOCKER_PASSWORD"', "aa")')

# выводим имя и пароль пользователя,
# чтобы их можно было увидеть с помощью docker logs
echo User: $DOCKER_USER
echo Password: $DOCKER_PASSWORD

# создаем пользователя
useradd --create-home --home-dir /home/$DOCKER_USER --password $DOCKER_ENCRYPTED_PASSWORD \
        --shell /bin/bash --user-group $DOCKER_USER

# добавляем инициализацию и экспорт PULSE_SERVER в ~/.profile для нового пользователя,
# чтобы она была доступна во время его сессии
echo "PULSE_SERVER=$PA_SERVER; export PULSE_SERVER" >> /home/$DOCKER_USER/.profile

# запускаем ssh-сервер
exec /usr/sbin/sshd -D

Соберем образ:

$ docker build -t deadbeef:ssh .

Запустим контейнер, не забыв указать хост PulseAudio (порт я опущу, так как у меня он стандартный), и назовем его «dead_player»:

$ docker run -d -p 2222:22 -e PA_HOST="172.17.42.1" --name=dead_player deadbeef:ssh

Узнать пароль пользователя для подключения можно с помощью команды docker logs:

$ docker logs dead_player
User: dockerx
Password: vai0ay7OuNga

Для подключения по ssh можно использовать адрес как самого контейнера, так и адрес docker-хоста (при этом порт подключения будет отличаться от стандартного 22-го; в данном случае это будет 2222 — тот, который мы указали при запуске контейнера). Узнать IP контейнера можно с помощью команды docker inspect:

$ docker inspect --format '{{ .NetworkSettings.IPAddress }}' dead_player
172.17.0.69

Подключение к контейнеру:

$ ssh -X dockerx@172.17.0.69

Или через docker-шлюз:

$ ssh -X -p 2222 dockerx@172.17.42.1

Наконец, после авторизации, можно расслабиться и послушать музыку:

dockerx@5e3add235060:~$ deadbeef


Subuser


Subuser позволяет запускать программы в изолированных контейнерах docker, беря на себя всю работу, связанную с созданием и настройкой контейнеров, поэтому пользоваться им могут даже люди, ничего не знающие о docker. Во всяком случае, такова идея проекта. Для каждого приложения-контейнера при этом устанавливаются ограничения в зависимости от его назначения — ограниченный доступ к директориям хоста, к сети, звуковым устройствам и т.д. По сути, subuser реализует удобную обертку над описанным здесь первым способом запуска графических приложений, так как запуск осуществляется с помощью монтирования нужных директорий, устройств и т.д.

К каждому создаваемому образу прилагается файл permissions.json, который определяет настройки доступа для приложения. Так, например, выглядит этот файл для образа vim:

{
  "description"                : "Simple universal text editor."
  ,"maintainer"                : "Timothy Hobbs <timothyhobbs (at) seznam dot cz>"
  // Путь к исполняемому файлу внутри контейнера
  ,"executable"                : "/usr/bin/vim"
  // Список директорий, к которым программа должна иметь доступ с правами на чтение/запись
  // Пути задаются относительно вашей домашней директории. Например: "Downloads" преобразуется в "$HOME/Downloads"
  ,"user-dirs"                 : [ 'Downloads', 'Documents' ]  // По умолчанию: []
  // Разрешить программе создавать X11 окна
  ,"x11"                       : true       // По умолчанию: false
  // Разрешить программе использовать вашу звуковую карту и устройства записи
  ,"sound-card"                : true       // По умолчанию: false
  // Дать программе доступ к директории, из которой она была запущена с правами на чтение/запись
  ,"access-working-directory"  : true       // По умолчанию: false
  // Дать программе доступ к интернету
  ,"allow-network-access"      : true       // По умолчанию: false
}

Subuser имеет репозиторий (на данный момент — небольшой) готовых приложений, список которых можно увидеть с помощью команды:

$ subuser list available

Добавить приложение из репозитория можно так:

$ subuser subuser add firefox-flash firefox-flash@default

Эта команда установит приложение, назвав его firefox-flash, основанное на одноименном образе из репозитория по умолчанию.

Запуск приложения выглядит так:

$ subuser run firefox-flash

Кроме использования стандартного репозитория, можно создавать и добавлять свои собственные subuser-приложения.

Проект довольно молодой и пока выглядит сыроватым, но свою задачу он выполняет. Код проекта можно найти на github: subuser-security/subuser

Пример №3


Создадим, subuser-приложение для все того же DeaDBeef. Для демонстрации создадим локальный репозиторий subuser (ни что иное как git-репозиторий). Директория ~/.subuser-repo сойдет. В ней следует инициализировать git-репозиторий:

$ mkdir ~/.subuser-repo
$ cd ~/.subuser-repo
$ git init

Здесь же создадим директорию для DeaDBeef:

$ mkdir deadbeef

Структура директории для subuser-образа выглядит следующим образом:

image-name/
  docker-image/
    SubuserImagefile
    docker-build-context...
  permissions.json

SubuserImagefile — это тот же Dockerfile. Разница лишь в возможности использовать инструкцию FROM-SUBUSER-IMAGE, которая принимает идентификатор существующего subuser-образа в качестве аргумента. Список доступных базовых образов можно посмотреть здесь: SubuserBaseImages.

Итак, подготовив структуру каталога, остается создать два файла: SubuserImagefile и permissions.json.

SubuserImagefile практически ничем не будет отличаться от приведенного ранее Dockerfile:

FROM debian:wheezy

ENV DEBIAN_FRONTEND noninteractive

RUN apt-get update

RUN apt-get install -yq wget

# установка deadbeef
RUN wget -P /tmp 'http://sourceforge.net/projects/deadbeef/files/debian/0.6.2/deadbeef-static_0.6.2-2_amd64.deb' \
 && dpkg -i /tmp/deadbeef-static_0.6.2-2_amd64.deb || true \
 && apt-get install -fyq --no-install-recommends \
 && ln -s /opt/deadbeef/bin/deadbeef /usr/local/bin/deadbeef \
 && rm /tmp/deadbeef-static_0.6.2-2_amd64.deb

В permissions.json опишем параметры доступа для нашего плеера. Нам понадобиться экран, звук и интернет:
{
 "description": "Ultimate Music Player For GNU/Linux",
 "maintainer": "Humble Me",
 "executable": "/opt/deadbeef/bin/deadbeef",
 "sound-card": true,
 "x11": true,
 "user-dirs": [
  "Music"
 ],
 "allow-network-access": true,
 "as-root": true
}

Параметр as-root позволяет запускать приложения в контейнере от имени root. По умолчанию subuser запускает контейнер с параметром --user, присваивая ему идентификатор текущего пользователя. Но deadbeef при этом отказывается запускаться (не может создать сокет-файл в домашней директории, которой не существует).

Закоммитим изменения в нашем импровизированном subuser-репозитории:

~/.subuser-repo $ git add . && git commit -m 'initial commit'

Теперь можно установить плеер из локального репозитория:

$ subuser subuser add deadbeef deadbeef@file:////home/silentvick/.subuser-repo

Наконец, запустить его можно с помощью следующей команды:

$ subuser run deadbeef


Удаленный рабочий стол


Раз уж контейнер так похож на виртуальную машину, а взаимодействие с ним напоминает сетевое, то в голову сразу приходит решение в виде систем удаленного доступа, таких как: TightVNC, Xpra, X2Go и т.п.

Такой вариант выглядит более накладным, так как требует установки дополнительного софта — как в контейнере, так и на локальном компьютере. Но у него есть и преимущества, например:
  • высокая изоляция контейнера, что увеличивает безопасность при запуске подозрительных программ
  • шифрование траффика
  • оптимизация передачи данных по сети
  • мультиплатформенность
  • а также возможность запуска полноценного графического окружения

Пример №4


В качестве примера я воспользуюсь X2Go, т.к. из опробованных мною решений он приглянулся своей простотой в использовании, а также встроенной поддержкой трансляции звука. Для подключения к x2go-серверу используется специальная программа x2goclient. Подробнее об установке сервера и клиента можно найти на официальном сайте проекта.

Что касается того, что мы будем ставить, то можно, конечно, в контейнер установить полноценную графическую оболочку вроде LXDE, XFCE, или даже Gnome с KDE. Но мне это показалось излишним для условий данного примера. Нам хватит и OpenBox.

В контейнере кроме x2go-сервера также понадобится ssh-сервер. Поэтому код будет во многом похож на приведенный в примере №2. В той части, где ставится плеер, openssh-сервер, и сервер pulseaudio. То есть останется только добавить x2go-сервер и openbox:

Dockerfile:
FROM debian:wheezy

ENV DEBIAN_FRONTEND noninteractive

RUN apt-get update

RUN apt-get install -yq wget

# установка deadbeef
RUN wget -P /tmp 'http://sourceforge.net/projects/deadbeef/files/debian/0.6.2/deadbeef-static_0.6.2-2_amd64.deb' \
 && dpkg -i /tmp/deadbeef-static_0.6.2-2_amd64.deb || true \
 && apt-get install -fyq --no-install-recommends \
 && ln -s /opt/deadbeef/bin/deadbeef /usr/local/bin/deadbeef \
 && rm /tmp/deadbeef-static_0.6.2-2_amd64.deb

# минимальная установка pulseaudio
RUN apt-get install -yq --no-install-recommends pulseaudio

# устанавливаем ssh-сервер и утилиту pwgen для генерации пароля
RUN apt-get install -yq \
      pwgen \
      openssh-server

# создаем директорию, необходимую для запуска ssh-сервера
RUN mkdir -p /var/run/sshd

# установка x2go-сервера
RUN echo 'deb http://packages.x2go.org/debian wheezy main' >> /etc/apt/sources.list \
 && echo 'deb-src http://packages.x2go.org/debian wheezy main' >> /etc/apt/sources.list \
 && apt-key adv --recv-keys --keyserver keys.gnupg.net E1F958385BFE2B6E \
 && apt-get update && apt-get install -yq x2go-keyring \
 && apt-get update && apt-get install -yq \
      x2goserver \
      x2goserver-xsession

# установка openbox
RUN apt-get install -yq openbox

# Добавляем пункт запуска DeaDBeeF в меню OpenBox.
#
# Для демонстрации сгодится и такой прямолинейный метод,
# но, в общем случае, лучше создать свой файл menu.xml и добавлять его через ADD
RUN sed -i '/<.*id="root-menu".*>/a <item label="DeaDBeeF"><action name="Execute"><execute>deadbeef</execute></action></item>' \
      /etc/xdg/openbox/menu.xml

ADD entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh

EXPOSE 22

ENTRYPOINT ["/entrypoint.sh"]

Также немного изменим скрипт entrypoint.sh. Нам теперь нет необходимости настраивать переменную окружения PULSE_SERVER, поэтому от этого кода можно избавиться. Кроме того, пользователя для подключения следует добавить в группу x2gouser, иначе он не сможет запустить x2go-сессию:

#!/bin/bash

# имя пользователя для подключения
DOCKER_USER=dockerx
X2GO_GROUP=x2gouser

# генерируем пароль пользователя
DOCKER_PASSWORD=$(pwgen -c -n -1 12)
DOCKER_ENCRYPTED_PASSWORD=$(perl -e 'print crypt('"$DOCKER_PASSWORD"', "aa")')

# выводим имя и пароль пользователя,
# чтобы их можно было увидеть с помощью docker logs
echo User: $DOCKER_USER
echo Password: $DOCKER_PASSWORD

# создаем пользователя
useradd --create-home --home-dir /home/$DOCKER_USER --password $DOCKER_ENCRYPTED_PASSWORD \
        --shell /bin/bash --groups $X2GO_GROUP --user-group $DOCKER_USER

# запускаем ssh-сервер
exec /usr/sbin/sshd -D

Соберем образ:

$ docker build -t deadbeef:x2go .

Запустим контейнер в режиме демона:

$ docker run -d -p 2222:22 --name=dead_player deadbeef:x2go

Теперь, когда контейнер работает, к нему можно подключиться с помощью x2goclient, как мы подключались бы к любой удаленной машине. В настройках подключения в качестве хоста следует указать адрес либо самого контейнера, либо docker-хоста (в этом случае стоит также учесть нестандартный порт подключения ssh). Узнать логин и пароль для авторизации можно с помощью команды docker logs, как показано в примере №2. Для запуска openbox-сесcии в настройках «Session type» следует выбрать «Custom desktop» и в поле «Command» прописать «openbox-session».

После подключения можно запустить плеер через меню openbox (правый клик мышью) и проверить его работоспособность:
скриншот


При желании можно добиться и более опрятного вида:
скриншот


Но это уже совсем другая история.

Добавлю еще, что X2Go позволяет запускать одиночные приложения, так, как если бы они запускались на локальной машине. Для этого надо в клиенте в настройках «Session type» выбрать «Single application» и в «Command» прописать путь к исполняемому файлу. При этом в контейнере даже нет необходимости устанавливать графическую среду — достаточно иметь X2Go-сервер и желаемое приложение.

Ссылки по теме


  • Desktop integration examples — пара примеров образов для запуска с помощью монтирования устройств из официального репозитория Docker
  • jlund/docker-chrome-pulseaudio — образ Google Chrome, использующий pulseaudio для передачи звука
  • tomparys/skype — skype в контейнере (для звука используется pulseaudio)
  • dockerfile/ubuntu-desktop — образ Ubuntu LXDE с VNC-сервером на борту
  • rogaha/docker-desktop — Ubuntu+FluxBox с использованием Xpra
  • paimpozhil/DockerX2go — несколько образов с разными ОС, использующие X2go
  • thewtex/docker-opengl-nvidia — образ, позволяющий запускать приложения, использующие проприетарные драйвера Nvidia с поддержкой OpenGL
  • Can you run GUI apps in a docker container? — обсуждение вопроса на stackoverflow
@silentvick
карма
15,0
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Администрирование

Комментарии (14)

  • +1
    $ xhost +local:
    Вот кейлоггеру-то раздолье будет. А Xephyr/Xnest чем не угодили?
    • 0
      Во многих статьях, которые мне попадались, часто вообще советуют использовать xhost +, а заботы о «защите» возложить на AppArmor, SELinux и т.п. :) Мне кажется, такое решение изначально не нацелено на полную изоляцию приложений, так как оно основано на встроенных возможностях самого docker, а он создавался, грубо говоря, не для этого.

      А Xephyr/Xnest чем не угодили?

      К сожалению, мало, что про них знаю — не довелось попробовать пока. Вы имеете ввиду какую-то связку Docker+Xephyr?
  • 0
    Причины могут быть разные, но чаще всего, это желание сменить излишне громоздкую виртуальную машину на что-то полегче, не потеряв в удобстве и сохранив при этом достаточный уровень изоляции.


    Какой уж тут уровень изоляции — контейнеру отдана в полный доступ целая куча устройств. С этим подходом докер превращается из средства контейнеризации в эдакий файрвол между программой и ресурсами ОС.
    • 0
      докер превращается из средства контейнеризации

      В chroot
      • 0
        «If you have the ability to use chroot() you are root. If you are root you can walk happily out of any chroot by a thousand other means.» © Alan Cox
        Не уверен, что с LXC такое прокатит…
        • 0
          Тогда fakeroot
          • 0
            $ man fakeroot

            Fakeroot runs a command in an environment wherein it appears to have root privileges for file manipulation. This is useful for allowing users to create archives (tar, ar, .deb etc.) with files in them with root permissions/ownership.


            Ещё варианты? :)
            • 0
              Программа думает, что она запущена от рута. На самом деле это не так.
              • 0
                Позволю себе поянить смысл моего первого комментария с цитатой Алана Кокса:
                LXC в chroot не превратится хотя бы потому, что в lxc изоляция происходит на уровне ядра, что даёт меньше шансов выбраться за пределы контейнера, нежели за пределы chroot'а

                Так же LXC позволяет влиять на потребление ресурсов контейнерами (cpu, ram, ...), изолировать пространство процессов, сетевой стек…

                В общем, chroot'у до LXC ой как далеко, даже если LXC сильно-сильно «сконфигурировать» :)

                На закуску из man'а chroot'а:

                This call does not change the current working directory, so that after the call '.' can be outside the tree rooted at '/'. In particular, the superuser can escape from a «chroot jail» by doing:

                mkdir foo; chroot foo; cd…

                This call does not close open file descriptors, and such file descriptors may allow access to files outside the chroot tree.
  • +1
    Мой вариант: github.com/Kagami/kagome
    Пока в статусе proof of concept, но планирую допиливать. Если, конечно, что-то более интересное не появится.
    Так-то подобных проектов много (особенно тема стала популярна с развитием легковесных контейнеров): sandstorm.io/, coreos.com/, qubes-os.org/ от Рутковской, наконец.
    • 0
      Интересно, я сам задумывался над чем-то вроде light версии QubesOS — более легкой и менее защищенной. Хотя я так понимаю в случае с PV domN, оверхэд и не такой большой. А как у вас обстоят дела с opengl? В QubesOS его нет by design, что немного обидно терять возможность иметь webgl, vdpau и прочее.
      • 0
        Судя по рассылке QubeOS, я так понял что у них даже memory deduplication выключен: groups.google.com/forum/#!msg/qubes-devel/tfMk_g7Y1tQ/iSLQ2jNyZH8J. А значит оверхэд получается очень даже приличным. Хотя вообще про QubeOS мало что могу сказать, но как концепт она гораздо более стройнее и привлекательнее и разрабатывают её люди с неплохим бэкграундом в области безопасности.
        Что мне в QubeOS и подобных дистрибутивах не очень нравится — так это то, что это полностью отдельный дистрибутив со своей экосистемой, а значит многие плюсы популярных систем вроде Debian сводятся на нет. Мне ближе по душе использование в родном дистрибутивы средств изоляции, которые достаточно надёжны для большинства задач: отдельные пользователи, отдельные иксы, MAC, контейнеры и т.д.

        Про OpenGL, честно говоря, ещё не думал, но вот судя по тому, что в Xephyr поддерживается акселлерация и пробросить иксы с акселлерацией внутрь контейнера возможно, в принципе проблема решаема.
        Хотя я, честно говоря, в последнее время больше смотрю в сторону использования отдельной машины для небезопасных и/или сложно изолируемых приложений. Заодно там и Windows можно второй системой для некоторых приложений. Получается и проще, и безопаснее.
  • 0
    Класс, у меня появилась надежда запилить легковесное средство для работы с jack на двух аудиокартах!
  • 0
    А ускорение графики? Я бы в варианте «Монтирование» смонтировал ещё /dev/dri/

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