Существуют ли образы, которые устанавливают vncserver или что-то подобное, чтобы вы могли, например, добавить дополнительную песочницу вокруг, скажем, Firefox?
Ответ 1
Вы можете просто установить vncserver вместе с Firefox :)
Я выложил образ vnc/firefox здесь: docker pull creack/firefox-vnc
Образ был создан с помощью этого Dockerfile:
# Firefox over VNC
#
# VERSION 0.1
# DOCKER-VERSION 0.2
FROM ubuntu:12.04
# Убедитесь, что репозиторий пакетов обновлен.
RUN echo "deb http://archive.ubuntu.com/ubuntu precise main universe" > /etc/apt/sources.list
RUN apt-get update
# Установите vnc, xvfb для создания "фальшивого" дисплея и firefox
RUN apt-get install -y x11vnc xvfb firefox
RUN mkdir ~/.vnc
# установите пароль
RUN x11vnc -storepasswd 1234 ~/.vnc/passwd
# Автозапуск firefox (возможно, это не самый лучший способ)
RUN bash -c 'echo "firefox" >> /.bashrc'
Это создаст контейнер Docker с VNC с паролем 1234:
Для Docker версии 1.8 или новее:
docker run -p 5900:5900 -e HOME=/ creack/firefox-vnc x11vnc -forever -usepw -create
Для Docker версии 1.3 или новее:
docker run -p 5900 -e HOME=/ creack/firefox-vnc x11vnc -forever -usepw -create
Для Docker до версии 1.3:
docker run -p 5900 creack/firefox-vnc x11vnc -forever -usepw -create
Ответ 2
Xauthority становится проблемой в новых системах. Я могу либо отказаться от любой защиты с помощью xhost перед запуском моих контейнеров докеров, либо передать хорошо подготовленный файл Xauthority. Типичные файлы Xauthority зависят от имени хоста. С докером каждый контейнер может иметь другое имя хоста (устанавливается с помощью docker run -h), но даже установка имени хоста контейнера, идентичного хост-системе, в моем случае не помогла. xeyes (мне нравится этот пример) просто проигнорирует файл cookie и не передаст учетные данные серверу. Следовательно, мы получаем сообщение об ошибке «Протокол не указан. Невозможно открыть дисплей».
Файл Xauthority можно записать таким образом, чтобы имя хоста не имело значения. Нам нужно установить для семейства аутентификации значение «FamilyWild». Я не уверен, есть ли у xauth подходящая для этого командная строка, поэтому вот пример, который сочетает xauth и sed для этого. Нам нужно изменить первые 16 бит вывода nlist. Значение FamilyWild — 65535 или 0xffff.
docker build -t xeyes - << __EOF__
FROM debian
RUN apt-get update
RUN apt-get install -qqy x11-apps
ENV DISPLAY :0
CMD xeyes
__EOF__
XSOCK=/tmp/.X11-unix
XAUTH=/tmp/.docker.xauth
xauth nlist :0 | sed -e 's/^..../ffff/' | xauth -f $XAUTH nmerge -
docker run -ti -v $XSOCK:$XSOCK -v $XAUTH:$XAUTH -e XAUTHORITY=$XAUTH xeyes
Ответ 3
С томами данных докеров очень легко открыть сокет домена xorg unix внутри контейнера.
Например, с таким Dockerfile:
FROM debian
RUN apt-get update
RUN apt-get install -qqy x11-apps
ENV DISPLAY :0
CMD xeyes
Вы могли сделать следующее:
$ docker build -t xeyes - < Dockerfile
$ XSOCK=/tmp/.X11-unix/X0
$ docker run -v $XSOCK:$XSOCK xeyes
Это, конечно, по сути, то же самое, что и X-forwarding. Он предоставляет контейнеру полный доступ к xserver на хосте, поэтому рекомендуется только в том случае, если вы доверяете тому, что находится внутри.
Примечание. Если вас беспокоит безопасность, лучшим решением будет ограничить приложение обязательным или ролевым контролем доступа. Docker обеспечивает довольно хорошую изоляцию, но он был разработан с другой целью. Используйте AppArmor, SELinux или GrSecurity, которые были разработаны для решения вашей проблемы.
Ответ 4
OSX
Есть ответ, который сработал для меня в Ubuntu, однако в OSX докер работает внутри VirtualBox, поэтому решение не работает без дополнительной работы.
У меня это работает с этими дополнительными ингредиентами:
Xquartz (OSX больше не поставляется с сервером X11)
переадресация сокетов с помощью socat (brew install socat)
bash скрипт для запуска контейнера
Я не уверен, что переадресация сокетов для X безопасна, но я предполагаю использовать это только для локального запуска контейнера докеров.
Кроме того, сценарий немного хрупок в том смысле, что получить IP-адрес машины непросто, поскольку она подключена к нашей локальной беспроводной сети, поэтому всегда используется случайный IP-адрес.
Скрипт BASH, который я использую для запуска контейнера:
#!/usr/bin/env bash
CONTAINER=py3:2016-03-23-rc3
COMMAND=/bin/bash
NIC=en0
# Получите ip-адрес
IPADDR=$(ifconfig $NIC | grep "inet " | awk '{print $2}')
DISP_NUM=$(jot -r 1 100 200) # случайное отображение числа между 100 и 200
PORT_NUM=$((6000 + DISP_NUM)) # чтобы несколько экземпляров контейнера не мешали друг другу
socat TCP-LISTEN:${PORT_NUM},reuseaddr,fork UNIX-CLIENT:\"$DISPLAY\" 2>&1 > /dev/null &
XSOCK=/tmp/.X11-unix
XAUTH=/tmp/.docker.xauth.$USER.$$
touch $XAUTH
xauth nlist $DISPLAY | sed -e 's/^..../ffff/' | xauth -f $XAUTH nmerge -
docker run \
-it \
--rm \
--user=$USER \
--workdir="/Users/$USER" \
-v "/Users/$USER:/home/$USER:rw" \
-v $XSOCK:$XSOCK:rw \
-v $XAUTH:$XAUTH:rw \
-e DISPLAY=$IPADDR:$DISP_NUM \
-e XAUTHORITY=$XAUTH \
$CONTAINER \
$COMMAND
rm -f $XAUTH
kill %1 # завершить задание socat, запущенное выше
Я могу заставить xeyes и matplotlib работать с этим подходом.
Windows 7+
В Windows 7+ это немного проще с MobaXterm:
Установите MobaXterm для Windows
Запустите MobaXterm
Настройте X-сервер: Настройки -> X11 (вкладка) -> установите удаленный доступ X11 на полный
Используйте этот сценарий BASH для запуска контейнера:
run_docker.bash:
#!/usr/bin/env bash
CONTAINER=py3:2016-03-23-rc3
COMMAND=/bin/bash
DISPLAY="$(hostname):0"
USER=$(whoami)
docker run \
-it \
--rm \
--user=$USER \
--workdir="/home/$USER" \
-v "/c/Users/$USER:/home/$USER:rw" \
-e DISPLAY \
$CONTAINER \
$COMMAND
Ответ 5
Совместное использование отображения хоста, как указано в некоторых других ответах, имеет два недостатка:
Нарушается изоляция контейнера из-за некоторых утечек безопасности X. Например, кейлоггинг с помощью xev или xinput возможен и удаленное управление хост-приложениями с помощью xdotool.
Приложения могут иметь сбои рендеринга и ошибки плохого доступа к ОЗУ из-за отсутствия общей памяти для расширения X MIT-SHM (также можно исправить с помощью опции снижения уровня изоляции --ipc=host).
Ниже приведен пример сценария для запуска образа докера в Xephyr, который решает эту проблему.
Это позволяет избежать утечек безопасности X, поскольку приложения-докеры работают на вложенном X-сервере.
MIT-SHM отключен, чтобы избежать сбоев доступа к ОЗУ.
Безопасность контейнеров улучшена с помощью --cap-drop ALL --security-opt no-new-privileges. Также пользователь контейнера не является пользователем root.
X cookie создается для ограничения доступа к дисплею Xephyr.
Сценарий ожидает, что некоторые аргументы: сначала оконный менеджер хоста будет запущен в Xephyr, второй — образ докера, и, возможно, третий — будет выполнена команда изображения. Чтобы запустить среду рабочего стола в докере, используйте ":" вместо оконного менеджера хоста.
Закрытие окна Xephyr завершает работу приложений контейнера докеров. Завершение закрепленных приложений закрывает окно Xephyr.
Примеры:
xephyrdocker "openbox --sm-disable" x11docker/lxde pcmanfm
xephyrdocker : x11docker/lxde
xephyrdocker xfwm4 --device /dev/snd jess/nes /games/zelda.rom
xephyrdocker скрипт:
#! /bin/bash
#
# Xephyrdocker: Пример сценария для запуска приложений docker GUI в Xephyr.
#
# Применение:
# Xephyrdocker WINDOWMANAGER DOCKERIMAGE [IMAGECOMMAND [ARGS]]
#
# WINDOWMANAGER хост-менеджер окон для использования с одиночными GUI-приложениями.
# Для запуска без оконного менеджера с хоста используйте ":".
# DOCKERIMAGE докер-образ, содержащий приложения с графическим интерфейсом или рабочий стол.
# IMAGECOMMAND команда для запуска в образе
#
Windowmanager="$1" && shift
Dockerimage="$*"
# пользователь контейнера
Useruid=$(id -u)
Usergid=$(id -g)
Username="$(id -un)"
[ "$Useruid" = "0" ] && Useruid=1000 && Usergid=1000 && Username="user$Useruid"
# Найдите свободный номер дисплея
for ((Newdisplaynumber=1 ; Newdisplaynumber <= 100 ; Newdisplaynumber++)) ; do
[ -e /tmp/.X11-unix/X$Newdisplaynumber ] || break
done
Newxsocket=/tmp/.X11-unix/X$Newdisplaynumber
# кэш-папка и файлы
Cachefolder=/tmp/Xephyrdocker_X$Newdisplaynumber
[ -e "$Cachefolder" ] && rm -R "$Cachefolder"
mkdir -p $Cachefolder
Xclientcookie=$Cachefolder/Xcookie.client
Xservercookie=$Cachefolder/Xcookie.server
Xinitrc=$Cachefolder/xinitrc
Etcpasswd=$Cachefolder/passwd
# команда для запуска docker
# --rm созданный контейнер будет отброшен.
# -e DISPLAY=$Newdisplay установить переменную окружения для нового дисплея
# -e XAUTHORITY=/Xcookie установить переменную окружения XAUTHORITY на предоставленный файл cookie
# -v $Xclientcookie:/Xcookie:ro предоставить файл cookie контейнеру
# -v $NewXsocket:$NewXsocket:ro Поделиться новым X-образным сокетом Xephyr
# --user $Useruid:$Usergid Безопасность: избегать root в контейнере
# -v $Etcpasswd:/etc/passwd:ro /etc/passwd файл с записью пользователя
# --group-add audio Разрешите доступ к /dev/snd при совместном использовании с '--device /dev/snd'
# --cap-drop ALL Безопасность: отключите ненужные возможности
# --security-opt no-new-privileges Безопасность: запретить новые привилегии
Dockercommand="docker run --rm \
-e DISPLAY=:$Newdisplaynumber \
-e XAUTHORITY=/Xcookie \
-v $Xclientcookie:/Xcookie:ro \
-v $Newxsocket:$Newxsocket:rw \
--user $Useruid:$Usergid \
-v $Etcpasswd:/etc/passwd:ro \
--group-add audio \
--env HOME=/tmp \
--cap-drop ALL \
--security-opt no-new-privileges \
$(command -v docker-init >/dev/null && echo --init) \
$Dockerimage"
echo "docker command:
$Dockercommand
"
# command to run Xorg or Xephyr
# /usr/bin/Xephyr для xinit должен быть указан абсолютный путь к исполняемому файлу X-сервера
# :$Newdisplaynumber первый аргумент должен быть новым дисплеем
# -auth $Xservercookie путь к файлу cookie для X-сервера. Должен отличаться от файла cookie клиента, не знаю почему.
# -extension MIT-SHM отключить MIT-SHM, чтобы избежать глюков рендеринга и плохого доступа к оперативной памяти (+ вместо - включает его)
# -nolisten tcp отключить соединения tcp в целях безопасности
# -retro красивый вид в стиле ретро
Xcommand="/usr/bin/Xephyr :$Newdisplaynumber \
-auth $Xservercookie \
-extension MIT-SHM \
-nolisten tcp \
-screen 1000x750x24 \
-retro"
echo "X server command:
$Xcommand
"
# создать /etc/passwd с непривилегированным пользователем
echo "root:x:0:0:root:/root:/bin/sh" >$Etcpasswd
echo "$Username:x:$Useruid:$Usergid:$Username,,,:/tmp:/bin/sh" >> $Etcpasswd
# создать xinitrc
{ echo "#! /bin/bash"
echo "# установить переменные окружения на новый дисплей и новый cookie"
echo "export DISPLAY=:$Newdisplaynumber"
echo "export XAUTHORITY=$Xclientcookie"
echo "# та же раскладка клавиатуры, что и на хосте"
echo "echo '$(setxkbmap -display $DISPLAY -print)' | xkbcomp - :$Newdisplaynumber"
echo "# создать новый файл cookie XAUTHORITY"
echo ":> $Xclientcookie"
echo "xauth add :$Newdisplaynumber . $(mcookie)"
echo "# создать подготовленный файл cookie с идентификацией localhost, отключенной по ffff,".
echo "# необходим, если X-сокет используется совместно, а не подключается по tcp. ffff означает "familiy wild"".
echo 'Cookie=$(xauth nlist '":$Newdisplaynumber | sed -e 's/^..../ffff/')"
echo 'echo $Cookie | xauth -f '$Xclientcookie' nmerge -'
echo "cp $Xclientcookie $Xservercookie"
echo "chmod 644 $Xclientcookie"
echo "# запустить оконный менеджер в Xephyr".
echo $Windowmanager' & Windowmanagerpid=$!'
echo "# show docker log"
echo 'tail --retry -n +1 -F '$Dockerlogfile' 2>/dev/null & Tailpid=$!'
echo "# run docker"
echo "$Dockercommand"
} > $Xinitrc
xinit $Xinitrc -- $Xcommand
rm -Rf $Cachefolder
Этот сценарий поддерживается в x11docker.
Linux