+-
在没有“–net host”的SSH连接的服务器上可靠地在Docker容器中运行X应用程序
如果没有Docker容器,可以直接使用SSH X11转发(ssh -X)在远程服务器上运行X11程序.当应用程序在服务器上的Docker容器内运行时,我试图让同样的东西工作.使用-X选项通过SSH连接到服务器时,会设置X11隧道,并且环境变量“$DISPLAY”会自动设置为“localhost:10.0”或类似内容.如果我只是尝试在Docker中运行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

在搜索网络后,我发现我可以做一些xauth魔术来修复身份验证.我添加了以下内容:

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”的docker中的远程服务器上运行,现在缺少什么?

最佳答案
我想到了.当您使用SSH连接到计算机并使用X11转发时,/ tmp / .X11-unix不用于X通信,并且不需要与$XSOCK相关的部分.

任何X应用程序都使用$DISPLAY中的主机名,通常是“localhost”并使用TCP连接.然后将其隧道传送回SSH客户端.当Docker使用“–net host”时,Docker容器的“localhost”与Docker主机相同,因此它可以正常工作.

如果未指定“–net host”,则Docker将使用默认的网桥模式.这意味着“localhost”意味着容器内部的其他内容与主机相同,容器内的X应用程序将无法通过引用“localhost”来查看X服务器.因此,为了解决这个问题,必须将“localhost”替换为主机的实际IP地址.这通常是“172.17.0.1”或类似的.检查“docker0”接口的“ip addr”.

这可以通过sed替换来完成:

DISPLAY=`echo $DISPLAY | sed 's/^[^:]*\(.*\)/172.17.0.1\1/'`

此外,SSH服务器通常未配置为接受与此X11隧道的远程连接.然后必须通过编辑/ etc / ssh / sshd_config(至少在Debian中)并设置来更改它:

X11UseLocalhost no

然后重新启动SSH服务器,并使用“ssh -X”重新登录服务器.

这几乎是这样,但还有一个复杂因素.如果Docker主机上正在运行任何防火墙,则必须打开与X11隧道关联的TCP端口.端口号是:和之间的数字.在$DISPLAY中添加到6000.

要获取TCP端口号,您可以运行:

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

然后(如果使用ufw作为防火墙),为172.17.0.0子网中的Docker容器打开此端口:

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/^[^:]*:\([^\.]\+\).*/\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

防止服务器上的其他用户如果知道您为/tmp/.docker.auth文件创建了什么,也能够访问X服务器.

我希望这可以使它适用于大多数情况.

点击查看更多相关文章

转载注明原文:在没有“–net host”的SSH连接的服务器上可靠地在Docker容器中运行X应用程序 - 乐贴网