本文翻译自:《Docker: Git for deployment -- Scout》,我的感受它的内容和标题不对,因此就没有直译过来,要是我理解错了请帮忙纠正。php
我据说了 Docker
多么使人惊叹,可是它并无征服个人心,直到我提出一个实际的问题:【若是 Scout 使用 Docker 来部署,它会让咱们的部署变得更顺利吗?】html
如下是三个案例:node
咱们线上有 16 台服务器,若是我尝试在本地使用 VirtualBox
配置每一个实例 512 MB内存,那么它将占用我笔记本的两倍内存(说明他笔记本只有 4G 内存),VirtualBox
须要有许多多余的开支来管理每一个子操做系统,Docker
在这方面是不同的——容器共享同一个操做系统,更有多是一样的二进制包文件和库文件,它能够运行在一台 Docker
主机上运行好几百个容器。mysql
我不能在本地彻底地模拟线上环境,让咱们来看一下经过 Vagrant
启动一台机器须要花多久:git
$ 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
启动一个镜像须要一分半钟,若是我须要修改一个配置文件并检测是否可以正常工做,那么须要重启镜像,那又是可怕的一分半钟。sql
若是你配置的有错,那将是一个残忍的惩罚。(每次修改就须要一分半钟才能看到结果)docker
Docker
后能想像 Docker
有多轻便吗?当你在 Docker
容器里面运行程序,你甚至可能不会注意到他们不是直接在主机上运行的,在下面的例子中,我从标记的 "rails" 镜像中启动一个 Docker
容器来运行 Rails 应用(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)
只须要两秒钟就完成了容器的启动和 supervisor 的启动(用来启动 Rails 应用的管理程序)ubuntu
总之,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
的依赖,可是你忘记了添加 Node 到 apt 库中
$apt-get install -y nodejs ... E: Unable to locate package nodejs
等你把这个问题解决了,想在新的基本镜像上运行你的脚本。
你须要从新安装 Ruby
,还须要在安装 Node
以前,忍受没必要要的 82 秒时间,真是痛苦至极。
Docker
的方式把建立镜像的步骤写入到 Dockerfile
文件中,看懂 Dockerfile
很是容易,由于里面就是你输入的命令,第一次安装 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
哇哦,为何安装 Ruby
连一秒都不到? 看那些 Keys (例如:dc92be6158b0 ),Docker
不会从新运行 Dockerfile
中的每一行命令,会检查那是否是已经运行过的命令,是的话直接从缓存中取回对文件的修改。
作的如此神奇,是由于 Docker
使用了 AuFS
文件系统(union file system)
总之,Docker
让咱们反复地建立一个镜像再也不那么痛苦,对于已经成功的后面就不须要再等了。I'm not perfect and Docker doesn't punish me when I make mistakes.
Scout和其它部署同样,很长的时间在运行虚拟机,使用 Puppet
来更新全部的基础设施,可是常常会很是的痛苦。
若是咱们部署更新到咱们的栈,Puppet
会在每台虚拟机运行更新,这会花去许多的时间——即便是一个小小的改变,Puppet
须要检查所其它全部的都检查一遍。在部署的时间会出问题:若是咱们安装 Memcached
时网络有点问题,apt-get install memcached
就会执行失败。
回滚到主要的改变经过不会像咱们想像的那么平稳,(例如更新 Ruby
的版本)
这些老是并非 Puppet
的问题, Puppet
和 Chef
是一个工具,当你要在一直运行的多台虚拟机上运行命令时,它会给你到多台机器上去运行,能够节省许多时间。
Docker
的作法部署镜像——不修改已经存在的虚拟机,你会 100% 有肯定在本地能够运行的,在生产环境也能运行。
镜像很是地大是吗?在 Docker
上不是这样的,请记住容器不会运行在宿主机上,它使用 union file system,当咱们改变一个镜像,咱们只须要新的一层。(说的好高大上,彻底听不懂,后面能够看看 union file system 为什么如此强大)
例如,在应用服务器上安装 Memcached
,建立一个新的镜像,而后给它打上一个 tag
叫 dlite/appserver-memcached
,它是基于 dlite/appserver
这个镜像的,dlite 是我在 index.docker.io 上的用户名。
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-memached
镜像下载下来了,镜像只有 10 MB 它使用 appserver 为基础镜像。
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
的改变就能够了。
大多数状况下,咱们的修改很是的小,因此下载一个新的镜像会很是地快。
启动一个新的 Docker
容器很快,上传和下载一个新的镜像也很轻量。
与其在现有的虚拟机上弄的乱七八糟,不如启动一个新的容器,而后把旧的容器删除就行了。
使人情奇的(Mind blown!)
它意味着咱们不须要去担忧统一性,咱们不会去修改现有的虚拟机,只是启动一个新的容器。那也意味着回滚也就是垂手可得的事!Memcached
挂了?直接中止使用 dlite/appserver-memcached
而后启动 dlite/appserver-memcached
的容器就行了。
生态还不是很完善,对于分布式配置 / 协调和服务发现没有好的解决方案(那是博文之前,如今应该很不同了,可参考:《腾讯Gaia:万台规模的Docker应用实践)》
咱们如何作到新应用服务窗口启动了,自动更改 HAProxy
的 配置文件?
新的数据库容器启动了,应用服务器如何自动与数据库容器通讯?
如何让不一样主机的 Docker
窗口通讯?
即将到来的 Flynn.io 将会解决这些问题,上面的问题将再也不是问题(如今这些老是早就不是问题了, Docker 的生态圈已经很是完善,国内 DaoCloud 在这方面就是领头羊,正在使用它的加速。)
建立一个项目的时候,开发者能够去使用 Git
来提高性能和灵活性。 Git
鼓励实验新的东西,而且在你作错了不会给你带来不少的麻烦事:在一个分支去作你的实验,若是作遭了,只须要 git rebase
或 git reset
, Git 能够很简单地就建立一个分支和推送一个分支。
Docker
鼓励实验操做,容器启动很是地快,建立一个镜像更是很是地快,使用别的镜像作为基本镜像也很是的容易,部署更个镜像很是地快,最后但一样重要的是,回滚也很是地方便。
快速 + 灵活 = 部署将会更快乐