本文翻譯自:《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
鼓勵實驗操做,容器啓動很是地快,建立一個鏡像更是很是地快,使用別的鏡像作爲基本鏡像也很是的容易,部署更個鏡像很是地快,最後但一樣重要的是,回滾也很是地方便。
快速 + 靈活 = 部署將會更快樂