在Docker中运行Chromium - Gtk:无法打开显示器::0

59
当我尝试在docker容器内运行chromium时,出现以下错误:Gtk: 无法打开显示::0
Dockerfile:(基于https://registry.hub.docker.com/u/jess/chromium/dockerfile
FROM debian:jessie

# Install Chromium
RUN sed -i.bak 's/jessie main/jessie main contrib non-free/g' /etc/apt/sources.list && \
    apt-get update && apt-get install -y \
    chromium \
    chromium-l10n \
    libcanberra-gtk-module \
    libexif-dev \
    libpango1.0-0 \
    libv4l-0 \
    pepperflashplugin-nonfree \                                                                          
    --no-install-recommends && \
    mkdir -p /etc/chromium.d/

# Autorun x11vnc
CMD ["/usr/bin/chromium", "--no-sandbox", "--user-data-dir=/data"]

构建和运行:

docker build -t chromium
docker run -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix --privileged chromium

和错误:

[1:1:0202/085603:ERROR:browser_main_loop.cc(164)] Running without the SUID sandbox! See https://code.google.com/p/chromium/wiki/LinuxSUIDSandboxDevelopment for more information on developing with the sandbox on.
No protocol specified
[1:1:0202/085603:ERROR:browser_main_loop.cc(210)] Gtk: cannot open display: :0

你在命令的结尾忘记了点(表示当前目录):“docker build -t chromium .”。由于新手可能会卡在这个问题上,因此你可能应该更正一下这行代码。 - user2081279
9个回答

76

我对Chromium了解不多,但很早以前我曾经使用过X :-) 当你告诉一个X客户端连接到:0时,实际上是在说连接到端口6000(或者你的X服务器运行的任何其他端口)+ 0,即在本例中连接到端口6000。事实上,DISPLAY是IP:PORT(如上所述加上+6000)。X服务器正在您的主机上运行,因此,如果您设置:

DISPLAY=your_host_ip:0

那也许可行。然而,X 服务器不允许来自任何旧客户端的连接,因此您需要打开您的 X 服务器。在您的主机上运行:

xhost +

在运行Docker容器之前。这一切都是基于您可以在主机上运行Chromium的情况(也就是说,您的主机上存在X服务器)。


1
停止容器,在主机上运行 xhost +,然后再次启动容器就可以了。 - GameScripting
14
似乎您可以执行 xhost +local:docker 来限制更多。 - Andy Smith
2
如果您执行xhost +,您将基本上禁用对x窗口系统的访问控制。因此,例如如果root是运行您的docker守护程序的用户,则使用更严格的xhost xhost +SI:localuser:root。这仅允许本地套接字连接,而不允许Internet或网络主机访问您的x窗口。 - opentokix
20
虽然很吸引人,但不要这样做。请参考上面的评论。那种解决方案基本上允许任何人连接到你的机器。最好使用更严格的https://dev59.com/DV4c5IYBdhLWcg3wCGf2#34586732,只允许本地连接。 - Baptiste Mathus
4
不要执行上述任何操作。相反,将--network=host添加到docker run参数中。这将允许您的容器使用主机的网络堆栈,使-e DISPLAY=$DISPLAY按照OP的意图正常工作。 - Konrad Botor

48

2
在 Archlinux 上工作过,谢谢,我现在可以全面使用 Docker 了! - HugoTai

16

添加为参考(请查看Greg的真正答案)

在您的Linux主机中添加

  xhost +"local:docker@"
在 Docker 镜像中添加。
RUN apt-get update
RUN apt-get install -qqy x11-apps

然后运行

sudo docker run \
    --rm \ # delete container when bash exits
    -it \ # connect TTY
    --privileged \
    --env DISPLAY=unix$DISPLAY \ # export DISPLAY env variable for X server
    -v $XAUTH:/root/.Xauthority \ # provide authority information to X server
    -v /tmp/.X11-unix:/tmp/.X11-unix \ # mount the X11 socket
    -v /home/alex/coding:/coding \
    alexcpn/nvidia-cuda-grpc:1.0 bash

在容器内 - 检查一个示例命令

xclock

3
请您提供一下这个命令的简短解释吗?这将非常有帮助。 - Whoami
"xclock程序以模拟或数字形式显示时间。时间会以用户可以指定的频率进行持续更新。该程序是安装在上述x11-apps包中的一部分。" - Ben Poon
这个答案很有用!(尤其是XAuthority卷挂载部分) - IcyFlame
为什么你不想在Dockerfile中包含--privileged之后的大部分/全部参数呢? - undefined

7
对于Ubuntu 20.04,将 DISPLAY=:0 更改为 DISPLAY=$DISPLAY 对我有用,因为我的本地环境中 $DISPLAY 被设置为 :1
docker run --rm -ti --net=host -e DISPLAY=$DISPLAY fr3nd/xeyes

4
因此,我也有一个要求,在我的Docker容器中打开一个图形化应用程序。这是适用于我的环境的步骤。(Docker版本:19.03.12容器操作系统:Ubuntu 18.04)在运行容器之前,请通过运行此命令使主机的X服务器接受任何客户端的连接:xhost +。这是一种非常不限制性的连接到主机X服务器的方式,您可以根据其他答案给出的答案进行限制。然后,使用-- network = host 选项运行容器(例如:docker run --network=host <my image name>)。容器启动后,登录其shell,并使用DISPLAY=:0启动您的应用程序(例如:DISPLAY=:0 <my graphical app>)。

3
在遍历整个互联网时," --network host " 就是我所需的。 - Tomilov Anatoliy

2
我在Windows主机上成功运行了它,但在我的Linux Mint(Ubuntu)主机上却没有成功。原因是我在Linux上使用的是Docker Desktop,它在底层使用了一个虚拟机。
解决方法:关闭Docker Desktop并安装Docker Engine。除此之外,还要按照其他答案中的方法进行操作。

是的!这也是我的问题。谢谢你。 - undefined

0
需要的是将您的docker主机名映射到外部主机名的别名。当使用以冒号开头的DISPLAY时,它表示localhost。基本上,您在docker内部的主机名需要通过/etc/hosts解析为与外部主机相同的名称 - 因为这是存储在.Xauthority中的名称。

0
我找到了一个自动获取电脑IP的脚本:
FOR /F "tokens=4 delims= " %%i in ('route print ^| find " 0.0.0.0"') do set localIp=%%i

创建一个批处理文件,将以下内容放入该批处理文件中:
FOR /F "tokens=4 delims= " %%i in ('route print ^| find " 0.0.0.0"') do set 
localIp=%%i
docker run -ti -v /tmp/.X11-unix -v /tmp/.docker.xauth -e 
XAUTHORITY=/tmp/.docker.xauth --net=host -e DISPLAY=%localIp%:0.0 your-container

脚本适用于Windows用户,使用xlaunch(VcXsrv)运行时请记得标记“禁用访问控制”。 - Matteo Toma

0

我使用这个命令列表

#host operating system; bash_shell1

i. environment debian11 MX-21.3_x64 ahs 


i. become sudo 
sudo su
password


i. docker restart
service docker restart


i. download/pull image 
docker pull ubuntu:jammy







i. check #dockerip
sudo ip addr show docker0
#output: 172.17.0.1





i. check ps
docker ps
#output:  CONTAINER ID      IMAGE               COMMAND             CREATED             STATUS              PORTS






i. check images
docker images

#output:
REPOSITORY    TAG       IMAGE ID       CREATED         SIZE
ubuntu        jammy     08d22c0ceb15   3 weeks ago     77.8MB
hello-world   latest    feb5d9fea6a5   18 months ago   13.3kB




i. CONNECT/DISCONNET xserver
# Disallow X server connection
xhost -local:*

# Allow X server connection
xhost +local:*



i. set up gui/display etc
service docker restart
sleep 2
DISPLAY=:0
xhost +








i. only create docker container

containername=custom_container_001

SOCK=/tmp/.X11-unix docker run --name $containername -d -it --rm --privileged --volume "$HOME/.Xauthority:/root/.Xauthority:ro" -p 8080:8080 --network=host -e DISPLAY=$DISPLAY -v $XSOCK:$XSOCK ubuntu:jammy



i. execute bash 
docker exec -it $containername bash; history -a





-----------------------------


#guest operating system; bash_shell1

i. now we are inside the ubuntu container, install mousepad or xclock and runn it

apt update -y

apt install mousepad -y
mousepad


apt install x11-apps -y
xclock


#try this command too
apt install xclock -y
xclock





-----------------------------
#host operating system; bash_shell2
docker ps


CONTAINER ID   IMAGE          COMMAND       CREATED          STATUS          PORTS     NAMES
8af08xxxcc64   ubuntu:jammy   "/bin/bash"   20 minutes ago   Up 20 minutes             custom_container_001


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接