Запустите приложение X в контейнере Docker надежно на сервере, подключенном через SSH без " --net host"

без контейнера Docker легко запустить программу X11 на удаленном сервере, используя пересылку SSH X11 (ssh-X). Я попытался сделать то же самое работает, когда приложение работает внутри контейнера Docker на сервере. Когда SSH-ing в сервер с опцией-X, туннель X11 настроен и переменная среды "$DISPLAY "автоматически устанавливается в типично "localhost: 10.0" или аналогичный. Если я просто попытаюсь запустить приложение X в докере, я получу эта ошибка:

Error: GDK_BACKEND does not match available displays

моей первой идеей было фактически передать $DISPLAY в контейнер с опцией"- e " следующим образом:

docker run -ti -e DISPLAY=$DISPLAY name_of_docker_image

Это помогает, Но это не решит проблему. Сообщение об ошибке изменяется на:

Unable to init server: Broadway display type not supported: localhost:10.0
Error: cannot open display: localhost:10.0

после поиска в Интернете я понял, что могу сделать некоторые можно magic для исправления аутентификации. Я добавил следующее:--8-->

SOCK=/tmp/.X11-unix
XAUTH=/tmp/.docker.xauth
xauth nlist $DISPLAY | sed -e 's/^..../ffff/' | xauth -f $XAUTH nmerge -
chmod 777 $XAUTH
docker run -ti -e DISPLAY=$DISPLAY -v $XSOCK:$XSOCK -v $XAUTH:$XAUTH  
  -e XAUTHORITY=$XAUTH name_of_docker_image

однако, это работает только если добавить "--net host" в команду docker:

docker run -ti -e DISPLAY=$DISPLAY -v $XSOCK:$XSOCK -v $XAUTH:$XAUTH  
  -e XAUTHORITY=$XAUTH --net host name_of_docker_image

это нежелательно, так как это делает всю хост-сеть видимой для контейнера.

чего теперь не хватает, чтобы полностью запустить его на удаленном сервере в докере без "--net host"?

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/'`

кроме того, сервер SSH обычно не настроен на прием удаленных подключений к этому туннелю X11. Это должно быть изменено путем редактирования /и т. д./по ssh/sshd_config в (по крайней мере в Debian) и установка:

X11UseLocalhost no

а затем перезапустите сервер SSH и повторно войдите на сервер с помощью "ssh-X".

это почти все, но есть один осложнение слева. Если на хосте Docker запущен брандмауэр, необходимо открыть TCP-порт, связанный с туннелем X11. Номер порта-это номер между : и . в $дисплей добавлен к 6000.

чтобы получить номер порта TCP, вы можете запустить:

X11PORT=`echo $DISPLAY | sed 's/^[^:]*:\([^\.]\+\).*//'`
TCPPORT=`expr 6000 + $X11PORT`

затем (при использовании ufw как брандмауэр), откройте этот порт для контейнеров Docker в подсети 172.17.0.0:

ufw allow from 172.17.0.0/16 to any port $TCPPORT proto tcp

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

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/^[^:]*:\([^\.]\+\).*//'`
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/'`
sudo docker run -ti --rm -e DISPLAY=$DISPLAY -v $XAUTH:$XAUTH \
   -e XAUTHORITY=$XAUTH name_of_docker_image

предполагая, что вы не корень и поэтому должны использовать sudo.

вместо sudo chmod 777 $XAUTH вы можете:

sudo chown my_docker_container_user $XAUTH
sudo chmod 600 $XAUTH

чтобы запретить другим пользователям на сервере также иметь доступ к X-серверу, если они знают, что вы создали /tmp/.докер.auth файл для.

Я надеюсь, что это должно заставить его работать правильно для большинства сценариев.