使用 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 了。
评论
好文,刚好需要,皓哥真是带领我们跨过无数的坑啊
7 年 5 个月 以前
可能还会遇到很多问题,慢慢解决。我遇到的问题主要是权限问题。
7 年 5 个月 以前
这个问题很好。但我现在不清楚为什么要使Docker! 为什么不直接使用LNMP LAMP 或是MAMP MNMP 这样的组合在本地开发测试。
是为了很好的统一开发平台。还是我们布署服服务器需要用Docker配置为生产环境。还有皓哥你主站有用docker作为生产环境吗》
7 年 5 个月 以前
我有几个站点是在 Docker 上运行的,一个 WordPress,一个分析应用,一个论坛。其实,如果你对正在使用的开发流程完全满意,我觉得就不需要强制做什么改变。您没事的时候可以了解下 Docker,说不定哪天你会突然觉得它可以帮你解决遇到的问题。把它放在你的工具箱里,需要的时候再拿出来用。
7 年 5 个月 以前
一个 WordPress,一个分析应用,一个论坛 网址是多少?
7 年 5 个月 以前
WordPress 是自己内部用的 https://work.ninghao.net ,我会在上面写些文章,但都没有发布。分析统计流量用的是 Piwik,没有前台。论坛地址是:https://talk.ninghao.net
7 年 5 个月 以前
王老师 教学一下 Piwik
7 年 4 个月 以前
皓哥, docker的文章学了二周了, 用nest总有些问题,能请教一下么?
1) docker-sync是一定要用的吗?
2) 我没用docker-sync, 安装完nest用docker-compose up -d, 打开localhost:8080/phpinfo.php 显示找不到文件, nginx的根目录设置为root /mnt/app/www;
3) localhost:8081也有错误, 信息如下:
#2003 - Can't connect to MySQL server on 'db' (111 "Connection refused") — 服务器没有响应。
望皓哥帮忙看一下. 能不能发我邮箱交流一下: polyclass@foxmail.com, 谢谢了!
7 年 2 个月 以前
docker-sync 不一定要用,用它我是想解决在本地开发环境上,共享数据卷的性能问题。
7 年 2 个月 以前
在本地做一个VM虚拟机,使用虚拟机上面的数据卷与容器共享文件,本地的文件直接与虚拟机同步 这样不就解决问题了么?当然这个只是针对对DFM,估计DFW就不可以了。另外我想知道,能不能把数据卷也就是存储也专门创建一个容器呢?这样在创建集群的时候,就可以有一个或者多个专门的服务器用来存储文件;
3 年 7 个月 以前
如果一个容器专门存储文件,那么随着我们的开发程度加深,我们的这个容器的大小也会随着增大么?容器中的文件在我们更换了服务器以后,数据也会跟着转移么?还是说容器内的文件不会随着容器移动,而是存储在主机上面?
3 年 7 个月 以前
在容器里的文件会随着容器的销毁而消失。如果你想保留容器里的文件,需要设置使用数据卷。
3 年 7 个月 以前