1. 程式人生 > >在Docker for Windows中運行GUI程序

在Docker for Windows中運行GUI程序

gui org 地址 over 是我 inside sta 分享圖片 name

Docker運行GUI原理

Docker目前大多應用在服務器領域,那麽在Docker中可以運行GUI程序嗎?懷著好奇心google了一番,還真有人寫了一篇文章 running-gui-applications-inside-docker-containers,文章從原理剖析到實際操作內容非常詳盡。

技術分享圖片

引用自running-gui-applications-inside-docker-containers

從上圖中我們可以清楚的了解到,要在docker中運行GUI程序,關鍵是讓Docker知道X Server(大多數Linux桌面環境的基礎)。文章的核心就在以下參數:

  • share the Host’s DISPLAY environment variable to the Container
  • --env="DISPLAY"
  • run container with host network driver with
  • --net=host

$ docker run --net=host --env="DISPLAY"

引用自running-gui-applications-inside-docker-containers

上述參數的含義就是將Linux宿主機的X Server共享給Docker容器,還有一種方式就是映射宿主機X Server.sock文件到容器中去。

那麽問題來了,在Windows或Mac這些沒有X11的Host機器上怎麽辦呢?由於本人一直使用的Docker for Windows(沒錢:)),所以Mac環境暫不關心。

Docker for Windows運行GUI程序

照例google到了一篇文章Run GUI app in linux docker container on windows host,內容同樣非常詳盡,本文大體也是按照這篇文章的指引。

安裝VcXsrv

VcXsrv Windows X Server是Windows上的X11程序,另外還可選擇Xming,但Xming最後一次更新是在2016年,代碼相對較老,所以還是選擇VcXsrv吧。

VcXsrv程序下載安裝步驟可以參考Run GUI app in linux docker container on windows host。

構建測試容器

和Run GUI app in linux docker container on windows host一樣也是選擇啟動一個firefox來做實驗,不同的是我對Dockerfile和docker run命令做了一些變更。

Create Dockerfile

FROM ubuntu:18.04
# 修改源地址
RUN mv /etc/apt/sources.list /etc/apt/sources_backup.list && echo "deb http://mirrors.ustc.edu.cn/ubuntu/ bionic main restricted " >> /etc/apt/sources.list && echo "deb http://mirrors.ustc.edu.cn/ubuntu/ bionic-updates main restricted " >> /etc/apt/sources.list && echo "deb http://mirrors.ustc.edu.cn/ubuntu/ bionic universe " >> /etc/apt/sources.list && echo "deb http://mirrors.ustc.edu.cn/ubuntu/ bionic-updates universe " >> /etc/apt/sources.list && echo "deb http://mirrors.ustc.edu.cn/ubuntu/ bionic multiverse " >> /etc/apt/sources.list && echo "deb http://mirrors.ustc.edu.cn/ubuntu/ bionic-updates multiverse " >> /etc/apt/sources.list && echo "deb http://mirrors.ustc.edu.cn/ubuntu/ bionic-backports main restricted universe multiverse " >> /etc/apt/sources.list && echo "deb http://mirrors.ustc.edu.cn/ubuntu/ bionic-security main restricted " >> /etc/apt/sources.list && echo "deb http://mirrors.ustc.edu.cn/ubuntu/ bionic-security universe " >> /etc/apt/sources.list && echo "deb http://mirrors.ustc.edu.cn/ubuntu/ bionic-security multiverse " >> /etc/apt/sources.list && echo "deb http://archive.canonical.com/ubuntu bionic partner " >> /etc/apt/sources.list && # 安裝firefox
apt-get update && apt-get install -y firefox
CMD /usr/bin/firefox

相較原文有如下變動:

  1. ubuntu的版本也升級到了18.04
  2. apt源替換成了中科大的鏡像地址方便快速構建

Docker build

$ docker build -t firefox .

和原文一致,構建容器。

Docker run

$ docker run -ti --rm -e DISPLAY=host.docker.internal:0.0 firefox

相較原文有如下變動:

  1. 刪除了set-variable -name DISPLAY -value YOUR-IP:0.0命令
  2. 設置容器的DISPLAY參數為host.docker.internal而不是宿主機的具體ip

原文的set-variable作用是將宿主機的ip作為臨時環境變量,在docker run的時候直接引用該環境變量賦值給容器的DISPLAY,可有可無,並且set-variable只能在PowerShell環境生效,因此直接刪除。

再來看-e DISPLAY=host.docker.internal:0.0,從18.03版本開始,Docker推薦容器使用host.docker.internal來訪問宿主機上的服務,容器的DNS會自動解析到宿主機的內部IP上,參考Docker for Windows的官方文檔:I WANT TO CONNECT FROM A CONTAINER TO A SERVICE ON THE HOST。

測試效果驗證

技術分享圖片

winpty 是因為我用的Git for Windows Bash

訪問下百度:
技術分享圖片
怎麽有亂碼,別急,這個是因為Docker build時未指定ubuntu的locales,ubuntu的鏡像默認不支持中文導致的,參考官方文檔:ubuntu locales 修改我們的Dockerfile:

FROM ubuntu:18.04
# 修改源地址
RUN mv /etc/apt/sources.list /etc/apt/sources_backup.list && echo "deb http://mirrors.ustc.edu.cn/ubuntu/ bionic main restricted " >> /etc/apt/sources.list && echo "deb http://mirrors.ustc.edu.cn/ubuntu/ bionic-updates main restricted " >> /etc/apt/sources.list && echo "deb http://mirrors.ustc.edu.cn/ubuntu/ bionic universe " >> /etc/apt/sources.list && echo "deb http://mirrors.ustc.edu.cn/ubuntu/ bionic-updates universe " >> /etc/apt/sources.list && echo "deb http://mirrors.ustc.edu.cn/ubuntu/ bionic multiverse " >> /etc/apt/sources.list && echo "deb http://mirrors.ustc.edu.cn/ubuntu/ bionic-updates multiverse " >> /etc/apt/sources.list && echo "deb http://mirrors.ustc.edu.cn/ubuntu/ bionic-backports main restricted universe multiverse " >> /etc/apt/sources.list && echo "deb http://mirrors.ustc.edu.cn/ubuntu/ bionic-security main restricted " >> /etc/apt/sources.list && echo "deb http://mirrors.ustc.edu.cn/ubuntu/ bionic-security universe " >> /etc/apt/sources.list && echo "deb http://mirrors.ustc.edu.cn/ubuntu/ bionic-security multiverse " >> /etc/apt/sources.list && echo "deb http://archive.canonical.com/ubuntu bionic partner " >> /etc/apt/sources.list && # 更新並安裝國際化語言包以及中文字體
apt-get update && apt-get install -y locales && locale-gen zh_CN && locale-gen zh_CN.utf8 && apt-get install -y ttf-wqy-microhei ttf-wqy-zenhei xfonts-wqy
# 設置系統語言環境為中文UTF-8
ENV LANG zh_CN.UTF-8  
ENV LANGUAGE zh_CN.UTF-8
ENV LC_ALL zh_CN.UTF-8
# 安裝firefox
RUN apt-get install -y firefox
CMD /usr/bin/firefox

重新run效果如下:
技術分享圖片

註意:必須安裝中文字體,僅僅設置語言環境還是會導致亂碼的。

其他方式

網上還有幾種方式,我只看了文章的理論,感覺可行,大家有空可以去親自嘗試一番:

  • Xvfb + VNC - https://medium.com/dot-debug/running-chrome-in-a-docker-container-a55e7f4da4a8
  • Xming - https://blogs.msdn.microsoft.com/jamiedalton/2018/05/17/windows-10-docker-gui/
  • SSH with X11 forwarding - https://blog.docker.com/2013/07/docker-desktop-your-desktop-over-ssh-running-inside-of-a-docker-container/
  • X11docker - 一個專門為Docker增加X11圖形渲染支持的項目 https://github.com/mviereck/x11docker

在Docker for Windows中運行GUI程序