瞎扯淡 为什么 Ruby 程序员应该了解和掌握 Docker

fsword · 2015年11月27日 · 最后由 reverland 回复于 2016年02月03日 · 12099 次阅读
本帖已被管理员设置为精华贴

为什么 Ruby 程序员应该了解和掌握 Docker

Docker 技术在 ruby 社区是有影响力的,我所知道的一些创业团队很早就在运用它来解决环境管理、持续集成以及部署的问题了。但是,也有一些同学尚未注意到这个技术,或者了解过后认为它不是很重要,所以我想讨论一下 Docker 对 Ruby 系技术的帮助。

有的人可能对 Docker 技术不太了解,不妨参考论坛里的这篇文章以及肖德时写的系列文章

Docker 与 Vagrant

我一直很喜欢 Vagrant 这个工具,两三年前就用它来进行自己项目的环境维护,那时候主要是做测试,由于 Vagrant 将操作系统环境进行了标准化,我很容易就能让自己的应用系统以及相关的测试结果保持稳定。

Vagrant 还有一个好处,Ruby 社区比较偏爱 Mac,但是线上的系统基本都是 Linux,所以开发环境所做的测试是有疑问的,特别是遇到一些有 so 依赖的 gem,这时一个和线上完全一样的环境就特别重要。

其实上面的表述不太准确,vagrant 也有各种 provider,我所说的场景,基本上都是 virtualbox 的 provider,所以这些地方正确的说法是 vagrant/virtualbox。

和 Docker 相比,vagrant/virtualbox 组合的成本还是很高的,无论是 setup 一个环境还是 reset 一个环境,都需要一段时间的等待,vagrant 只是把 virtualbox 的操作 DSL 了而已,底层的做法没有变化。而 Docker 由于本质上就是一个进程,因此天生就是轻量级的。对于运行时间在分钟级别的自动化测试工作,docker 显然有很大的优势。

当然,也有人会认为 docker 不能模拟完整的操作系统,不过这恐怕是一个优点而不是缺点。我在以前的文章中已经说过了,这里概述一下主要观点——

docker 简化了操作系统这个基础设施,让应用精简为其最核心的形态——携带有限资源的进程,在此基础上更有利于架构上的最佳实践

而对 Ruby 工程师而言,这个“最佳实践”中肯定少不了的一条就是——微服务

微服务

Ruby 工程师中有很多就是 Rails 工程师,而 Rails 实际上更倾向于单体架构,因此后来社区的工程师们才需要在实际工作中总结1 to 30这样的实践。

其实微服务本身不是个教条,即使没有人教,我们也常常自发的去进行服务化改造,但是这个工作并不容易,主要是会受到一些问题的掣肘,比如运维复杂度和系统测试成本会大幅度上升等等。

处理这些困难,首先当然是看是否必要,一些简单场景我们也可以用单体架构直接搞定,但是我们很容易会注意到,这两年大家越来越多的提到了微服务或者服务化,这背后其实是有趋势的——各种业务形态都在朝着互联网级的用户规模推进,同时大家都在努力从每一个用户的各种维度上挖掘价值(这导致了大数据的需求),这些场景变得越来越常见,单体架构是难以支持的。

既然微服务或者服务化不可避免,那么就要有相应的对策,虽然 Ruby 社区也有很多人在不同问题点上针对微服务进行改进(比如完善异步化框架,以及对服务协议的探索等),但是在基础设施层面,Docker 是最重要的武器,没有之一!

对 Ruby 工程师来说,Docker 能做两件事:约束边界和建立通用基础服务。

约束服务边界

Ruby 项目 Docker 化,并不是简单换个虚拟机那么简单,我们会面对拆分的压力,相信很多人尝试用 Dockerfile 来描述自己的项目的时候都会觉得束手束脚,但这些地方其实是促使我们想清楚——这个应用到底要做什么?它和外界是什么关系?对于外界的变化它如何响应?失败后怎样恢复?

这类的问题对系统架构非常重要。比如应用到底要做什么,这是让工程师去思考系统的目标,无论是提供 web 服务,管理调度后台任务,还是提供实时分析,它们都应该有一个尽可能单一的目标,在这个基础之上,我们建立的服务才有可能是易测试、易扩展和易维护的。

其它问题也类似,这些地方以前如果没有留意,很可能不是没问题,而是没意识到,使用 Docker 有助于我们意识到这些问题。

另外补充一点,由于 Ruby 项目不能完全脱离动态库依赖(java 大都可以),本身的打包机制又没有自包含结构(gem+bundle 不包括动态库,相比之下,Golang 是静态联编的),在分布式环境中的交付和软件包分发其实是有着先天不足的,Docker 的 Image 恰好补上了这一块,简直是睡觉时候有人送枕头了。

建立通用基础服务

当我们将应用系统分裂为各种服务并明确其边界以后,就出现了“分久必合”的问题,这很自然,服务化改造并不是各行其是,应用之间还是要协作,而对应用的运维——服务发现、水平扩展、容错等等——都需要基础设施的支持。

以前,对于这种运维基础设施,各公司甚至同一个公司的各个团队的做法都千差万别, 但是借助 Docker 以及周边的生态圈,我们可以很容易的得到通用的服务发现框架,享受自动的部署和弹性扩展。

更好的消息是,这些基础服务是通用的——不但不关心是 rails 还是 sinatra,甚至根本不关心是不是 ruby。

这也很好理解,Docker 是对进程这个操作系统工作单元进行了简化约束,而进程的概念本来就是与语言和框架无关的

这使得 Ruby 工程师以及 Ruby 项目可以更为自由的选择合适的技术去扩展公司的产品线。

延伸技术框架

Ruby 刚出来的时候,有很多来自 Java 社区的工程师加入其中(我也算是其中之一吧),很多人最大的感受是——视野被打开了。曾经象口号一样的“all in java”变成了落后的标志,大家意识到,一把钥匙开一把锁,用最合适的技术针对性的解决问题才是聪明的做法,单纯排斥某种技术或者语言框架并不明智。

这个道理在 Ruby/RoR 应用开发中也不例外,但是不少人在使用了几年 ruby 以后都会遇到一个问题——“ruby 确实很适合开发 Web,但是现在有些问题需要使用 XX 技术,而我们的系统严重依赖 ruby 环境,这该怎么办呢?”

我认为问题就出在“系统严重依赖 ruby 环境”上,研发的基础设施,比如配管、自动化测试、打包、部署,不应该仅满足一种技术或是语言,它一开始就要考虑到通用性,否则我们就只能“手里拿着锤子,看谁都像钉子”。

Docker 本身和语言无关,它唯一的约束大概就是要运行在 Linux 上,这个对互联网服务端系统来说也算是标准了,问题不大。所以,我们应该以 Docker 为核心打造研发的基础设施,这将是未来的一笔重要投资。

当然,为未来画饼是危险的,不过还好,Docker 领域的创业很活跃,有很多团队和公司已经做了相当多的基础工作,对于 Ruby 工程师和 Ruby 创业团队,去用现成的基础设施其实更方便。

写得很好,为什么要放在瞎扯淡节点呢? Docker 的优点这里列出很多了,Ruby 社区要积极跟上。 也许有些人觉得无从下手,列出几个资源:

安装

https://docs.docker.com/v1.8/installation/mac/ 默认 Mac 了。

Compose and Rails

https://docs.docker.com/compose/rails/

Basic Rails App with Docker

http://www.thagomizer.com/blog/2015/05/12/basic-docker-rails-app.html


国内 Docker 社区

http://dockone.io

微服务加重了运营负担,如果没有 docker,真的会玩残

前几天在 CentOS 7 上安装了 docker,感觉适合一个进程一个容器来跑,日志和数据目录通过 volume 挂载到容器里。测试跑了一个 redis 容器。您好,你有使用 docker 跑 Java 项目的经验吗? docker hub 上已经有 java jdk image,我们公司使用专用的版本,我装一个 rpm 包感觉怪怪的。

FROM        centos:6.7
ADD         jdk-6u26-linux-amd64.rpm /root
RUN         rpm -ivh /root/jdk-6u26-linux-amd64.rpm
RUN         rm -f /root/jdk-6u26-linux-amd64.rpm
ENV         JAVA_HOME=/usr/java/jdk1.6.0_26
ENV         PATH=$JAVA_HOME/bin:$PATH:.
ENV         CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar

docker 内部有一套内网,物理机上有个 docker0,我们线上集群是用的 LVS DR,下面的节点需要关闭 ARP 广播响应。现在用的 KVM 虚拟机,用 docker 这块也不知道怎么整了。

受益良多,不知道 LZ 对 Core OS 怎么看?

LZ,完全不是在瞎扯谈,👍

#1 楼 @ithelloworld 谢谢补充 #2 楼 @i5ting 完全赞同,docker 和微服务是好基友 #3 楼 @linuxgit 我对网络不精通,不过 DR 工作在数据链路层,理论上应该不影响基于 tcp 的上层应用,docker 的网络解决方案有好几个,建议了解一下,如果能在论坛上做个介绍就更好了 #4 楼 @darkbaby123 对 Core OS 关注不多,因为我更看重 Docker 的使用,目前知道 Core OS 不会影响我们使用 docker 的方式就可以了,基础选型要根据实际业务做测试 #5 楼 @rei 这篇文章槽点好多啊,我猜你的意思是不要过多考虑 future,我也同意,不过 Docker 不算想多了,做现有的项目时可以不考虑它,但是对于个人和团队技术规划是有必要做出选择的,当然不选择也是一种选择。顺便八卦一下,我以前比较过,circle 是我知道对 CI 理解最好的一个团队,但是原因倒不记得了 :-P #6 楼 @springwq 见笑,不知道怎么归类,所以扯扯淡吧 :-)

弱弱的问下1 to 30实践是啥? @fsword

#9 楼 @fsword 多谢 去学习一下 :plus1:

我倒是很想知道,业务逻辑拆分过程中带来的开发进度流失问题怎么解决。

#11 楼 @msg7086 这个问题其实和 docker 关系不大,不过问题本身很有价值。

简单说,这个开发进度流失可以减少(比如合理的设计,或者借助 docker 这种技术做一些简化)但不可能消除,所以答案是:“不能解决”

业务逻辑拆分带来的开发进度流失不可避免!!! 业务逻辑拆分带来的开发进度流失不可避免!!! 业务逻辑拆分带来的开发进度流失不可避免!!!

重要的话说三遍 :-D

那为什么还要做拆分呢?很简单,如果没好处我们并不建议拆分,这件事不能变成一个教条。通常情况下,我们从单体架构走向服务化应该有业务上的驱动原因(比如需要增强水平扩展能力以应对压力的急剧变化,或者需要将某个部分独立出来快速演化,以及商业上需要的某些必要的逻辑分离等等)。这时考虑拆分,就不能设想它是一顿免费的午餐,而是产品为了走的更好而付出的必要代价。

#12 楼 @fsword 感谢解答。 因为最近公司里就一直在讨论这个问题。我们的系统非常古老,Rails 1.2,代码庞大杂乱,又想要赶着继续演化增加功能换取投资,所以这方面我也是无比纠结。现在已经到了写一个新的小功能就会引入一堆 bug 的状态,一个 ticket 要做俩星期。然而又没机会重构重写甚至拆分,连测试代码都上不了……(因为系统开发的时候 RSpec 还没发明……然后就完蛋了)

另外我最近倒是在玩 systemd-nspawn,感觉用系统自带的 container 可能会比 docker 来得更方便一些?

#13 楼 @msg7086 你们的问题看来已经拖了很久了,所以还是尽早开始迁比较好,当然要掌握好节奏,循序渐进的进行 systemd-nspawn 我不了解,你不妨学习一下发个帖子在论坛上介绍介绍?

#14 楼 @fsword 是很久很久了。照我说的话,起码 4、5 年前就应该重构了。 而且代码质量很差,一个方法几百行,一个累几千行,而且写得很粗糙。 然而我自己又是个 Entry Level 的职位,经验少,也不可能带着公司团队干活…… 现在有几个方向。一个是拆分业务逻辑,也就是帖子里说到的,改造成 Microservice。 另一种就是先想办法迁移到比较新的平台,然后再逐渐把垃圾代码替换成高质量的。 不管哪个方向都难哪 😢

看了文章又去补 Microservices 的内容,受益匪浅。:thumbsup:

docker 是运维部署中的好东西,赞。

想我这种 junior 看了三遍还是云里雾里的,却少站在产品的角度去理解技术。学习了:)

#18 楼 @hmilym docker 这个技术绝不是仅仅和运维有关,就象集装箱绝不仅仅和船有关(这也是我没把这篇文章放在运维节点的部分原因),理解然后发挥 docker 的价值,最终是要涉及整个研发链路的

其实,docker 分布式的运维成本也挺高的

#21 楼 @xanderzhang 不是 docker 成本高,是分布式本来就成本很高,所以如果系统演化到非分不可(一般来讲这是必然趋势),就需要 docker 出手了,这就是我们必须掌握 docker 的原因

感谢分享; 我在的公司现在主要用 docker 来 deploy rails/nodeJS app,现在是 在 openStack 上用 coreOS fleet,deploy script 集成到 jenkkins;希望看到更多 docker 在 production 上应用的交流,学习借鉴一下

#23 楼 @gzrain 你是哪个公司?1 月份北京有一个 container 大会,是 dockerone 社区搞的,我了解了一下,案例比较多,打算去看看

#24 楼 @fsword 我在一间小公司,公司自己搭建硬件做 private cloud;infrastructure 和 deployment 都是由 team lead 和 DevOps 2 个牛人负责,技术上可能有些传统,用 makefile 和 ansible 配合 jenkis 建立 cluster/deployment;我做 ror 的,对 docker 只是知道一点点,但是挺有兴趣了解,特别是比较复杂的 production 情况下,例如 n 个 app server 做 load balance,主副 DB,extra 的 services 像 redis,elasticsearch,MessageQueue 等;不知道用 machine/swarm 或者一些工具像 deis 管理是否更方便

首先我觉得标题应该是所有程序员,而不是只是 Ruby 吾等”小众语言“的圈子,,哈哈。 在刚开始的时候,我的想法是利用 docker 给 Rails/Nodejs 做环境隔离。但是在深入了解 docker 真是,惊呼 Docker 真的是心太大了。我拿 docker 去给 rails 做环境隔离真的是大才小用了。 以前传统的 MVC 一旦发展集成为了一个大的应用系统,其开发的风险、维护压力会非常大。但是如果只是简单的替换成的微服务,又是压榨死运维的节奏。 微服务的初衷是希望在前期投资一下劳动力在开发,虽然初期开发量会比较大(指的是单应用 MVC 的代码级复用的工作量),但是换来的是架构上的可伸缩和将来运维时不会有”我不知道改了这行会不会 crash 的问题“(测试覆盖在很多企业级开发基本是 0……)。 然后 Docker 又给运维的同学们提供了一条节约成本的路,将以前 VPS 的管理变成了管理镜像,Docker+ 微服务形成一个向外暴露服务接口的黑盒子,接上消息总线,一个理想化的 SOA 体系就出来了。 个人体会这个方案中一切的一切都是拿了一部分开发工作量与运维工作量去换未来整个架构的可伸缩性。对于一些小周期的项目并不适合…… 我们现在正在尝试底层一些业务核心走总线的拿 rails 做快速原型开发并提供 json api,然后过了 3-6 个月逐步替换成 java spring boot 的方案。Docker 给了我们一个绝佳的工具完成这样的工作。 希望 Docker 社区越走越远吧。

#26 楼 @akirapanda 这篇文章是针对 ruby 工程师而写的,针对所有程序员的简书文集在这里

你的感受很充分,不过其实 docker 的未来(未必是 docker 公司的野心)还要更宽广些,实际上我是打算写一本书专门谈这个,不过考虑到自身水平和拖延症,还是先拿些文章凑数比较好。

spring boot 作为微服务基础挺契合你说的演化路径,如果有空来杭州的话,不妨在 ruby tuesday 上聊聊

#25 楼 @gzrain 做法是有些传统了,不知道你们的 private cloud 是否有其它因素考虑,如果没有特殊原因,还是多接触新趋势好一些

第一次接触微服务是因为 wildfly,那时候也是觉得视野一下被打开了。第一次认真接触 java,渐渐产生一种 all in java 是个不错选择的感觉。没想到历史真是反复。。。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号