特别说明:要在我的随笔后写评论的小伙伴们请注意了,我的博客开启了 MathJax 数学公式支持,MathJax 使用
$
标记数学公式的开始和结束。如果某条评论中出现了两个$
,MathJax 会将两个$
之间的内容按照数学公式进行排版,从而导致评论区格式混乱。如果大家的评论中用到了$
,但是又不是为了使用数学公式,就请使用\$
转义一下,谢谢。
想从头阅读该系列吗?下面是传送门:
- Linux 桌面玩家指南:01. 玩转 Linux 系统的方法论
- Linux 桌面玩家指南:02. 以最简洁的方式打造实用的 Vim 环境
- Linux 桌面玩家指南:03. 针对 Gnome 3 的 Linux 桌面进行美化
- Linux 桌面玩家指南:04. Linux 桌面系统字体配置要略
- Linux 桌面玩家指南:05. 发博客必备的图片处理和视频录制神器
- Linux 桌面玩家指南:06. 优雅地使用命令行及 Bash 脚本编程语言中的美学与哲学
- Linux 桌面玩家指南:07. Linux 中的 Qemu、KVM、VirtualBox、Xen 虚拟机体验
- Linux 桌面玩家指南:08. 使用 GCC 和 GNU Binutils 编写能在 x86 实模式运行的 16 位代码
- Linux 桌面玩家指南:09. X Window 的奥秘
- Linux 桌面玩家指南:10. 没有 GUI 的时候应该怎么玩
- Linux 桌面玩家指南:11. 在同一个硬盘上安装多个 Linux 发行版以及为 Linux 安装 Nvidia 显卡驱动
- Linux 桌面玩家指南:12. 优秀的文本化编辑思想大碰撞(Markdown、LaTeX、MathJax)
- Linux 桌面玩家指南:13. 使用 Git 及其 和 Eclipse 的集成
- Linux 桌面玩家指南:14. 数值计算和符号计算
- Linux 桌面玩家指南:15. 深度学习可以这样玩
- Linux 桌面玩家指南:16. 使用 CUDA 发挥显卡的计算性能
- Linux 桌面玩家指南:17. 在 Ubuntu 中使用 deepin-wine,解决一些依赖 Windows 的痛点问题
前言
关于 Docker 的介绍,我这里就不废话了。Docker 是什么?Docker 和虚拟机有什么区别?Docker 适用的场景是什么?这些介绍早就烂大街了。大家可以去 Docker 的官网首页看介绍,也可以在博客园的首页随便搜一下,入门级的文章到处都是。如果想了解更深一点的技术细节,可以看 sparkdev 的博客,我这里先对 sparkdev 表示感谢,我这篇随笔中,引用了他的部分内容。而且,我这篇的标题是“我对 Docker 的使用的学习心得”,重点是学习它的使用,而不是它的原理。
安装 Docker
在 Ubuntu 中安装 Docker 真的是太方便了。完全不用访问 Docker 的官网,不需要自己去下载,apt
超级牛力瞬间搞定。稍微需要注意的是,不是安装docker
软件包,而是安装docker.io
软件包。首先,我先用sudo aptitude search docker
命令查看 Ubuntu 的软件源中有哪些和 Docker 有关的包,如下图:
其中docker
被明确标记为 transitional package,所以我们安装下面的docker.io
包,使用sudo aptitude install docker.io
命令。安装完成后,使用sudo docker --version
查看一下,发现是最新的版本,而且是社区版,不是企业版,所以其版本号为 18.06.1-ce。如下图:
拉两个镜像测试一下
只要稍微了解一点 Docker 的人都知道有一个 dockerhub,和我们常用的 github 一样,可以获得别人精心制作并分享的资源。在 github 中,我们可以找到我们感兴趣的项目,并把它 clone 到本地。而在 dockerhub 中,这些资源叫 Image,我们可以把我们感兴趣的 Image 拉到本地,并以该 Image 为基础,运行一些 Container。
关于 Image 和 Container 的概念,我这里不再废话。我选择了一个 ubuntu,还有一个 spacevim。使用的命令分别为sudo docker pull ubuntu
和sudo docker pull spacevim
。如下图:
配置 Docker 使用中国的 Image 仓库
上面拉取 Image 的操作看似简单,其实经历过失败,主要原因就是国外的仓库被墙挡住了。解决这个问题的方法,就是设置 Docker 使用中国的 Image 仓库。其设置方法为修改/etc/docker/daemon.json
配置文件,如果没有该文件,就新建一个。将其内容修改为:
{
"registry-mirrors":["https://registry.docker-cn.com"]
}
然后,使用如下命令重启 Docker 服务:
systemctl daemon-reload
systemctl restart docker
运行一个容器
使用sudo docker image ls
命令可以查看我们的机器上有哪些 Image,使用sudo docker container ps -a
命令,可以查看我们的机器上有哪些 Container。在上图中,在我们拉取镜像之前,它们的显示结果都是空的。sudo docker container ps -a
命令之所以要加上-a
参数,就是为了显示所有的 Container,包括运行的和停止的。
拉取完了以后,再使用sudo docker image ls
命令,显示的就不再是空的了。如下图:
然后,使用sudo docker run -it spacevim/spacevim nvim
命令运行一个容器,启动 SpaceVim,如下图:
在上图中,我分别写了一个 C 语言的文件和一个 Python 语言的文件,同时修改了一下 SpaceVim 自己的配置文件。
介绍一下 SpaceVim
SpaceVim 是一个非常优秀的 Vim 整合项目,简单点说,就是通过各种插件把 Vim 打造成一个万能的 IDE,而且它对 NeoVim 支持非常好。确实很漂亮,功能也确实很强大。但是,我系统上用的 Vim 是我自己配的一个非常简洁的 Vim(请看我前面的随笔),如果再在系统上安装 SpaceVim 就不太方便。所以,使用 SpaceVim 官方提供的 Docker Image 就是一个非常方便的选择了。
Docker 的最常用命令和参数
从上面的截图可以看出,我们最常用的命令就是sudo docker run
命令,它就是以某个 Image 为基础运行一个新的 Container,注意,是新的 Container 哦。也就是说,每执行一次sudo docker run
,就建立一个新的 Container,哪怕它们用的是同一个 Image。如果要启动一个已经存在的 Container 怎么办呢?别担心,有sudo docker container start
命令。
最常用的参数是-i
和-t
,只有这样,我们才能够和 Container 中的程序进行交互。其次,就是-p
参数,可以把 Container 中的某个端口映射到主机的某个端口,这对网络服务非常重要。还有-v
参数,可以把主机的某个目录映射到 Container 中的某个目录,这样,共享文件就很方便了。
使用 SpaceVim 时遇到的问题:在一个 Container 中可以运行多个程序吗?
使用 SpaceVim 的 Image 启动一个 Container 后,问题来了。每次启动这个 Container,就自动运行 nvim,进入 SpaceVim 的界面,编辑文件是不成问题,可是这个编辑器界面毕竟不是 Shell 不是吗?我们其它的管理工作怎么做?
而我们使用 ubuntu 的 Image 启动 Container 后就很方便了,直接进入 Bash。所以问题来了,在一个 Container 中可以执行多个程序吗?
答案是肯定的,那就是sudo docker container exec
命令,如下图:
从上图可以看出,我们进入 Ubuntu 时,直接和 Shell 进行交互,所以可以非常方便地使用ls
、pwd
等命令,甚至可以使用cat /etc/os-release
命令查看系统的版本信息。当然,还可以使用apt
安装软件。而要想进入 SpaceVim 所在的容器,就需要使用sudo docker container exec -i spacevim-1.0 bash
命令再启动一个 Shell,这样就可以使用ls
命令看到我们刚才编辑的test.c
和test.py
了。甚至可以使用ps
命令查看该容器中运行的进程。
Docker 的学习资源
Docker 的官网就别看了,难受。买书呢?费钱!还不一定能找到优秀的。最好的办法就是查看 Docker 的手册页啦。使用sudo dpkg -L docker.io
命令,可以看到系统中安装了好多手册页,如下图:
如果输入man docker
,就是下面这样:
如果输入man docker run
,就是下面这样:
如果想自己写 Dockfile,就输入man Dockfile
。我就不继续截图了。每一个手册页都可以从头读到尾,这种流畅的感觉是在 Docker 的官网上查看文档体会不到的。
下一个问题:我们可以把我们的 Container 再打包带走吗?
运行一个 Container 后,我们可以在上面编辑文件、更改配置,还可以按需安装软件。做了很多工作后,我们可以把这个 Container 打包带走吗?当然可以了,使用sudo docker container commit
命令可以基于一个 Container 再创建一个镜像。然后使用sudo docker push
命令就可以把这个镜像再上传到 dockerhub 上了。当然,这只是理想状态,毕竟有墙的存在,而且 dockerhub 要注册后才能上传镜像。所以上传这个事就不是那么好做啊。
不过没关系,我们可以打包用 U 盘带走。sudo docker image save
命令可以把 Image 导出为本地文件。使用 U 盘带走后,使用sudo docker image load
命令可以从这个文件再导入镜像。
下一个问题:Docker 中的程序可以访问我们主机上的所有硬件资源吗?
其实我关心的是显卡。在我的上上篇随笔中,我写到了使用 CUDA 加速计算,而 CUDA 需要 Nvidia 的显卡支持。如果我要用 Docker 构建一个 CUDA 的开发环境,那就需要我 Docker 中的程序能够访问主机的显卡资源。从理论上讲,这是可以的。毕竟 Docker 不同于虚拟机,Docker 是和主机共享内核的,而 Nvidia 的驱动,只是一个内核模块。于是,我在使用 Ubuntu 镜像的 Container 中测试了一下。使用lsmod
命令查看内核模块,发现它确实是使用的 Nvidia 的驱动,如下图:
另外,使用sudo aptitude install nvidia-cuda-toolkit
安装 cuda-toolkit,也是可以安装的。因此,证明 Docker 中的程序可以访问主机上的所有硬件资源。使用 Docker 构建我们自己的开发环境不是梦。
最后一个问题:Docker 中能运行 GUI 程序吗?
答案是可以。
先来分析一下思路。在 Docker 中运行控制台程序时,我们需要给程序一个标准输入输出,就可以和程序交互了。在 Docker 中运行 Web 服务时,我们需要给程序一个 IP 和端口,就可以和服务交互了。GUI 程序需要什么呢?它们需要一个 X Server 的 Display。我们给它就行了。
DISPLAY的格式是unix:端口
或主机名:端口
,前一种格式表示使用本地的 unix 套接字,后一种表示使用 tcp 套接字。默认情况下,X11的服务端会监听本地的unix:0
端口,而 DISPLAY 的默认值为:0
,这实际上是unit:0
的简写。因此如果在 Linux 的控制台启动一个图形程序,它就会出现在当前主机的显示屏幕中。
而 unix 套接字就是一个文件,所以,可以使用-v
参数,将主机的 unix 套接字共享到 Container 中,然后,运行在 Container 中的 GUI 程序,就会出现在主机的屏幕上。
其实早在2015年的“Docker全球开发者大会”上,Docker 自家的美女程序员“杰西·弗莱泽尔(Jessie Frazelle)”就展示了一系列黑魔法一样的镜像。这些镜像中的大多数都使用了图形界面。比如,她使用这样的命令docker run -d -v /tmp/.X11-unix:/tmp/.X11-unix jess/libreoffice
在 Docker 中运行了 LibreOffice(这只是举例,真要运行成功还有很多细节需要完善),其中最重要的参数就是-v /tmp/.X11-unix:/tmp/.X11-unix
,也就是把主机的 unix 套接字映射到 Container 中。
OK,关于 Docker,今天就写这么多。我感觉我又找到了新世界的大门。
版权申明
该随笔由京山游侠在2019年03月08日发布于博客园,引用请注明出处,转载或出版请联系博主。QQ邮箱:[email protected]