在生產環境使用Docker部署應用

Docker是如今開發應用程序的不錯選擇;由於對於一個研發組來講,部署一個應用不再用像之前那樣繁瑣的修改、設置配置文件了;由於對於Docker來講它「屏蔽」了應用程序的運行環境,無論你使用Mac、Linux仍是Windows都能用相同的方式運行。前端

可是,當你使用Docker將應用部署到生產環境時,你會以爲Docker仍是有些「弱」,至少從Ruby On Rails(ROR)的角度出發是這樣的。當我查找與測試了不少不一樣的部署方法與Docker鏡像後發現:確實沒有一個確切並且標準的部署方案。在這篇文章中我會分享一種生產環境部署ROR應用的最佳實踐。linux

docker

標準web

在實際操做以前,咱們列舉生產環境部署應用的標準:sql

  1. 易於使用:部署應用自己應該十分簡單,否則部署新程序的過程會變得十分「恐怖」。
  2. 零服務中斷:讓咱們面對它——零服務中斷部署ROR應用程序已經成爲當今的標準。
  3. 自動化部署:我更習慣把代碼推送到代碼倉庫,而後使用Codeship這樣的工具自動測試,測試經過後自動將代碼部署到生產環境的服務器。我但願Docker能完成相同的工做。

    ## 操做就像以前我說過的,我但願部署過程越簡單越好。若是你看過Docker:Part4這個視頻,可能對如下命令有所熟悉,它啓動了一個叫db的容器(跑postgres數據庫),以後又啓動了一個叫web的容器,最後將容器「web」跟容器「db」鏈接起來。docker

$ docker run -d --name db training/postgres
$ docker run -i -t --name web --link db:db -p 45000:80

固然若是你照着這麼作來部署程序,當你敲了不少次這樣的命令後,並且保證不遺漏的敲了不少次這種命令後,你會發現這是個「坑爹的」噩夢。這就是爲何會有Fig的緣由。數據庫

FIG服務器

若是你用Dockerfile來定義如何生成你的容器,那麼Fig則能夠幫你定義整個容器的運行框架。Fig將「添加數據卷(add volumes)」、「鏈接容器」(link container)與「映射端口」等操做都封裝到一個YAML的描述文件中;如同前面提到的CodeTV中描述的那個操做在Fig中簡化成以下形式:負載均衡

web:
build: .
ports:
- "80:80"
links:
- db

db:
image: postgres
ports:
- "5432"

volumes:
- /etc/postgresql
- /var/log/postgresql
- /var/lib/postgresql

我在YAML中定義了兩個容器:web與db;容器web生成自當前文件夾下的Dockerfile,向外暴露了80號端口,同時連接到了容器db。容器db生成自DockerHub的PostgreSQL鏡像,向外暴露5432號端口。使用此YAML配置文件,fig能夠用如下命令生成容器,而後依照配置文件的意圖啓動它們。框架

$ fig build
$ fig up -d

Fig會先啓動被連接的容器db,這樣容器web就不至於連不上數據庫。-d參數表示之後臺運行的方式啓動容器,這樣能夠保證用戶登出操做系統後,容器任然在運行。您能夠登陸Fig的官方網站獲取更多的配置信息。工具

部署

如今咱們能夠很容易的啓動一個Docker容器,可是怎麼在生產環境下部署Docker容器呢?若是在生產環境下安裝了Fig與Docker,咱們全部要作的就是克隆以前的容器鏡像,而後用相同的fig命令來啓動容器。可是,如今的問題是如何更新線上運行的容器。

不幸的是,Fig能夠很是優雅的啓動一個容器,可是它並不擅長更新並重啓服務。固然,你能夠在代碼倉庫拉取程序的更新,而後從新運行以上的fig命令來達到這個目的;可是,在容器在更新代碼,從新啓動的過程當中,就不能對外提供服務了。爲了應對這種狀況,咱們使用原生的Docker命令,並引入Nginx作反向代理(注:軟負載)來解決這個問題。

咱們首先把容器監聽的端口修改掉,由於Nginx須要監聽80號端口。咱們這麼修改:

web:
build: .
ports:
- "8080:80"
links:
- db
...

經過修改Fig的配置文件,咱們的web容器修改爲監聽8080號端口。而Nginx要配置成8080與8081端口的負載均衡;因此Nginx的配置以下:

upstream docker {
server 127.0.0.1:8080;
server 127.0.0.1:8081;
}

server {
listen 80;
location / {
proxy_pass http://docker;
}
}

重啓Nginx後,Nginx就開始在8080與8081號端口之間作反向代理(軟負載);當其中任何一個端口失效後,Nginx將請求自動轉發到另外一個,直到失效後的端口恢復。這樣,咱們就能從Git中拉取更新,而後運行下面的命令將其啓動:

$ docker run -d --name web1 --link codetvjournal_db_1:db -p 8081:80 codetvjournal_web:latest

當咱們肯定8081號端口的web1容器啓動並服務正常後,咱們就能夠中止8080號端口的服務並開始爲8080號端口服務進行更新了。我推薦使用原生的docker命令而不使用Fig來完成這個工做,由於這樣能夠避免干擾到正在運行的db容器(注:做者可能指的是以前寫好的YAML,裏面包含了啓動db容器的配置)

咱們能夠用上述方法建立不少個web容器,只要保證它們佔用的端口與容器名不一樣便可;同時使用Nginx在它們前端作負載便可實現不掉線的程序升級。

自動化

那麼問題又來了,怎麼將上述的更新流程自動化運行呢?有兩個方式能夠達到:

  1. 將容器更新、啓停、切換等操做封裝到一個單一的腳本中,這個腳本能夠加入到傳統的上線流程(注:新代碼拉取,自動測試,自動部署的流程,做者稱之爲deployment pipeline)以後執行;
  2. 另外一種方式是,使用相似Consul或者etcd等的發現服務來管理容器的更新,啓停,與發現;這會更加「高大上」。

因此,使用Docker在生產環境中部署服務不像你想象中那麼容易。我推薦你們試試上面所說的方法;同時分享你本身的實踐經驗給你們,這會幫助你們一同使用Docker。Docker仍是個很年輕的產品,同時又是個很是熱門的產品,它確定會在將來不斷的演化升級。

免費提供最新Linux技術教程書籍,爲開源技術愛好者努力作得更多更好:http://www.linuxprobe.com/

相關文章
相關標籤/搜索