Переслать X11 через SSH-соединение с хостом контейнера?

Я хотел бы запустить приложение GUI в контейнере с удаленного компьютера.

Я не хочу решать эту проблему, добавив хост SSH в контейнер, потому что

  • У меня уже есть доступ к хост-машине через SSH
  • Это добавляет ненужные накладные расходы
  • Это делает контейнер непереносимым между удаленным и локальным использованием

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

хозяин

  • xauth + (не на длительный срок, но полезно для устранения возможных проблем)
  • docker-user с идентификатором 501000 на хосте == docker-user с uid 1000 в контейнере через функцию пространства имен
  • .Xauthority файл скопирован в docker-user домашняя папка

Dockerfile

  • На основе альпийского
  • Установлено xauth и, для целей тестирования, xterm
  • Создает docker-user с надлежащей UID / GID

докер-Compose

  • Переменная среды DISPLAY отправлено в
  • объем /home/docker-user/:/home/docker-user/:ro предоставлять .Xauthority печенье
  • объем /tmp/.X11-unix:/tmp/.X11-unix:ro обеспечить доступ к сокету X11
  • Запускает команду su - docker-user -c "export DISPLAY=$DISPLAY && xterm"
    • su раньше бегал как docker-user
    • DISPLAY перенаправлен в su контекст

К сожалению, этого еще недостаточно. В то время как xterm в операционной системе хоста подключается к моему локальному X-серверу без проблем, xterm в контейнере говорит Xt error: Can't open display: localhost:10.0,

Я подтвердил, что "localhost:10.0" правильный, localhost существует в контейнере /etc/hostsи cookie и сокет делают это с правильными разрешениями.

Что еще может пойти не так?

3 ответа

Решение

Похоже, что вы делаете все то же самое, что и я, за исключением того, что вы делитесь.Xauthority во время создания контейнера. Это означает, что если вы когда-либо создадите ssh -X на своей машине после создания контейнера,.Xauthority больше не будет действительным. Вы не можете ssh -X из другого терминала в ту же машину и вернуться назад и использовать.Xauthority, ssh -X каждый раз меняет.Xauthority для самого последнего терминала. Я только заставил его работать, копируя.Xauthority каждый раз, когда я запускаю ssh -X на свою машину и пытаюсь поделиться экраном с моим контейнером.

примечание: я поделился устройством и идентификатором компьютера, потому что я переадресовал выходные данные веб-камеры

1. Создайте контейнер и сообщите xhost, чтобы разрешить пересылку с идентификатора контейнера:

sudo docker run -it -d \
    --net=host \
    --env="DISPLAY" \
    --env="QT_X11_NO_MITSHM=1" \
    --volume="/tmp/.X11-unix:/tmp/.X11-unix:rw" \
    --device="/dev/video0:/dev/video0" \
    --volume="/path/to/your/sharedDockerFiles:/root/sharedDockerFiles" \
    --volume="/etc/machine-id:/etc/machine-id" \
    yourdockerrepo/image:tag \
    bash
export containerId=$(docker ps -l -q)
sudo xhost +local:`sudo docker inspect --format='{{ .Config.Hostname }}' $containerId`
sudo docker start $containerId

2. Скопируйте.Xauthority из домашнего хоста в каталог sharedDockerFiles:

sudo cp ~/.Xauthority /path/to/your/sharedDockerFiles

3.Запустите и прикрепите свой контейнер

4.Скопируйте.Xauthority из вашей общей папки в ваш домашний контейнер

sudo cp /root/sharedDockerFiles/.Xauthority ~/

5.(необходимо один раз): отредактируйте контейнер /etc/ssh/ssh_config в Host *, включив в него:

   ForwardX11 yes
   X11Forwarding yes

6.Перезапустите свой контейнер, подключите и запустите приложение с графическим интерфейсом.

7.Если у вас все еще есть проблемы, убедитесь, что переменная $DISPLAY в контейнере совпадает с переменной хоста

echo $DISPLAY #do this in the container
exit
echo $DISPLAY #do this in the host, should be the same as container's
#if they aren't equal, start container and:
export DISPLAY= #put the output of your host's $DISPLAY variable here

Скопируйте.Xauthority в контейнер в начале сеанса SSH перед использованием GUI:

sudo docker exec -i container_name bash -c 'cat > ~/.Xauthority' < ~/.Xauthority

Затем вы можете передать DISPLAY, если используете 'docker exec'. Например, чтобы открыть новый Bash:

sudo docker exec -it --env="DISPLAY" container_name bash

Еще 2 возможных причины ошибки: (в дополнение к принятому ответу)

  • basic: у вас нет ssh-сервера или xauth в контейнере (для ubuntu запустите 'apt install openssh-server xauth')

  • подлый: Если ваше имя хоста контейнера отличается от имени хоста (например, установите через -h значок в 'docker run'), вы получите ошибку, и вам придется с этим справиться (например, установить то же имя хоста или добавить cookie в Xauth)

Давайте запустим docker с параметром --net=host. Это заставляет контейнер видеть тот же сетевой стек хоста.

Например,

запуск докера --net = хост --rm -ti -u myid -e DISPLAY="$DISPLAY" -v /tmp/.X11-unix:/tmp/.X11-unix image: тег BINARY

Другие вопросы по тегам