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.pswp.cn/news/249418.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/249418.shtml
英文地址,請注明出處:http://en.pswp.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…