使用 Docker 可以在本地为网站搭建一个开发环境,在本地开发时,通常我们会把网站的代码共享到容器里,这样可以直接编辑网站代码,然后立即看到运行结果。在生产环境下,我们需要把网站的代码 Build 到镜像里。在本地使用 Docker,需要用到 Docker for Windows 或 Docker for Mac 。它提供了很好的本地体验,但最大的问题是共享数据卷的性能非常差。注意这并不是 Docker 本身的问题。你在生产环境上用的 Docker 的共享数据卷不会有任何性能问题。
下面先介绍下原因,然后介绍一下我的解决方案。Docker for Windows 以下简称为 DFW,Docker for Mac 以下简称为 DFM。
原因
首先要知道 Docker 引擎只能在 Linux 核心的系统上运行,Windows 与 macOS 系统上是不能直接运行 Docker 引擎的。最开始的解决方案是在本地创建虚拟机,也就是 Docker Machine 提供的功能。创建一台 Linux 系统的虚拟机,并且上面已经安装好了 Docker 。 后来 Docker 公司为了让 Docker 在我们平时工作的电脑上有很好的本地化体验,推出了我们现在用的 Docker for Windows 与 Docker for Mac。
DFW 与 DFM 都分别用了自己的虚拟技术,比如你用 DFW,要在 Windows 上开启 Hype-V。在用户体验上,让我们感觉 Docker 就在本地运行,但实际上,还是用了些虚拟技术。这就导致了共享数据卷性能差的问题,也就是如果你的网站文件非常多(比如 Drupal),你在本地设置了共享数据卷,把网站文件共享给容器,你会发现网站的运行速度会相当慢。可能比实际的性能差了几十倍。
在本地开发网站的时候, 我们要设置共享数据卷,把网站文件共享到容器。而在生产环境上,网站的文件应该已经 Build 到了镜像里了,这也就不会存在性能问题。即使在生产环境上使用了共享数据卷,也不会遇到性能问题。所以只有在本地开发的时候, 我们才需要想办法解决这个数据卷的性能问题。
解决
我找到的方案是用一个叫 docker-sync 的工具,主要功能就是让我们创建一个同步文件用的容器,它会使用我们自己设置的同步方法,把本地文件同步到这个容器里。这个同步也可以是双向的,也就是容器里对文件的修改也会同步到本地。网站需要的其它服务可以使用这个同步容器创建的数据卷,这就越过了 DFW 或 DFM 用的共享数据卷的方法,这样也就解决了数据卷的性能问题。
说实话,这真的有点复杂。本身 Docker 就有点让人晕,我们还在挣扎容器与虚拟机之间的区别,因为要解决本地的容器数据卷性能问题,又带了一些新概念。比如 docker-sync,它是一套工具,你得先去安装一下它,它是用 Ruby 语言写的,可以使用 gem 命令安装它。docker-sync 提供了一些同步文件的方法,其中我用的是 unison 方法,unison 是个双向同步用的工具。
unison 是个独立的工具,docker-sync 用了这个工具在主机与容器之间同步文件。这个同步只有在我们本地开发时会用到,因为要解决性能问题,在生产环境上你不需要使用同步。即使你的网站在共享数据卷上,运行起来也不会有性能问题,一定要记清楚这一点。同步文件只是为了解决本地开发时遇到的共享数据卷的性能问题。
方案
我把之前做的 nest 改进了一下,支持使用 docker-sync ,仓库地址:https://github.com/ninghao/nest 。先安装好 Docker for Windows 或 Docker for Mac,再安装一下 docker-sync 工具。然后把 nest 克隆到本地,启动 docker-sync 同步,还要启动定义的服务。
运行网站需要的所有的服务都在 docker-compose-dev.yml 文件里定义好了。你把仓库下面的 example.env 复制一份,把复制的文件命名成 .env,这样你在使用 docker-compose 命令的时候就不需要指定特定的 compose 文件了。因为默认 docker-compose 需要用的 compose 文件是 docker-compose.yml。在本地我们的服务,跟在生产环境下需要的服务可能会不太一样,所以我们在本地创建了专门的配置文件,就是 docker-compose-dev.yml。
在 .env 文件里,已经说明了要使用的 compose 文件,设置成了 docker-compose-dev.yml 。这样你在执行 docker-compose 命令的时候就不需要再手工指定要用 docker-compose-dev.yml 文件了。不然你可能需要这样:
docker-compose -f docker-compose-dev.yml up -d
因为 .env 文件里设置了默认的 compose 文件。所以,现在可以像这样:
docker-compose up -d
结语
用 Docker 在本地搭建开发环境的流程,需要不断地优化,也需要多一点熟悉。我现在也经常会遇到需要手工输入命令才能解决的问题,比如去修改文件或目录的权限。理想状态应该是完全自动化,一行命令就能全部搞定。不过还好,遇到问题解决的过程全当学习了,就是过程太花时间,我到是希望问题全都让我遇上,这样我解决了以后,就可以让你少花钱时间去解决同样的问题。
Docker宁皓网有 Docker 课程包,订阅以后您就可以在线学习 Docker 了。



