Docker -- Git 部署

jopen 11年前發布 | 46K 次閱讀 Docker 分布式/云計算/大數據

我一直聽說Docker是個很棒的新事物,但是我一直提不起興趣,直到我遇到一個切實的問題: 如果通過Docker來部署 Scout ,這么做會輕松一些嗎?</em>

下面我將分三部分來闡述。

哇哦, 有效的模擬生產環境的方法

Docker —— Git 部署

真實生產環境中有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</pre>

啟動一個鏡像超過了一分半鐘。那我要簡單修改下配置怎么辦啊?那我要驗證下可行性呢,那是不是又得重啟?又是一分半鐘了啊。

這分明就是個殘酷的懲罰嘛。

使用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絕對勝任在你的開發電腦上虛擬出一個完整的生產環境,而且很快。既然這么簡單,來,開動起來吧:我要徹底測試一下

構建鏡像如此方便快捷 - 緩存萬歲!

Docker —— Git 部署

老方法

如果你想把從空鏡像到一個功能鏡像的構建過程腳本化(例如:在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</pre>

然后,你想裝了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</pre>

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</pre>

哇哦 - 太不可思議了,怎么可能不到一秒鐘就安裝好了啊?看到這些緩存的keys(ex:dc92be6158b0)了嗎? 其實根本沒有重新逐條執行Dockerfile中命令, Docker認為這些命令已經執行過了,就不再執行,只是從緩存區中得到文件系統上的變化,通過這些變化可以組合出完整的文件系統。Docker之所以能 可以這樣神奇,關鍵在于AuFS file system,這是一個聯合文件系統(類似于記錄變化,然后通過變化來組合出原貌)。

總而言之, Docker可以輕松地反復構建鏡像,而且之后的構建過程,你幾乎無需等待。人無完人,我時常犯錯,但是Docker卻從不懲罰我的過失。

部署鏡像, 別更新基礎環境

老辦法

像許多其他部署一樣,Scout也使用長期運行的虛擬機。我們通過Puppet來更新基礎環境,但是, 這經常比我們想象得要痛苦:

  • 如果我們要更新stack, Puppet將運行虛擬機然后更新。這將花費很長時間-即使只是一小部分的stack需要更新,但是Puppet仍然會檢查全部。
  • 部署過程中也可能有問題。如果我們正在安裝Memcached,突然網絡中斷了一小下,那么apt-get install memcached的指令可能就會無效了。
  • 回滾主要變化,這也時常不是想象中那么順利(像更新Ruby版本).
  • </ul>

    這些都是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</pre>

    只要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</pre>

    在生產環境中的機器上,我把鏡像下載下來:

    root@prod:/# time docker pull dlite/appserver-memcached
    Pulling repository dlite/appserver-memcached
    Pulling image ad8f8a3809afcf0e2cff1af93a8c29275a847609b05b20f7b6d2a5cbd32ff0d8 (latest) from dlite/appserver-memcached

    real 0m15.749s</pre>

    只用了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.

      </li> </ul>

      Docker —— Git 部署

      的確震驚! 這意味著我不需要擔心一致性問題 - 我們不會修改運行的虛擬機,只是開始新的containers。這意味著可以輕松回滾!Memcached失敗了?停止運行 dlite/appserver-memcached的container,開始一個新container運行dlite/appserver鏡像。

      不足之處

      在短暫的containers上工作,這會導致一系列新問題- 分布式配置 / 協調和服務發現:

      • 當一個新的app服務器containers開始后,我們改如何更新HAProxy配置?
      • 當一個新的數據庫container開始后,app服務器應該如何與數據container來通信?
      • 如何跨越Docker宿主機器通信?
      • </ul>

        即將發布的Flynn.io,那會使用etcd,將會有幫助。但是,在小規模部署的時候沒必要擔心這些。

        總結一下: Docker來部署Git來開發

        當開發應用的時候,開發者可以利用Git的性能和靈活性。Git鼓勵嘗試,不會因為你出錯而懲罰你:在一個分支開始試驗,如果失敗了,只要git rebase或者git reset回復一下。開始一個分支非常簡單,上傳也很快速。 

        Docker鼓勵對于操作的試驗。Containers的啟動非常快速。 構建鏡像簡簡單單,使用另一個鏡像作為基礎鏡像也非常容易。部署整個鏡像非常快速。最后,回滾輕輕松松。

        快速+靈活= 部署即將成為令人愉快的事。

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!