这是我翻译的国外博客,如需转载请注明出处和原文链接

我一直听说Docker是个很棒的新事物,但是我一直提不起兴趣,直到我遇到一个切实的问题: 如果通过Docker来部署 Scout ,这么做会轻松一些吗?

下面我将分三部分来阐述。

哇哦, 有效的模拟生产环境的方法

真实生产环境中有16台服务器。如果我尝试用虚拟机去模拟的话,每个VirtualBox实例最好能有512MB内存。这样的内存需求是我笔记本内存的两倍大。此外VirtualBox还有许多限制,比如使用单独的系统内核和文件系统。但是这些限制对于Docker都不算个事,Docker的containers是共享一个宿主机器的系统的,甚至可能是同一个程序和库。一台Docker宿主机器上运行数百个containers也不是什么问题。

老办法

我实在没办法在本地模拟一个完全真实的环境,但是我们只要看一下启动一台虚拟机使用的时间:

$time vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
[default] Importing base box 'squeeze64-ruby193'...
...
[default] Booting VM...
[default] Waiting for VM to boot. This can take a few minutes.
... real 1m32.052s

启动一个镜像超过了一分半钟。那我要简单修改下配置怎么办啊?那我要验证下可行性呢,那是不是又得重启?又是一分半钟了啊。

这分明就是个残酷的惩罚嘛。

使用Docker

Docker到底有多么轻量级? 当你在Docker container中运行个进程时,你甚至都可能忘记这个进程竟然不是直接运行在主机上的。在下面的例子中,我运行一个叫“rails”的镜像在Docker container中,那里是个Rails App (Dockerfile):

root@precise64:~# docker run rails
2013-08-26 20:21:14,600 CRIT Supervisor running as root (no user in config file)
2013-08-26 20:21:14,603 WARN Included extra file "/srv/docker-rails/Supervisorfile" during parsing
2013-08-26 20:21:14,736 INFO RPC interface 'supervisor' initialized
2013-08-26 20:21:14,740 CRIT Server 'unix_http_server' running without any HTTP authentication checking
2013-08-26 20:21:14,754 INFO supervisord started with pid 1
2013-08-26 20:21:15,783 INFO spawned: 'rails' with pid 10
2013-08-26 20:21:16,841 INFO success: rails entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)

开始container和启动supervisor (这是负责开始Rails app的)一个只用了2秒

简而言之,Docker绝对胜任在你的开发电脑上虚拟出一个完整的生产环境,而且很快。既然这么简单,来,开动起来吧:我要彻底测试一下

构建镜像如此方便快捷 - 缓存万岁!

老方法

如果你想把从空镜像到一个功能镜像的构建过程脚本化(例如:在Ubuntu上怎么安装一个Rails stack),要是你不是经常干这事,那么正确获得所有的流,这绝对会是个痛苦的活儿。看看为Ruby安装依赖吧:

$time apt-get install -y -q ruby1.9.1 ruby1.9.1-dev rubygems1.9.1 irb1.9.1 build-essential libopenssl-ruby1.9.1 libssl-dev zlib1g-dev
Reading package lists...
Building dependency tree...
The following extra packages will be installed:
....
Setting up libalgorithm-merge-perl (0.08-2) ...
Processing triggers for libc-bin ...
ldconfig deferred processing now taking place real 1m22.470s

然后,你想装了NodeJS的依赖,但是忘了给apt添加源了:

$apt-get install -y nodejs
...
E: Unable to locate package nodejs

解决了源的问题后,你得确认你的脚本在新镜像中会不会有问题。那么你需要重装Ruby,好吧,又要浪费82秒了。正是神烦。

使用Docker

在Docker中,是把构建镜像的步骤放到Dockerfile. Dockerfiles是非常容易阅读的,因为你根本不需要学习DSL - 这就是些你输入时记录下来的基本命令。第一次安装Ruby会有点麻烦,但是让我们看看,通过Dockerfile来构建余下的镜像会发生什么:

FROM ubuntu:12.04
RUN apt-get update ## MYSQL
RUN apt-get install -y -q mysql-client libmysqlclient-dev ## RUBY
RUN apt-get install -y -q ruby1.9.1 ruby1.9.1-dev rubygems1.9.1 irb1.9.1 build-essential libopenssl-ruby1.9.1 libssl-dev zlib1g-dev
root@precise64:/# time docker build -t="dlite/appserver" .
Uploading context 92160 bytes
Step 1 : FROM ubuntu:12.04
---> 8dbd9e392a96
Step 2 : RUN apt-get update
---> Using cache
---> b55e9ee7b959
Step 3 : RUN apt-get install -y -q mysql-client libmysqlclient-dev
---> Using cache
---> dc92be6158b0
Step 4 : RUN apt-get install -y -q ruby1.9.1 ruby1.9.1-dev rubygems1.9.1 irb1.9.1 build-essential libopenssl-ruby1.9.1 libssl-dev zlib1g-dev
---> Using cache
---> 7038022227c0
Successfully built 7038022227c0 real 0m0.848s

哇哦 - 太不可思议了,怎么可能不到一秒钟就安装好了啊?看到这些缓存的keys(ex:dc92be6158b0)了吗? 其实根本没有重新逐条执行Dockerfile中命令, Docker认为这些命令已经执行过了,就不再执行,只是从缓存区中得到文件系统上的变化,通过这些变化可以组合出完整的文件系统。Docker之所以能可以这样神奇,关键在于AuFS file system,这是一个联合文件系统(类似于记录变化,然后通过变化来组合出原貌)。

总而言之, Docker可以轻松地反复构建镜像,而且之后的构建过程,你几乎无需等待。人无完人,我时常犯错,但是Docker却从不惩罚我的过失。

部署镜像, 别更新基础环境

老办法

像许多其他部署一样,Scout也使用长期运行的虚拟机。我们通过Puppet来更新基础环境,但是, 这经常比我们想象得要痛苦:

  • 如果我们要更新stack, Puppet将运行虚拟机然后更新。这将花费很长时间-即使只是一小部分的stack需要更新,但是Puppet仍然会检查全部。
  • 部署过程中也可能有问题。如果我们正在安装Memcached,突然网络中断了一小下,那么apt-get install memcached的指令可能就会无效了。
  • 回滚主要变化,这也时常不是想象中那么顺利(像更新Ruby版本).

这些都是Puppet's的毛病 - 像Puppet或者Chef这样的工具是非常重要,特别当你有着一些长时间运行的虚拟机,这些虚拟机可能随着时间的推移出现不一致的情况,那么这些工具就更重要了。

使用Docker

部署镜像 - 不用修改存在的虚拟机。你可以100%确保,本地运行什么,相应的生产环境就会运行什么。

但是镜像很大,对吗?不要整个Docker-记住containers不是运行在自己的操作系统上的,还有我们使用的是联合文件系统。当我们对于镜像做出改变时,我们只需要在上面添加新的层。

例如,我们安装Memcached在app服务器上。我们构建了一个新的镜像。我会标注asdlite/appserver-memcached,dliteis是我的index.docker.io用户名,这是基于dite/appserver镜像的。

root@precise64:/# time docker build -t="dlite/appserver-memcached" .
Uploading context 92160 bytes
Step 1 : FROM appserver
---> 8dbd9e392a96
Step 2 : RUN apt-get update
---> Using cache
---> b55e9ee7b959
Step 3 : RUN apt-get install -y -q memcached
---> Running in 2a2a689daee3
Reading package lists...
Building dependency tree...
...
Starting memcached: memcached.
Processing triggers for libc-bin ...
ldconfig deferred processing now taking place
---> 2a2a689daee3
Successfully built 2a2a689daee3 real 0m13.289s
user 0m0.132s
sys 0m0.376s

只要13秒就能安装好Memcached,这是因为之前的Dockerfile被缓存了,我爱这种速度的感觉。

我会上传和提交这些:

root@precise64:/# time docker push dlite/appserver-memcached
The push refers to a repository [dlite/appserver-memcached] (len: 1)
Processing checksums
Sending image list
Pushing repository dlite/appserver-memcached (1 tags)
Pushing 8dbd9e392a964056420e5d58ca5cc376ef18e2de93b5cc90e868a1bbc8318c1c
Image 8dbd9e392a964056420e5d58ca5cc376ef18e2de93b5cc90e868a1bbc8318c1c already pushed, skipping
...
Pushing tags for rev [ad8f8a3809afcf0e2cff1af93a8c29275a847609b05b20f7b6d2a5cbd32ff0d8] on {https://registry-1.docker.io/v1/repositories/dlite/appserver-memcached/tags/latest} real 0m28.710s

在生产环境中的机器上,我把镜像下载下来:

root@prod:/# time docker pull dlite/appserver-memcached
Pulling repository dlite/appserver-memcached
Pulling image ad8f8a3809afcf0e2cff1af93a8c29275a847609b05b20f7b6d2a5cbd32ff0d8 (latest) from dlite/appserver-memcached real 0m15.749s

只用了15秒就获得了dlite/appserver-memachedimage。注意那个镜像只有10MB大小,使用app服务器镜像作为基础镜像:

root@precise64:~# docker images
REPOSITORY TAG ID CREATED SIZE
appserver latest 7038022227c0 3 days ago 78.66 MB (virtual 427.9 MB)
appserver-memcached latest 77dc850dcccc 16 minutes ago 10.19 MB (virtual 438.1 MB)

我们没有必要将整个Memcached镜像都下载下来, 只要将Memcached镜像中的改变添加到dlite/appserver镜像中。

绝大多数时间,我们做出的改变会小得多。所以下载一个新镜像会更快。

这些会有很大的作用:

  • 开始新的Docker containers是非常快的
  • 上传+下载新的Docker镜像要轻量级的

    并非要改变现在运行的虚拟机,我们只是开始新的containers,停止旧的containers.

的确震惊! 这意味着我不需要担心一致性问题 - 我们不会修改运行的虚拟机,只是开始新的containers。这意味着可以轻松回滚!Memcached失败了?停止运行dlite/appserver-memcached的container,开始一个新container运行dlite/appserver镜像。

不足之处

在短暂的containers上工作,这会导致一系列新问题- 分布式配置 / 协调和服务发现:

  • 当一个新的app服务器containers开始后,我们改如何更新HAProxy配置?
  • 当一个新的数据库container开始后,app服务器应该如何与数据container来通信?
  • 如何跨越Docker宿主机器通信?

即将发布的Flynn.io,那会使用etcd,将会有帮助。但是,在小规模部署的时候没必要担心这些。

总结一下: Docker来部署Git来开发

当开发应用的时候,开发者可以利用Git的性能和灵活性。Git鼓励尝试,不会因为你出错而惩罚你:在一个分支开始试验,如果失败了,只要git rebase或者git reset回复一下。开始一个分支非常简单,上传也很快速。

Docker鼓励对于操作的试验。Containers的启动非常快速。 构建镜像简简单单,使用另一个镜像作为基础镜像也非常容易。部署整个镜像非常快速。最后,回滚轻轻松松。

快速+灵活= 部署即将成为令人愉快的事。

 

Docker:通过Git部署的更多相关文章

  1. 基于Jenkins,docker实现自动化部署(持续交互)

      前言 随着业务的增长,需求也开始增多,每个需求的大小,开发周期,发布时间都不一致.基于微服务的系统架构,功能的叠加,对应的服务的数量也在增加,大小功能的快速迭代,更加要求部署的快速化,智能化.因此 ...

  2. 基于Jenkins,docker实现自动化部署(持续交互)【转】

      前言 随着业务的增长,需求也开始增多,每个需求的大小,开发周期,发布时间都不一致.基于微服务的系统架构,功能的叠加,对应的服务的数量也在增加,大小功能的快速迭代,更加要求部署的快速化,智能化.因此 ...

  3. 深入浅出Docker(四):Docker的集成测试部署之道

    1. 背景 敏捷开发已经流行了很长时间,如今有越来越多的企业开始践行敏捷开发所提倡的以人为中心.迭代.循序渐进的开发理念.在这样的场景下引入Docker技术,首要目的就是使用Docker提供的虚拟化方 ...

  4. Docker 入门 到部署Web 程序- (阿里面试常用的docker命令和优点)

    最近阿里的面试官问我Docker是做什么用的,我记得之前360和美团,京东的都问过,但是一直没时间看,最近有时间了,系统的学习了一下Docker,在此做一下记录,方便各位看官学习交流 一.Docker ...

  5. .Net Core 自动化部署:使用docker版jenkins部署dotnetcore应用

    安装docker版jenkins 因为jenkins的docker版本本身没有 dotnetcore的环境,所以我们需要先自己动手制作下包含dotnet环境的jenkins Docker Contai ...

  6. jenkins+Docker持续化部署(笔记)

    参考资料:https://www.cnblogs.com/leolztang/p/6934694.html (Jenkins(Docker容器内)使用宿主机的docker命令) https://con ...

  7. docker持续集成部署、csphere监控平台【转:http://blog.csdn.net/java_dyq/article/details/51997024】

    为什么使用Docker “ 从我个人使用的角度讲的话  部署来的更方便 只要构建过一次环境 推送到镜像仓库 迁移起来也是分分钟的事情 虚拟化让集群的管理和控制部署都更方便 hub.docker.com ...

  8. Docker+Jenkins+Git发布SpringBoot应用

    Doccker Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之 ...

  9. RocketMQ(2)---Docker集群部署RocketMQ

    RocketMQ(2)-Docker集群部署RocketMQ =前言= 1.因为自己只买了一台阿里云服务器,所以RocketMQ集群都部署在单台服务器上只是端口不同,如果实际开发,可以分别部署在多台服 ...

  10. 使用Gitlab-CI 实现NetCore项目Docker化并部署到阿里云K8S

    使用Gitlab-CI 实现NetCore项目Docker化并部署到阿里云K8S 先行条件: 1.了解NetCore项目基础命令,如dotnet publish   等几个常用命令. 2.了解Dock ...

随机推荐

  1. java实现快速排序算法

    1.算法概念. 快速排序(Quicksort)是对冒泡排序的一种改进.由C. A. R. Hoare在1962年提出.2.算法思想. 通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据 ...

  2. 算法笔记_055:蓝桥杯练习 Tricky and Clever Password (Java)

    目录 1 问题描述 2 解决方案   1 问题描述 问题描述 在年轻的时候,我们故事中的英雄——国王 Copa——他的私人数据并不是完全安全地隐蔽.对他来说是,这不可接受的.因此,他发明了一种密码,好 ...

  3. T-SQL 数据库的创建

    create database databaseNameon primary(  Name =dbName1,  FileName='C:\mydatabase1\dbName1.mdf',  Siz ...

  4. ant font 本地化

    要解决的问题1.antd默认iconfont指向的是阿里在公网CDN上部署的url 2.项目需要在本地进行部署,使用的是本地文件的访问方式,希望能内网/离线使用 在ant-design-pro中的配置 ...

  5. DOM BOM document window 区别

    DOM 是为了操作文档出现的 API,document 是其的一个对象: BOM 是为了操作浏览器出现的 API,window 是其的一个对象.   使用下图讲解:   归DOM管的: E区:即doc ...

  6. TX2 ROS IDE开发环境配置

    参考资料: http://www.mamicode.com/info-detail-1663827.html    基于Qt搭建ROS开发环境 https://blog.csdn.net/sbtxg/ ...

  7. 将object格式转为json格式

    在页面内容显示时,有时需要用到json格式.但数据库内容的显示,需要将数据库中获取的格式转为json: using Newtonsoft.Json;public static string ToJso ...

  8. java基础讲解09-----接口,继承,多态

    还有什么包装类,数字类,这些简单的我就不想过去介绍,前面也大概的介绍了下,继承,多态 1.类的继承 继承的思想:基于某个父类的扩展,制定一个新的子类.子类可以继承父类原有的属性,方法,也可以重写父类的 ...

  9. 机器学习实战笔记7(Adaboost)

    1:简单概念描写叙述 Adaboost是一种弱学习算法到强学习算法,这里的弱和强学习算法,指的当然都是分类器,首先我们须要简介几个概念. 1:弱学习器:在二分情况下弱分类器的错误率会低于50%. 事实 ...

  10. unity, 什么时候用静态类,什么时候用单例

    如果没有成员变量,或者成员变量都是常量,则用静态类. 如果有成员变量,则用单例.(以便让成员变量有初始化机会). //静态类 public class CmyFuncs{ public float m ...