Можно ли запускать графические приложения в контейнере Docker?


Как вы можете запускать графические приложения в настройки контейнер?

есть ли какие-либо изображения, которые настраивают vncserver или что - то, что вы можете - например-добавить дополнительную песочницу speedbump вокруг, скажем, Firefox?

19 309

19 ответов:

вы можете просто установить vncserver вместе с Firefox:)

Я нажал изображение, vnc / firefox, здесь:docker pull creack/firefox-vnc

изображение было сделано с помощью этого Dockerfile:

# Firefox over VNC
#
# VERSION               0.1
# DOCKER-VERSION        0.2

FROM    ubuntu:12.04
# Make sure the package repository is up to date
RUN     echo "deb http://archive.ubuntu.com/ubuntu precise main universe" > /etc/apt/sources.list
RUN     apt-get update

# Install vnc, xvfb in order to create a 'fake' display and firefox
RUN     apt-get install -y x11vnc xvfb firefox
RUN     mkdir ~/.vnc
# Setup a password
RUN     x11vnc -storepasswd 1234 ~/.vnc/passwd
# Autostart firefox (might not be the best way to do it, but it does the trick)
RUN     bash -c 'echo "firefox" >> /.bashrc'

это создаст контейнер Docker под управлением VNC с паролем 1234:

для Docker версии 1.3 или новее:

docker run -p 5900 -e HOME=/ creack/firefox-vnc x11vnc -forever -usepw -create

для Докера до версии 1.3:

docker run -p 5900 creack/firefox-vnc x11vnc -forever -usepw -create

Xauthority становится проблемой с новыми системами. Я могу либо отказаться от любой защиты с помощью xhost + перед запуском моих контейнеров docker, либо я могу передать хорошо подготовленный файл Xauthority. Типичный Xauthority файлы определенного имени хоста. С помощью docker каждый контейнер может иметь другое имя хоста (заданное с помощью docker run-h), но даже установка имени хоста контейнера, идентичного хост-системе, не помогла в моем случае. xeyes (мне нравится этот пример) просто проигнорирует волшебное печенье и не передавайте учетные данные на сервер. Следовательно, мы получаем сообщение об ошибке "no protocol specified Cannot open display"

файл 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

Я только что нашла эту запись в блоге и хочу поделиться им с вами, потому что я думаю, что это лучший способ, чтобы сделать это и это так легко.

http://fabiorehm.com/blog/2014/09/11/running-gui-apps-with-docker/

плюсы:
+ нет Х серверных вещей в контейнере docker
+ не требуется клиент/сервер vnc
+ нет ssh с X переадресацией
+ гораздо меньшие контейнеры докера

плюсы:
- использование x на хосте (не означает для безопасного-песочница)

в случае, если ссылка не удастся когда-нибудь я поставил самую важную часть здесь:
dockerfile:

FROM ubuntu:14.04

RUN apt-get update && apt-get install -y firefox

# Replace 1000 with your user / group id
RUN export uid=1000 gid=1000 && \
    mkdir -p /home/developer && \
    echo "developer:x:${uid}:${gid}:Developer,,,:/home/developer:/bin/bash" >> /etc/passwd && \
    echo "developer:x:${uid}:" >> /etc/group && \
    echo "developer ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/developer && \
    chmod 0440 /etc/sudoers.d/developer && \
    chown ${uid}:${gid} -R /home/developer

USER developer
ENV HOME /home/developer
CMD /usr/bin/firefox

построить изображения:

docker build -t firefox .

и выполнить команду:

docker run -ti --rm \
   -e DISPLAY=$DISPLAY \
   -v /tmp/.X11-unix:/tmp/.X11-unix \
   firefox

конечно, вы также можете сделать это в команде run с sh -c "echo script-here"

подсказка: для аудио взгляните на: https://stackoverflow.com/a/28985715/2835523

с томами данных docker очень легко открыть сокет домена unix xorg внутри контейнера.

например, с 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-переадресация. Он предоставляет контейнеру полный доступ к xserver на хосте, поэтому рекомендуется только если Вы доверяете тому, что находится внутри.

Примечание: если вы обеспокоены безопасность, лучшим решением было бы ограничить приложение с обязательно- или на основе ролей -контроль доступа. Docker достигает довольно хорошей изоляции, но он был разработан с другой целью. Используйте AppArmor,SELinux или GrSecurity, которые были разработаны для решения вашей проблемы.

вы также можете использовать subuser:https://github.com/timthelion/subuser

Это позволяет упаковать многие приложения gui в docker. Firefox и emacs были протестированы до сих пор. С firefox, webGL не работает, хотя. Хром вообще не работает.

редактировать: звук работает!

EDIT2: за то время, как я впервые опубликовал это, subuser значительно продвинулся. Теперь у меня есть сайт вверх subuser.org, и новая модель безопасности для подключение к Х11 через мост XPRA.

OSX

Юрген Вейгерту имеет лучший ответ, который работал для меня на Ubuntu, однако на OSX docker работает внутри VirtualBox, и поэтому решение не работает без дополнительной работы.

у меня есть он работает с этими дополнительными ингредиентами:

  1. Xquartz (OSX больше не поставляется с сервером X11)
  2. переадресация сокетов с помощью socat (brew install socat)
  3. bash-скрипт для запуска контейнер

Я был бы признателен за комментарии пользователей, чтобы улучшить этот ответ для OSX, я не уверен, что пересылка сокетов для X безопасна, но мое предполагаемое использование предназначено только для запуска контейнера docker локально.

кроме того, скрипт немного хрупок в том, что нелегко получить IP-адрес машины, так как он находится на нашей локальной беспроводной сети, поэтому это всегда какой-то случайный IP.

скрипт BASH, который я использую для запуска контейнера:

#!/usr/bin/env bash

CONTAINER=py3:2016-03-23-rc3
COMMAND=/bin/bash
NIC=en0

# Grab the ip address of this box
IPADDR=$(ifconfig $NIC | grep "inet " | awk '{print }')

DISP_NUM=$(jot -r 1 100 200)  # random display number between 100 and 200

PORT_NUM=$((6000 + DISP_NUM)) # so multiple instances of the container won't interfer with eachother

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       # kill the socat job launched above

Я могу получите xeyes и matplotlib, работающие с этим подходом.

Windows 7+

Это немного проще на Windows 7+ С MobaXterm:

  1. установить MobaXterm для windows
  2. Запуск MobaXterm
  3. настройка X-сервера:настройки ->X11 (tab) - > set X11 Удаленный Доступ до полное
  4. используйте этот скрипт 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

xeyes running on PC

вот легкое решение, которое позволяет избежать необходимости устанавливать любые X сервер vnc сервер или sshd демон на контейнере. То, что он приобретает в простоте, он теряет в безопасности и изоляции.

предполагается, что вы подключены к хост-машине с помощью ssh С X11 переадресация.

на sshd конфигурация хоста, добавьте строку

X11UseLocalhost no

чтобы перенаправленный порт X-сервера на хосте был открыт на всех интерфейсах (не просто lo) и, в частности, на виртуальном интерфейсе настройки docker0.

контейнер, при запуске, нуждается в доступе к .Xauthority файл, чтобы он мог подключиться к серверу. Для этого мы определяем том только для чтения, указывающий на домашний каталог на хосте (возможно, это не мудрая идея!), а также установить XAUTHORITY переменной соответственно.

docker run -v $HOME:/hosthome:ro -e XAUTHORITY=/hosthome/.Xauthority

этого недостаточно, мы также должны передать переменную отображения от хоста, но подставляя имя хоста по IP:

-e DISPLAY=$(echo $DISPLAY | sed "s/^.*:/$(hostname -i):/")

мы можем определить псевдоним:

 alias dockerX11run='docker run -v $HOME:/hosthome:ro -e XAUTHORITY=/hosthome/.Xauthority -e DISPLAY=$(echo $DISPLAY | sed "s/^.*:/$(hostname -i):/")'

и проверить это такой:

dockerX11run centos xeyes

общий хост-дисплей :0, как указано в некоторых других ответах, имеет два недостатка:

  • он нарушает изоляцию контейнера из-за некоторых утечек безопасности X. Например, кейлоггинг с xev или xinput возможно, и дистанционное управление хост-приложениями с xdotool.
  • приложения могут иметь сбои рендеринга и плохие ошибки доступа к ОЗУ из-за отсутствия общей памяти для расширения X MIT-SHM. (Смогите также быть зафиксировано с вариантом изоляции ухудшая --ipc=host).

Ниже приведен пример сценария для запуска образа docker в Xephyr, который решает эту проблему.

  • это позволяет избежать утечек безопасности X, поскольку приложения docker работают на вложенном сервере X.
  • MIT-SHM отключен, чтобы избежать сбоев доступа к оперативной памяти.
  • безопасность контейнера улучшена с --cap-drop ALL --security-opt no-new-privileges. Также пользователь контейнера является не корень.
  • файл cookie X создается для ограничения доступа к Xephyr дисплей.

сценарий предполагает какие-то аргументы, первый хозяин оконный менеджер для работы в Xephyr, второй Docker образ, при необходимости третий команда изображения для выполнения. Чтобы запустить среду рабочего стола в docker, используйте ": "вместо диспетчера окон хоста.

закрытие окна Xephyr завершает приложения контейнера docker. Завершение закрепленных приложений закрывает 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:     Example script to run docker GUI applications in Xephyr.
#
# Usage:
#   Xephyrdocker WINDOWMANAGER DOCKERIMAGE [IMAGECOMMAND [ARGS]]
#
# WINDOWMANAGER     host window manager for use with single GUI applications.
#                   To run without window manager from host, use ":"
# DOCKERIMAGE       docker image containing GUI applications or a desktop
# IMAGECOMMAND      command to run in image
#
Windowmanager="" && shift
Dockerimage="$*"

# Container user
Useruid=$(id -u)
Usergid=$(id -g)
Username="$(id -un)"
[ "$Useruid" = "0" ] && Useruid=1000 && Usergid=1000 && Username="user$Useruid"

# Find free display number
for ((Newdisplaynumber=1 ; Newdisplaynumber <= 100 ; Newdisplaynumber++)) ; do
  [ -e /tmp/.X11-unix/X$Newdisplaynumber ] || break
done
Newxsocket=/tmp/.X11-unix/X$Newdisplaynumber

# cache folder and files
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

# command to run docker
# --rm                               created container will be discarded.
# -e DISPLAY=$Newdisplay             set environment variable to new display
# -e XAUTHORITY=/Xcookie             set environment variable XAUTHORITY to provided cookie
# -v $Xclientcookie:/Xcookie:ro      provide cookie file to container
# -v $NewXsocket:$NewXsocket:ro      Share new X socket of Xephyr
# --user $Useruid:$Usergid           Security: avoid root in container
# -v $Etcpasswd:/etc/passwd:ro       /etc/passwd file with user entry
# --group-add audio                  Allow access to /dev/snd if shared with '--device /dev/snd' 
# --cap-drop ALL                     Security: disable needless capabilities
# --security-opt no-new-privileges   Security: forbid 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                an absolute path to X server executable must be given for xinit
# :$Newdisplaynumber             first argument has to be new display
# -auth $Xservercookie           path to cookie file for X server. Must be different from cookie file of client, not sure why
# -extension MIT-SHM             disable MIT-SHM to avoid rendering glitches and bad RAM access (+ instead of - enables it)
# -nolisten tcp                  disable tcp connections for security reasons
# -retro                         nice retro look
Xcommand="/usr/bin/Xephyr :$Newdisplaynumber \
  -auth $Xservercookie \
  -extension MIT-SHM \
  -nolisten tcp \
  -screen 1000x750x24 \
  -retro"

echo "X server command:
$Xcommand
"

# create /etc/passwd with unprivileged user
echo "root:x:0:0:root:/root:/bin/sh" >$Etcpasswd
echo "$Username:x:$Useruid:$Usergid:$Username,,,:/tmp:/bin/sh" >> $Etcpasswd

# create xinitrc
{ echo "#! /bin/bash"

  echo "# set environment variables to new display and new cookie"
  echo "export DISPLAY=:$Newdisplaynumber"
  echo "export XAUTHORITY=$Xclientcookie"

  echo "# same keyboard layout as on host"
  echo "echo '$(setxkbmap -display $DISPLAY -print)' | xkbcomp - :$Newdisplaynumber"

  echo "# create new XAUTHORITY cookie file" 
  echo ":> $Xclientcookie"
  echo "xauth add :$Newdisplaynumber . $(mcookie)"
  echo "# create prepared cookie with localhost identification disabled by ffff,"
  echo "# needed if X socket is shared instead connecting over tcp. ffff means '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 "# run window manager in 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

Это не легкий, но это хорошее решение, которое дает docker функцию паритета с полной виртуализации рабочего стола. И Xfce4 или IceWM для Ubuntu и CentOS работают, и noVNC опция обеспечивает легкий доступ через браузер.

https://github.com/ConSol/docker-headless-vnc-container

Он работает noVNC а также tigerVNCС VNC-сервером. Затем он вызывает startx для данного оконного менеджера. Кроме того, libnss_wrapper.so используется для эмуляции пароль руководство для пользователей.

решение, данное в http://fabiorehm.com/blog/2014/09/11/running-gui-apps-with-docker/ кажется, это простой способ запуска графических приложений из контейнеров (я пробовал для firefox над ubuntu 14.04), но я обнаружил, что для решения, опубликованного автором, требуется небольшое дополнительное изменение.

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

    docker run -ti --rm \
    -e DISPLAY=$DISPLAY \
    -v /tmp/.X11-unix:/tmp/.X11-unix \
    firefox

но я обнаружил, что (на основе конкретного комментария тот же сайт) что два дополнительных варианта

    -v $HOME/.Xauthority:$HOME/.Xauthority

и

    -net=host 

необходимо указать при запуске контейнера для правильной работы firefox:

    docker run -ti --rm \
    -e DISPLAY=$DISPLAY \
    -v /tmp/.X11-unix:/tmp/.X11-unix \
    -v $HOME/.Xauthority:$HOME/.Xauthority \
    -net=host \
    firefox

Я создал изображение докера с информацией на этой странице и этими дополнительными выводами:https://hub.docker.com/r/amanral/ubuntu-firefox/

здесь еще одно решение господа.мусор для запуска графических приложений в контейнере без использования VNC, SSH и X11 переадресации. Это упоминается здесь тоже.

Если вы хотите запустить приложение GUI без головы, то прочитайте здесь. Что вам нужно сделать, это создать виртуальный монитор с xvfb или другое подобное программное обеспечение. Это очень полезно, если вы хотите запустить тесты Selenium, например, с браузерами.

что-то нигде не упоминается, что некоторые программы На самом деле сами используют sand-boxing с контейнерами Linux. Так, например Chrome никогда не будет работать нормально, если вы не используете соответствующий флаг --privileged когда запуск контейнера.

на основе Юрген Вейгертуответ, у меня есть некоторые улучшения:

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_DIR=/tmp/.docker.xauth
XAUTH=$XAUTH_DIR/.xauth
mkdir -p $XAUTH_DIR && touch $XAUTH
xauth nlist $DISPLAY | sed -e 's/^..../ffff/' | xauth -f $XAUTH nmerge -
docker run -ti -v $XSOCK:$XSOCK -v $XAUTH_DIR:$XAUTH_DIR -e XAUTHORITY=$XAUTH xeyes

единственное отличие заключается в том, что он создает каталог $XAUTH_DIR, который используется для размещения файла $XAUTH и монтирования каталога $XAUTH_DIR вместо файла $XAUTH в контейнер docker.

преимущество этого метода заключается в том, что вы можете написать команду в /etc/rc автомобиль.локальный, который должен создать пустую папку с именем $XAUTH_DIR в /tmp и изменить ее режим на 777.

tr '\n' '0' < /etc/rc.local | sudo tee /etc/rc.local >/dev/null
sudo sed -i 's|\x00XAUTH_DIR=.*\x00\x00|\x00|' /etc/rc.local >/dev/null
tr '0' '\n' < /etc/rc.local | sudo tee /etc/rc.local >/dev/null
sudo sed -i 's|^exit 0.*$|XAUTH_DIR=/tmp/.docker.xauth; rm -rf $XAUTH_DIR; install -m 777 -d $XAUTH_DIR\n\nexit 0|' /etc/rc.local

при перезагрузке системы перед входом пользователя docker автоматически смонтирует каталог $XAUTH_DIR, если политика перезапуска контейнера "всегда". После входа пользователя, вы можете написать команду в~/.профиль, который должен создать файл $XAUTH, то контейнер будет автоматически использовать этот файл $XAUTH.

tr '\n' '0' < ~/.profile | sudo tee ~/.profile >/dev/null
sed -i 's|\x00XAUTH_DIR=.*-\x00|\x00|' ~/.profile
tr '0' '\n' < ~/.profile | sudo tee ~/.profile >/dev/null
echo "XAUTH_DIR=/tmp/.docker.xauth; XAUTH=$XAUTH_DIR/.xauth; touch $XAUTH; xauth nlist $DISPLAY | sed -e 's/^..../ffff/' | xauth -f $XAUTH nmerge -" >> ~/.profile

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

для рендеринга OpenGL с драйвером Nvidia используйте следующее изображение:

https://github.com/thewtex/docker-opengl-nvidia

для других реализаций OpenGL убедитесь, что образ имеет ту же реализацию, что и хост.

Я опаздываю на вечеринку, но для пользователей Mac, которые не хотят идти по пути XQuartz, вот рабочий пример, который создает образ Fedora с помощью среды рабочего стола (xfce) с помощью Xvfb и VNC. Это просто, и работает:

на Mac, вы можете просто доступ к нему с помощью Общий Доступ К Экрану (по умолчанию) приложение, подключившись к localhost:5901.

Dockerfile:

FROM fedora

USER root

# Set root password, so I know it for the future
RUN echo "root:password123" | chpasswd

# Install Java, Open SSL, etc.
RUN dnf update -y --setopt=deltarpm=false  \
 && dnf install -y --setopt=deltarpm=false \
                openssl.x86_64             \
                java-1.8.0-openjdk.x86_64  \
                xorg-x11-server-Xvfb       \
                x11vnc                     \
                firefox                    \
                @xfce-desktop-environment  \
 && dnf clean all

# Create developer user (password: password123, uid: 11111)
RUN useradd -u 11111 -g users -d /home/developer -s /bin/bash -p $(echo password123 | openssl passwd -1 -stdin) developer

# Copy startup script over to the developer home
COPY start-vnc.sh /home/developer/start-vnc.sh
RUN chmod 700 /home/developer/start-vnc.sh
RUN chown developer.users /home/developer/start-vnc.sh

# Expose VNC, SSH
EXPOSE 5901 22

# Set up VNC Password and DisplayEnvVar to point to Display1Screen0
USER developer
ENV  DISPLAY :1.0
RUN  mkdir ~/.x11vnc
RUN  x11vnc -storepasswd letmein ~/.x11vnc/passwd

WORKDIR /home/developer
CMD ["/home/developer/start-vnc.sh"]

start-vnc.sh

#!/bin/sh

Xvfb :1 -screen 0 1024x768x24 &
sleep 5
x11vnc -noxdamage -many -display :1 -rfbport 5901 -rfbauth ~/.x11vnc/passwd -bg
sleep 2
xfce4-session &

bash
# while true; do sleep 1000; done

Регистрация связана readme для сборки и запуска команд, если вы хотите / нужно.

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

во-первых, соответствующая документация является X безопасности man-страницы.

многочисленные интернет-источники предлагают просто установить сокет X11 unix и ~/.Xauthority файл в контейнер. Эти решения часто работают по счастливой случайности, не понимая, почему, например, пользователь контейнера получает тот же UID, что и пользователь, поэтому нет необходимости в авторизации magic key.

во-первых, файл Xauthority имеет режим 0600, поэтому пользователь контейнера не сможет прочитать его, если он не имеет того же UID.

даже если вы скопируете файл в контейнер и измените владельца, есть еще одна проблема. Если вы запустите xauth list на хосте и контейнере, с тем же Xauthority файл, вы увидите различные записи в списке. Это потому что xauth фильтрует записи в зависимости от того, где он выполняется.

клиент X в контейнере (т. е. приложение GUI) будет вести себя так же, как xauth. Другими словами, он не видит волшебный cookie для сеанса X, запущенного на рабочем столе пользователя. Вместо этого он видит записи для всех "удаленных" сеансов X, которые вы открыли ранее (объяснено ниже).

Итак, что вам нужно сделать, это добавить новую запись с именем контейнера и тот же шестнадцатеричный ключ, что и файл cookie хоста (т. е. сеанс X, запущенный на вашем рабочем столе), например:

containerhostname/unix:0   MIT-MAGIC-COOKIE-1   <shared hex key>

загвоздка в том, что cookie должен быть добавлен с xauth add внутри контейнера:

touch ~/.Xauthority
xauth add containerhostname/unix:0 . <shared hex key>

иначе xauth помечает его таким образом, что он виден только за пределами контейнера.

формат команды:

xauth add hostname/$DISPLAY protocol hexkey

здесь . представляет MIT-MAGIC-COOKIE-1 протокол.

Примечание: нет нужно скопировать или смонтируйте .Xauthority в контейнер. Просто создайте пустой файл, как показано на рисунке, и добавьте файл cookie.

Юрген Вейгертуответ получает вокруг этого с помощью FamilyWild тип подключения для создания нового файла полномочий на хосте и копирования его в контейнер. Обратите внимание, что он сначала извлекает шестнадцатеричный ключ для текущего сеанса X из ~/.Xauthority используя xauth nlist.

Итак, основные шаги являются:

  • извлечь шестигранный ключ файла cookie для текущего сеанса X пользователя.
  • создайте новый файл Xauthority в контейнере, с именем хоста контейнера и общим шестнадцатеричным ключом (или создайте файл cookie с FamilyWild тип подключения).

признаюсь, я не очень хорошо понимаю, как FamilyWild, или как xauth или X клиенты фильтруют записи из файла Xauthority в зависимости от того, где они выполняются. Дополнительная информация по этому вопросу приветствуется.

если вы хотите распространите приложение Docker, вам понадобится сценарий запуска для запуска контейнера, который получает шестнадцатеричный ключ для сеанса X пользователя и импортирует его в контейнер одним из двух способов, описанных ранее.

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

  • клиент X (т. е. приложение GUI), работающий в контейнере, ищет в файле Xauthority запись cookie, которая соответствует имени хоста контейнера и значению $DISPLAY.
  • если соответствующая запись найдена, клиент X передает ее с запросом авторизации на сервер X через соответствующий сокет в /tmp/.X11-unix каталог, смонтированный в контейнере.

Примечание: сокет X11 Unix все еще должен быть установлен в контейнере, или контейнер не будет иметь маршрута к серверу X. Большинство дистрибутивов по умолчанию отключают TCP-доступ к серверу X по соображениям безопасности.

для дополнительная информация, а также для лучшего понимания того, как работают отношения клиент / сервер X, также полезно посмотреть пример SSH X forwarding:

  • сервер SSH, работающий на удаленной машине, эмулирует свой собственный X-сервер.
  • он устанавливает значение $DISPLAY в сеансе SSH указать на свой собственный X-сервер.
  • он использует xauth чтобы создать новый файл cookie для удаленного хоста и добавить его в Xauthority файлы как для локального, так и для удаленного пользователи.
  • когда приложения GUI запускаются, они разговаривают с эмулированным X-сервером SSH.
  • сервер SSH пересылает эти данные обратно клиенту SSH на локальном рабочем столе.
  • локальный SSH-клиент отправляет данные в сеанс X-сервера, запущенный на вашем рабочем столе, как если бы SSH-клиент был на самом деле X-клиентом (т. е. GUI-приложением).
  • сервер X использует полученные данные для отображения графического интерфейса на рабочем столе.
  • в начале этого обмена удаленный клиент X также отправляет запрос на авторизацию, используя только что созданный файл cookie. Локальный сервер X сравнивает его с локальной копией.

вы можете разрешить пользователю Docker (здесь: root) получить доступ к дисплею X11:

XSOCK=/tmp/.X11-unix
xhost +SI:localuser:root 
docker run -t -i --rm -v $XSOCK:$XSOCK:ro -e DISPLAY=unix$(DISPLAY) image 
xhost -SI:localuser:root

другие решения должны работать, но вот решение для docker-compose.

чтобы исправить эту ошибку, вам нужно передать $DISPLAY and .X11-unix для docker, а также предоставить пользователю, который запустил docker доступ к xhost.

внутри docker-compose.в формате YML: version: '2' services: node: build: . container_name: node environment: - DISPLAY volumes: - /tmp/.X11-unix:/tmp/.X11-unix

в терминале или скрипте:

  • xhost +si:localuser:$USER
  • xhost +local:docker
  • export DISPLAY=$DISPLAY
  • docker-compose up

OSX (10.13.6, high sierra)

аналогично @Nickответ, но его решение не сработало для меня.

Сначала установите socat, выполнив brew install socat, и установить XQuartz (https://www.xquartz.org/)

затем выполните следующие действия здесь (http://fabiorehm.com/blog/2014/09/11/running-gui-apps-with-docker/) в разделе комментариев:

1. in one mac terminal i started:

socat TCP-LISTEN:6000,reuseaddr,fork UNIX-CLIENT:\"$DISPLAY\"

2. and in another mac terminal I ran:

docker run -ti --rm \
-e DISPLAY=$(ipconfig getifaddr en0):0 \
-v /tmp/.X11-unix:/tmp/.X11-unix \
firefox

Я также смог запустить CLion из моего Debian docker контейнер тоже.