Ответ 1
Я понял. Когда вы подключаетесь к компьютеру с SSH и используете пересылку X11, /tmp/.X11-unix не используется для связи X, и часть, связанная с $ XSOCK, не нужна.
Любое приложение X скорее использует имя хоста в $ DISPLAY, обычно "localhost", и подключается с использованием TCP. Это тогда передано обратно клиенту SSH. При использовании "--net host" для Docker "localhost" будет таким же для контейнера Docker, как и для хоста Docker, и поэтому он будет работать нормально.
Если не указано "--net host", Docker использует режим мостовой сети по умолчанию. Это означает, что "localhost" означает что-то другое внутри контейнера, чем для хоста, и X-приложения внутри контейнера не смогут видеть X-сервер, ссылаясь на "localhost". Таким образом, чтобы решить эту проблему, нужно заменить "localhost" фактическим IP-адресом хоста. Обычно это "172.17.0.1" или подобное. Проверьте "ip addr" на наличие интерфейса "docker0".
Это можно сделать с помощью замены sed:
DISPLAY='echo $DISPLAY | sed 's/^[^:]*\(.*\)/172.17.0.1\1/''
Кроме того, сервер SSH обычно не настроен для приема удаленных подключений к этому туннелю X11. Затем это необходимо изменить, отредактировав /etc/ssh/sshd_config (по крайней мере, в Debian) и установив:
X11UseLocalhost no
а затем перезапустите сервер SSH и повторно войдите на сервер с помощью "ssh -X".
Это почти все, но осталось одно осложнение. Если на хосте Docker работает какой-либо брандмауэр, должен быть открыт TCP-порт, связанный с туннелем X11. Номер порта - это число между : и . в $ DISPLAY, добавленное к 6000.
Чтобы получить номер порта TCP, вы можете запустить:
X11PORT='echo $DISPLAY | sed 's/^[^:]*:\([^\.]\+\).*/\1/''
TCPPORT='expr 6000 + $X11PORT'
Затем (при использовании ufw в качестве брандмауэра) откройте этот порт для контейнеров Docker в подсети 172.17.0.0:
ufw allow from 172.17.0.0/16 to any port $TCPPORT proto tcp
Все команды вместе можно поместить в скрипт:
XSOCK=/tmp/.X11-unix
XAUTH=/tmp/.docker.xauth
xauth nlist $DISPLAY | sed -e 's/^..../ffff/' | sudo xauth -f $XAUTH nmerge -
sudo chmod 777 $XAUTH
X11PORT='echo $DISPLAY | sed 's/^[^:]*:\([^\.]\+\).*/\1/''
TCPPORT='expr 6000 + $X11PORT'
sudo ufw allow from 172.17.0.0/16 to any port $TCPPORT proto tcp
DISPLAY='echo $DISPLAY | sed 's/^[^:]*\(.*\)/172.17.0.1\1/''
sudo docker run -ti --rm -e DISPLAY=$DISPLAY -v $XAUTH:$XAUTH \
-e XAUTHORITY=$XAUTH name_of_docker_image
Если вы не являетесь пользователем root и, следовательно, должны использовать sudo.
Вместо sudo chmod 777 $XAUTH
вы можете запустить:
sudo chown my_docker_container_user $XAUTH
sudo chmod 600 $XAUTH
чтобы другие пользователи на сервере также не могли получить доступ к X-серверу, если они знают, для чего вы создали файл /tmp/.docker.auth.
Я надеюсь, что это должно сделать это правильно для большинства сценариев.