我有一个需求:html
一方面,我须要在 Docker 容器环境下运行应用(由于有些环境在 Mac 下很难安装配置,而且但愿环境干净隔离)。
另外一方面,容器中的应用又须要进行图形界面的显示。
因为 Docker 容器是命令行的形式,自己不支持图形界面显示,所以我但愿 Docker 容器能和个人 Mac 主机上的 GUI 进行链接。linux
个人 Mac OS X 系统版本是:10.14.2git
实现的解决方案
socat 安装
首先用 socat 来解决容器和 Mac 主机 GUI 的通讯问题:docker
brew install socat
xquartz 安装
接下来是处理 X windows system,咱们须要安装 Xquartz。能够采用 brew 安装(我没有使用这种方式):macos
brew install xquartz
因为个人网络极差,里面 git clone 下载不下来,我最终选择进入官网直接安装 dmg(v2.6.1),大概 70M 大小。windows
安装好了以后须要注销并从新进入 Mac 主机。网络
xquartz 配置
重启以后咱们发现有了环境变量 $DISPLAY。app
echo $DISPLAY
/private/tmp/com.apple.launchd.nzm51qjuIW/org.macosforge.xquartz:0
点击应用图标或者命令行输入:测试
open -a Xquartz
程序坞能够看到有一个 Xquartz 应用:动画
在这个应用下进行偏好设置,勾选容许从网络客户端链接:
配置以后,此时暂时关闭 Xquartz 应用。
Socat 配置
与其余参考的方法不一样,咱们在有了 DISPLAY 环境变量以后,才会对 Socat 进行配置,输入:
socat TCP-LISTEN:6000,reuseaddr,fork UNIX-CLIENT:\"$DISPLAY\"
注意这个进程一直是运行状态,不要中断它。
如今从新开启 Xquartz 应用(由于个人实践发现 Xquartz 彷佛有可能会占用 6000 端口,若是先开启它的话,上面的命令可能不能正常执行)。
此外 Xquartz 应用须要多点击几回。
容器配置
让咱们查看主机 OS 上的 IP 地址:
ifconfig en0
en0: flags=8863 mtu 1500
ether 60:30:d4:61:f2:fa
inet6 fe80::1021:a4c7:f106:2c02%en0 prefixlen 64 secured scopeid 0x5
inet 192.168.0.106 netmask 0xffffff00 broadcast 192.168.0.255
nd6 options=201
media: autoselect
status: active
而后在容器内设置环境变量指向这个 IP 地址(因为退出容器后不会保存环境变量,所以每次进入容器都要执行这个命令):
export DISPLAY=192.168.0.106:0
或者在一开始启动容器时就进行设置:
docker run -e DISPLAY=192.168.0.106:0 [image_id]
这样就配置好了。
测试
简单测试应用
在容器内安装钟表小动画并执行:
sudo apt-get installxarclock
xarclock
测试脚本
或者,咱们能够在容器内写一个 Python 测试脚本:
1 importmatplotlib.pyplot as plt2 importnumpy as np3
4 x = np.linspace(-1, 1, 50)5 y = 2 *x6
7 plt.plot(x, y)8 plt.show()
运行这个脚本后,成功出来图像:
在实际过程当中,运行这个脚本可能会报这样的错误:
XIO: fatal IO error 11 (Resource temporarily unavailable) on X server "192.168.0.106:0"
after 382 requests (382 known processed) with 11 events remaining.
我本身的理解是可能 Socat 或者 Xquatz 的有些初始化工做没有完成,多运行几回就会成功跑通,而且比较稳定。
这个问题折腾了半天总算实现,仍是比较爽的哦。
参考