Docker运行GUI软件的方法

转自 https://www.csdn.net/article/2015-07-30/2825340

简介:
Docker通过namespace将容器与主机上的网络和运行环境进行了隔离,默认情况下,在容器中运行带界面的软件在外部是看不到的。在这个分享中,将介绍通过共享X11套接字让外部主机显示容器中运行的程序界面的方法。并讨论在『运行本地的GUI程序』和『运行远程服务器上的GUI程序』两种场景的下的实现原理。

下文是本次的分享整理:
Docker比较常用的场景是『运行无界面的后台服务』或者『运行基于的Web服务』。不过有时出于个人的喜好或特定的需求,我们会希望在Docker中运行带图形界面的应用程序。

比如,在今年的『Docker全球开发者大会』上,Docker自家的美女程序员『杰西·弗莱泽尔(Jessie Frazelle)』展示了一系列黑魔法一样的镜像。这些镜像中的大多数都使用了图形界面。

DaoCloud的孙宏亮在现场通过博客直播了她的演讲。看到这张照片很多人应该已经认出她了。

Jessie在自己的博客里介绍这些镜像时说,她十分欣赏苹果的Mac电脑中每个应用程序使用独立沙盒中运行的做法,这样避免了应用程序将配置文件和运行过程中生成的临时文件散乱的丢在系统各种目录中。Jessie现在的工作环境主要是Debian系统,出于这种喜好,她将自己常用的各种软件统统使用Docker容器化了。

将容器中的图形界面展示到外部的一般性思路。
目前Unix/Linux比较主流的图形界面服务是X11,而X11服务的图形显示方式实际上是一种Client/Server模式,在服务端和客户端之间,X11通过『DISPLAY』环境变量来指定将图形显示到何处。如下面的流程所示,请注意服务端与客户端的位置,服务端是用于提供显示信息的。

[应用程序]->[X11客户端]->[X11服务端]->[显示屏幕]

DISPLAY的格式是『unix:端口』或『主机名:端口』,前一种格式表示使用本地的unix套接字,后一种表示使用tcp套接字。

默认情况下,X11的服务端会监听本地的『unit:0』端口,而DISPLAY的默认值为『:0』,这实际上是『unit:0』的简写。因此如果在Linux的控制台启动一个图形程序,它就会出现在当前主机的显示屏幕中。

基于这个原理,将Docker中的GUI程序显示到外面,就是通过某种方式把X11的客户端的内容从容器里面传递出来。基本的思路无非有两种:

通过SSH连接或远程控制软件,最终通过tcp套接字将数据发送出来
让容器和主机共享X11的unix套接字,直接将数据发送出来
从应用场景上划分,又可以分成两类情况:『运行本地的GUI程序』和『运行远程服务器上的GUI程序』。这两类情况在操作上很相似,但前者可以使用unix套接字,而后者必然要使用tcp套接字转发,原理上有很大差别。先说本地运行GUI程序的情况。

以Jessie在Docker开发者大会上做的第一个演示『LibreOffice』为例。这个镜像的Dockerfile代码和使用方法都已经开源在Github上了。

不知道有多少人实际测试过Jessie在博客或者Docker开发者大会上用过的例子,我相信其中应该有些人会发现,直接运行这些例子是行不通的。下面是我的运行环境:

$ cat lsb-release

DISTRIB_ID=Ubuntu

DISTRIB_RELEASE=14.04

DISTRIB_CODENAME=trusty

DISTRIB_DESCRIPTION="Ubuntu 14.04.2 LTS"

$ docker --version

Docker version 1.7.1, build 786b29d

这是一个全新的Ubuntu系统,仅仅添加了Docker等基本的软件。

在LibreOffice的Dockerfile注释里提供了运行方法:

$ docker run -d
-v /etc/localtime:/etc/localtime:ro
-v /tmp/.X11-unix:/tmp/.X11-unix
-e DISPLAY=unix$DISPLAY
-v $HOME/slides:/root/slides
-e GDK_SCALE
-e GDK_DPI_SCALE
--name libreoffice
jess/libreoffice
其中的『-v /tmp/.X11-unix:/tmp/.X11-unix』参数就是将主机上X11的unix套接字共享到了容器里面。因为每个unix套接字实际上就是系统/tmp/.X11-unix目录下面依据套接字编号命名的一个特殊文件。

命令执行完,LibreOffice并没有启动。

好在刚刚已经说过这茬,所以还不算太意外。看一下日志:

$ docker logs libreoffice

No protocol specified

Failed to open display

javaldx: Could not find a Java Runtime Environment!

Warning: failed to read path from javaldx

No protocol specified

No protocol specified

No protocol specified

No protocol specified
这是由于X11服务默认只允许『来自本地的用户』启动的图形程序将图形显示在当前屏幕上。对于Jessie的运行环境,她应该的已经修改了这个设置,但并没有在博客中提及。对于大多数的Linux用户来说,直接运行博客中的命令,都应该会遇到这个问题。

解决的办法很简单,允许所有用户访问X11服务即可。这个事情可以用xhost命令完成。

$ sudo apt-get install x11-xserver-utils

$ xhost +
参数『+』表示允许任意来源的用户。

现在再次运行前面的docker run命令,就会看到LibreOffice启动起来了,速度相当快。由于是直接共享了X11的unix套接字,在效率上与运行安装在主机上的程序基本没有差异。

在远程服务器上用Docker运行GUI程序的情况。
这种情况多出现在将Docker作为产品测试环境使用的场景。利用Docker用后既消除的特点,能够快速的为每次测试提供干净的上下文环境。有时为了在非Linux系统中使用Linux的图形化软件,也可以通过远程Docker运行的方法实现。

此时,整个数据连接实际就变成了这样的:

[应用程序]->[X11客户端]->[SSH服务端]->[SSH客户端]->[X11服务端]->[显示屏幕]

这种情况实际上已经演化成为了通过tcp套接字转发的X11连接,只不过用户并没有直接使用SSH连接到容器里面的tcp端口上,而是连接到了远程主机。相应的X11数据先从容器传递到了主机,再通过SSH通过传递到了用户的电脑上。

这就必须有要求用于展示的用后电脑安装有X11服务,大多数的Linux系统默认就具备了,Mac系统可以安装XQuartz软件,Windows则可以使用Xming等第三方X11服务端实现。首先将本地的X11服务运行起来。

其次,当用户使用SSH连接运行程序的服务器时,应该开启SSH的『X11-Forwarding』功能。具体来说,有两个注意点。

1)检测服务器上的/etc/ssh/sshd_config文件,是否已经有『X11Forwarding yes』这样的配置,如果没有则需要加上。

2)当连接到服务器时,应该在ssh命令后面加上-X参数,表示使用X11-Forwarding特性。

$ ssh -X @
登陆上去后运行刚才的docker run命令,并不能看到LibreOffice运行起来的迹象。通过log发现错误还是『Failed to open display』。在前面已经说过,对于远程连接运行GUI的情况,必然要换成tcp套接字的X11转发方式。而命令中的『-v /tmp/.X11-unix:/tmp/.X11-unix』参数仅仅是共享了unix套接字。那么怎样才能换成tcp套接字呢?需要修改两个地方:

1)首先为容器里面设置的环境变量『DISPLAY』,不能是『unix$DISPLAY』了

2)其次共享unix套接字可以不必了,而是要用『--net=host』让容器内的网络环境与主机共享

DISPLAY改成什么呢?首先要看SSH登陆后得到的系统DISPLAY变量值,我这里看到的是『localhost:10.0』,主机的localhost:10.0到了容器里面就要变成0.0.0.0:10.0。原因不解释了,这个是Docker默认添加的映射。

因此DISPLAY的值应该赋予『0.0.0.0:10.0』。可以简写为『:10.0』,X11会先去找unix:10.0,发现没有那个套接字文件,然后就会去试0.0.0.0:10.0。结果是一样的。修改过后的启动命令变成了:

$ docker run -d
-v /etc/localtime:/etc/localtime:ro
--net=host
-e DISPLAY=:10.0
-v $HOME/slides:/root/slides
-e GDK_SCALE
-e GDK_DPI_SCALE
--name libreoffice
jess/libreoffice
再次运行这个镜像,然而,依旧没有看到LibreOffice。查看Docker logs,这次的错误信息是:

『X11 connection rejected because of wrong authentication』。

这是因为在使用SSH通道转发X11时,会生成一个随机的授权cookie,存放在服务器的Xauthority文件中。这个cookie会在每次X11客户端发送数据时被用到。我们使用了『--net=host』参数后,容器中的X11客户端将直接通过tcp套接字与外部通信,然而容器里面并没有这个授权文件。因此我需要加上参数『-v $HOME/.Xauthority:/root/.Xauthority』把授权文件也放到容器里面。此外,启动命令中的两个GDK开头的环境变量在服务器端的Ubuntu上是不存在的,因此也可以删掉。

现在我们得到了最终的启动命令:

$ docker run -d
-v /etc/localtime:/etc/localtime:ro
--net=host
-e DISPLAY=:10.0
-v $HOME/slides:/root/slides
-v $HOME/.Xauthority:/root/.Xauthority
--name libreoffice
jess/libreoffice
执行这个命令后,就看到LibreOffice已经在本地电脑的显示器上运行起来啦!

这个在Mac上看到的LibreOffice,程序本身运行在远程服务器的Docker里面。同样的方法也可以适应于Jessie的其他镜像。

Q&A:
问题1. X11是什么,与KDE有什么区别?

林帆:X11是Linux下面的界面显示服务。KDE是一种窗口管理软件,是具体的界面,X11是在更下面一层的协议层。

问题2. 在服务端运行GUI镜像时会收到网络的影响画面卡顿吗?

林帆:这个和网速关系比较大。

问题3. 通过这种gui方式,是不是可以做docker桌面云了?

林帆:不算是,因为这种做法需要SSH登录,其实有点不安全.

问题4. 可以多用户连接同一docker image不?就像remote desktop service一样?

林帆:用这种方式不能,SSH的X-Forwarding是单点的。

问题5. 可以考虑用xvfb吗?

林帆:原理上是可以的,不过这样就看不到运行的界面了。

问题6. 理论上讲,只要配置合理正确并且GUI支持X11,这种方式可以运行大部分linux下的gui应用?

林帆:是的,对于应用程序本身感觉不到图像是被现实到了本地还是远程的屏幕上

问题7. 请问在docker上运行的gui应用,应用间的互操作性如何保障?x11协议应该只能转发显示数据,无法转发实际数据(如电子表格中的数据,用以粘贴到其他打开的文档文件中),是否有其他协议可以保证互操作性?

林帆:目前看来互操作的话只能用其他协议代替X11了,比如VNC或者FreeNX。X11协议中,剪贴板的数据都是保存在X的客户端,两个远程窗口之间不能共享。

转载于:https://www.cnblogs.com/jcchen1987/p/10553930.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/249418.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JS正则表达式验证数字非常全

验证数字的正则表达式集 验证数字:^[0-9]*$ 验证n位的数字:^\d{n}$ 验证至少n位数字:^\d{n,}$ 验证m-n位的数字:^\d{m,n}$ 验证零和非零开头的数字:^(0|[1-9][0-9]*)$ 验证有两位小数的正实数:^[0-9](.[0-9…

VMware VIC

vSphere Integrated Containers - a short intro High-Level view of VCH Networking vSphere Integrated Containers Roles and Personas 参考链接:https://vmware.github.io/vic-product/assets/files/html/1.4/转载于:https://www.cnblogs.com/vincenshen/p/9715…

vue new vue

https://www.jianshu.com/p/5ca5f40e4810

MySQL 之group_concat_max_length Mac 版

用过MySQL的人都知道,group_concat这个函数是有最大值限制的,当超过了最大值就会报错! 在window下的处理方法就是修改MySQL的配置文件my.ini,在其中添加 #group_concat_max_len setting group_concat_max_len 1024000000 然…

Locust学习总结分享

简介: Locust是一个用于可扩展的,分布式的,性能测试的,开源的,用Python编写框架/工具,它非常容易使用,也非常好学。它的主要思想就是模拟一群用户将访问你的网站。每个用户的行为由你编写的py…

IDEA系列(四)一部署war 和 war exploded的区别

war模式:将WEB工程以包的形式上传到服务器 ; war exploded模式:将WEB工程以当前文件夹的位置关系上传到服务器;(1)war模式这种可以称之为是发布模式,看名字也知道,这是先打成war包&a…

Vue常用7个属性

https://www.cnblogs.com/bgwhite/p/9297221.html

初始Zookeeper

Zookeeper是一个分布式服务框架,据说是一个比较强大的架构模式,具体我也不甚了解,但是最近由于工作上的原因,需要部署一个Zookeeper服务,实现移动端一个简单的发单、抢单功能。于是我便开始了解这个框架,将…

开发进度

项目名称:信息技术手册查重错误比对分析 功能概述: (1) 数据导入:要求将提供的信息技术手册文档倒入数据库中 方法: 将word文档中的内容复制到text中,利用notepad打开,利用正则表达…

Solr的安装和使用

安装 CentOS中先安装好Java和Tomcat。准备工具IK Analyzer 2012FF 和Solr-4.10.3.tgz 将solr-4.10.3文件夹中dist中的solr-4.10.3.war文件复制到Tomcat的webapps,并且更名为solr.war,下开启tomcat解压后再关闭tomcat,再删除solr.war。 将Solr…

springboot工程打包时将application.properties放在jar包外

https://blog.csdn.net/luckyzsion/article/details/83743604

史上最详细的js日期正则表达式分享

最简单的正则 如 : /d{4}-/d{2}-/d{2} 但是实际情况却不是那么简单,,要考虑,有效性和闰年等问题..... 对于日期的有效范围,不同的应用场景会有所不同。MSDN中定义的DateTime对象的有效范围是:0001-01-01 00:00:00到9999-12-31 23:59:59。 UNIX时间戳的0按…

laravel的validator验证

1.引入对应的类 use Illuminate\Support\Facades\Validator;2.自定义规则,写在模型,控制器,中间件都可以 $rules [password > required|between;6,20|confirmed, name > required|between;3,8, ];3.自定义提示,laravel自…

HTML,CSS,JaveScript

一、HTML 1、标记语言 标记语言为非编程语言,不具备编程语言具备的程序逻辑 2、html为前端页面的主体,由标签、指令与转义字符(实体)等组成 标签:被尖括号包裹,由字母开头包含合法字符的,可以被…

python用户交互、基本数据类型、运算符

用户交互 在实际应用中,我们经常需要用户输入相应信息,根据用户输入信息进行反馈,此时我们需要input/output信息 python中提供了便捷的输入方法input()和print() 在python3中 name input("…

pom.xml详细说明

<project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd "><!-- 父项目的坐标。…

maven如何修改本地仓库与中央仓库

什么是Maven仓库 在不用Maven的时候&#xff0c;比如说以前我们用Ant构建项目&#xff0c;在项目目录下&#xff0c;往往会看到一个名为/lib的子目录&#xff0c;那里存放着各类第三方依赖jar文件&#xff0c;如 log4j.jar&#xff0c;junit.jar等等。每建立一个项目&#xff0…

Maven项目 之eclipse操作篇

使用eclipse创建maven项目大家应该都很熟悉&#xff0c;这里主要说明如何将已创建的非maven项目修改为maven项目。 1.创建测试项目 创建一个Dynamic Web Project &#xff0c;项目结构如图。 2.配置工程类型 右击项目--> Properties --> Project Facets&#xff0c;勾选…

前端jQuery基本语法

jQuery基础语法 #不管找什么标签&#xff0c;用什么选择器&#xff0c;都必须要写$("")&#xff0c;引号里面再写选择器&#xff0c;通过jQuery找到的标签对象就是一个jQuery对象&#xff0c;用原生JS找到的标签对象叫做DOM对象。二者可以相互转换。$()[0]:就是jQuer…

网络工程:3.1 RIP(Routing Information Protocol)协议

遵循协议&#xff1a; 1、特网rip1标准文件&#xff1a;rfc1058 网站 &#xff1a; https://tools.ietf.org/html/rfc1058 2、因特网rip2标准文件&#xff1a;rfc1723 网站 &#xff1a;https://tools.ietf.org/html/rfc1723 使用工具&#xff1a; GNS3 使用路由器文件&a…