Rub*_*ben 19 x11 ssh x11-forwarding docker
如果没有Docker容器,可以直接使用SSH X11转发(ssh -X)在远程服务器上运行X11程序.当应用程序在服务器上的Docker容器内运行时,我试图让同样的东西工作.当使用-X选项SSH连接到服务器时,会设置X11隧道,并且环境变量"$ DISPLAY"会自动设置为"localhost:10.0"或类似内容.如果我只是尝试在Docker中运行X应用程序,我会收到此错误:
Error: GDK_BACKEND does not match available displays
Run Code Online (Sandbox Code Playgroud)
我的第一个想法是实际将$ DISPLAY传递给容器,其中包含"-e"选项,如下所示:
docker run -ti -e DISPLAY=$DISPLAY name_of_docker_image
Run Code Online (Sandbox Code Playgroud)
这有帮助,但它没有解决问题.错误消息更改为:
Unable to init server: Broadway display type not supported: localhost:10.0
Error: cannot open display: localhost:10.0
Run Code Online (Sandbox Code Playgroud)
在搜索网络后,我发现我可以做一些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
Run Code Online (Sandbox Code Playgroud)
但是,这仅在将" --net host " 添加到docker命令时才有效:
docker run -ti -e DISPLAY=$DISPLAY -v $XSOCK:$XSOCK -v $XAUTH:$XAUTH \
-e XAUTHORITY=$XAUTH --net host name_of_docker_image
Run Code Online (Sandbox Code Playgroud)
这是不可取的,因为它使整个主机网络对容器可见.
为了让它完全在没有"--net host"的docker中的远程服务器上运行,现在缺少什么?
Rub*_*ben 29
我想到了.当您使用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/'`
Run Code Online (Sandbox Code Playgroud)
此外,SSH服务器通常未配置为接受与此X11隧道的远程连接.然后必须通过编辑/ etc/ssh/sshd_config(至少在Debian中)并设置来更改它:
X11UseLocalhost no
Run Code Online (Sandbox Code Playgroud)
然后重新启动SSH服务器,并使用"ssh -X"重新登录服务器.
这几乎是这样,但还有一个复杂因素.如果Docker主机上正在运行任何防火墙,则必须打开与X11隧道关联的TCP端口.端口号是:和之间的数字.在$ DISPLAY中添加到6000.
要获取TCP端口号,您可以运行:
X11PORT=`echo $DISPLAY | sed 's/^[^:]*:\([^\.]\+\).*/\1/'`
TCPPORT=`expr 6000 + $X11PORT`
Run Code Online (Sandbox Code Playgroud)
然后(如果使用ufw作为防火墙),为172.17.0.0子网中的Docker容器打开此端口:
ufw allow from 172.17.0.0/16 to any port $TCPPORT proto tcp
Run Code Online (Sandbox Code Playgroud)
所有命令可以放在一个脚本中:
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
Run Code Online (Sandbox Code Playgroud)
假设你不是root用户,因此需要使用sudo.
而不是sudo chmod 777 $XAUTH
,你可以运行:
sudo chown my_docker_container_user $XAUTH
sudo chmod 600 $XAUTH
Run Code Online (Sandbox Code Playgroud)
防止服务器上的其他用户如果知道您为/tmp/.docker.auth文件创建了什么,也能够访问X服务器.
我希望这可以使它适用于大多数情况.
归档时间: |
|
查看次数: |
6365 次 |
最近记录: |