可以停止假装Docker是最棒的开发环境了吧?

jopen 9年前
 

依托Docker运行的后端服务(如数据库,缓存,存储等)感觉相当完美,但对于编译语言,Docker却并未本地开发的理想之选。

每隔六个月我都尝试使用Docker作为本地开发环境。最近我又尝试了一遍,结果再次发现依然行不通。但是这次尝试我得出了进一步的结论,那就是对于大多数的开发堆栈而言,将Docker作为本地开发环境是毫无意义的。它引入了复杂性并且几乎没有任何优势。

问题的症结在于:若要实现高效的编辑、编译、运行周期,意味着本地开发环境的容器没必要和生产环境的容器保持一致。这等于是否定了容器最重要的 优势之一。此外,你也无法使编辑、编译、运行周期达到没有容器的本地环境下的高效和万无一失。这意味着付了集装箱运输税,但却毫无奖励。

先看看我的要求,一个高效的编辑、编译和运行周期需要单独的“非生产环境”的容器。首先,如果将生产环境的容器用于开发环境,容器必须包含某些预编译的组件,或者更加疯狂,比如在你的 Dockerfile 中运行编译。这样,每次微小改动都需要重建容器。你的E/C/R(编辑、编译、运行周期)看起来像这样:

docker-compose up -d # start all your containers, and leave them running 

edit myservice

make myservice # or whatever you do to build myservice

docker-compose build myservice

docker-compose restart myservice

按这种方式,整个重建的周期要花很长时间(超过30秒,还不包括服务自身的构建时间)来触发无聊至极的上下文切换。这绝对是生产力杀手。

你可以说这是个实现上的问题,并且最终这一重建周期将会大大加快,但是对比本地环境,构建和重启过程需要几乎无感。我也不觉得这会有效利用到Docker的镜像缓存。

如果愿意放弃使用生产容器作为本地开发容器的想法,或者运行一个没有构建过程的解释性堆栈,你或许可以改变游戏规则。你可将资源库目录装载到容器中,进而监听文件的变更,在容器内使用实时装载工具或刷新机制来重新编译和发布应用。

在一系列愚蠢的步骤下,这种方式也可工作的很好。比如我们将花时间寻找和设置 docker-osx-dev 开发环境,装载并与源文件夹高效的同步,又将花几个小时摆弄 boot2docker 以便使 inotify 正常工作起来,但是我们的确找到了解决方案。

但当我们回顾并看看这一变态的过程,我们竟然找不到令人信服的优势所在。我们在本地使用 foreman 启动所有服务,对比 docker-compose up foreman start 速度难以置信的快。除了Docker容器本身,我们也继承了管理 boot2docker 所带来的复杂性。配置文档长度也增加了三倍。

我们的初衷是使用Docker作为本地开发环境,打破在本地只能运行如 Memcached Elasticsearch 的几种关键服务。最终,我们得到结论,通过 docker-compose 运行后端服务是很有意义的,但配置和运行本地开发环境需要尽量简单。另外,我们又回到了通过 foreman 来运行本地微服务的方式。从此不再回头。

原文链接: Can we stop pretending that Docker is great for development environments? (翻译:Andrew)

译者介绍

Andrew,云计算从业者,PPTV技术总监,乐于分享对于云计算的一些想法和对未来科技的猜想。