1. 程式人生 > >使用 Docker 構建開發、測試環境

使用 Docker 構建開發、測試環境



docker 為開發人員和系統管理員提供了一個可供開發,分發(ship)和執行應用的平臺。將Docker化的應用及其依賴環境不需要經過任何修改就可以分發到任何地方--提供給QA,團隊成員或者分發到雲平臺中。這是使用Docker的一個很重要的目的。

Docker的英文字意是碼頭工人,也就是搬運工,這種搬運工搬運的是集裝箱(Container),集裝箱裡面裝的可不是商品貨物,而是任意型別的App,Docker把App(叫Payload)裝在Container內,通過Linux Container技術的包裝將App變成一種標準化的、可移植的、自管理的元件,這種元件可以在你的筆記本上開發、除錯、執行,最終非常方便和一致地執行在生產環境下的各種雲機房和伺服器上。

Docker 與傳輸虛擬機器的對比

Docker的核心底層技術是LXC(Linux Container),Docker在其上面加了薄薄的一層,添加了許多有用的功能。這篇stackoverflow上的問題和答案很好地詮釋了Docker和LXC的區別,能夠讓你更好的瞭解什麼是Docker, 簡單翻譯下就是以下幾點:

  • Docker提供了一種可移植的配置標準化機制,允許你一致性地在不同的機器上運行同一個Container;而LXC本身可能因為不同機器的不同配置而無法方便地移植執行;
  • Docker以App為中心,為應用的部署做了很多優化,而LXC的幫助指令碼主要是聚焦於如何機器啟動地更快和耗更少的記憶體;
  • Docker為App提供了一種自動化構建機制(Dockerfile),包括打包,基礎設施依賴管理和安裝等等;
  • Docker提供了一種類似git的Container版本化的機制,允許你對你建立過的容器進行版本管理,依靠這種機制,你還可以下載別人建立的Container,甚至像git那樣進行合併;
  • Docker Container是可重用的,依賴於版本化機制,你很容易重用別人的Container(叫Image),作為基礎版本進行擴充套件;
  • Docker Container是可共享的,有點類似github一樣,Docker有自己的INDEX,你可以建立自己的Docker使用者並上傳和下載Docker Image;
  • Docker提供了很多的工具鏈,形成了一個生態系統;這些工具的目標是自動化、個性化和整合化,包括對PAAS平臺的支援等;

Docker 有什麼用呢?以運維的角度來說,你的應用程式一般都需要特定版本的作業系統、應用伺服器、 JDK 、資料庫伺服器,還可能需要調整配置檔案和其他一些依賴關係。應用程式可能需要繫結到指定的埠和一定量的記憶體。這些執行應用程式所需要的元件和配置就是所說的應用程式作業系統。你當然可以寫一個包含下載和安裝這些元件的安裝指令碼。 Docker 簡化了這個流程,通過建立一個包含應用程式和基礎設施的映象(image),當作一個元件進行管理。這些映象可以建立 Docker 容器(container),容器執行在 Docker 提供的容器虛擬化平臺上。

Docker 有兩個主要元件:

  • Docker:開源的容器虛擬化平臺
  • Docker Hub:共享和管理 Docker 映象的 Saas 平臺

Docker 採用 Linux 容器 來提供隔離、沙箱、複製、資源限制、快照和其他的一些優勢。詳細資訊的可以看 excellent piece at InfoQ on Docker Containers 瞭解。

映象是 Docker 的“構建元件”,也是應用作業系統的只讀模版。容器是從映象創建出來的執行狀態,是 Docker 的“執行元件”。容器是可以執行、啟動、停止、移動和刪除的。映象儲存的倉庫是 Docker 的“分發元件”。

Docker的映象與容器

Docker 按啟動順序包含兩個元件:

  • 服務端:執行在宿主機上,負責構建、執行和分發 Docker 容器等重要工作
  • 客戶端:Docker 二進位制程式,接收使用者的命令和服務程式進行通訊

客戶端可以和服務端執行在一臺主機上,也可以在不同的主機上。服務端需要用 pull 命令從倉庫中拉一個映象下來。服務端可以從 Docker Hub 或者其他配置的倉庫中下載映象。服務端主機可以從倉庫中下載和安裝多個映象。然後客戶端就可以用 run命令 來啟動容器。客戶端與服務端通過socket或者REST API 進行通訊。

在 CentOS 中安裝 Docker:

sudo yum -y install docker-io    #安裝 docker
sudo service docker start           #啟動 docker 服務
sudo chkconfig docker on        #如果需要 docker 服務為自啟動

在Ubuntu/Debian中安裝 Docker:

sudo apt-get udpate
sudo apt-get install docker.io
sudo ln -sf /usr/bin/docker.io /usr/local/bin/docker
sudo sed -i '$acomplete -F _docker docker' /etc/bash_completion.d/docker.io #命令自動補全

其它作業系統的安裝可以檢視官方文件

在瞭解了Image和Container的概念後,我們可以開始下載一個Image,Docker的好處就是提供了一個類似github的Image倉庫管理,你可以非常方便pull別人的Image下來執行,例如,我們可以下載一個CentOS Image:

sudo docker pull centos:centos6

這裡 centos6是一個 tag,類似於 Git 的 tag,能過它來確定下載的 CentOS 的版本。下載完成後,執行docker images命令來列出你已經下載的 images:
下載截圖
下載之後,我們通過命令列來執行一個容器,命令很簡單,例如我們想執行一個 shell 終端:

sudo docker run -i -t centos:centos6 /bin/bash

預設情況下,docker 容器是不提供互動shell 的,也不提供標準輸入。可以指定-i選項來提供互動,提供-t 選項來分配一個偽終端。
在 Shell 中你可以做你想做的任意操作,安裝軟體,編寫程式,執行命令等。當你操作後想將結果儲存,這時可以用 docker commit 命令將 Container 提交成 Image。哦,假如你這裡還處在互動 shell 中,記得先使用Ctrl+d或者exit命令退出。

sudo docker ps -a

首先執行 ps 命令檢視容器ID
容器 ID 截圖
然後使用 commit 命令將容器進行儲存

sudo docker commit 851d custom/centos-aliyun

容器提交後,執行sudo docker images就能看到剛才提交的容器。

經常要在 Docker 中開啟某些網路服務,需要將 docker 虛擬機器的網路埠與宿主機埠連線起來。比如將 docker 中的8080埠對映到宿主機的80埠上:

sudo docker run -p 80:8080 custom/tomcat

這也是常用功能之一,尤其是服務需要記錄日誌、儲存檔案等時候。

sudo docker run -i -t -v /host/dir:/container/path ubuntu /bin/bash

以上是把宿主機器的/host/dir 掛載到/container/path 路徑上。

主要藉助於-volumes-from引數實現

COUCH1=$(sudo docker run -d -v /var/lib/couchdb shykes/couchdb:2013-05-03)
COUCH2=$(sudo docker run -d -volumes-from $COUCH1 shykes/couchdb:2013-05-03)

這個特性,讓人有許多想像空間,比如,一個容器例項用於 Web 儲存,另外兩個例項用於 Web 請求,實現讀寫分離。

方法1: 使用 save/load 命令來實現映象的匯入匯出

sudo docker save IMAGENAME | bzip2 -9 -c>img.tar.bz2
#或者你喜歡 tar.gz
sudo docker save IMAGENAME > imageName.tar.gz

映象匯入功能使用 load 命令解壓匯入即可

sudo docker load < imageName.tar.gz

# 喜歡壓縮的同學
bzip2 -d -c <img.tar.bz2 | sudo docker load

方法2: push/pull 將 image 檔案推送到Docker Hub上去。這種方法類似於 git。你可以在 Docker Hub 上建立自己的公有或者私有庫,適用於遠端分享。缺點是,有時 image 檔案特別大,需要考慮網路頻寬問題。
方法3: 搭建自己的私服repository,將 image 提交到私服,適用於企業網路。

在 Shell 指令碼環境中一步步安裝,低效且勞累。Docker 可以通過自定義 Dockerfile 實現自動化構建 docker 映象的指令碼,既方便分享也便於修改與模板化。

# VERSION 1.0.0

# 預設Centos,可以改成你需要的任意映象
FROM centos

# 簽名
MAINTAINER wupher "[email protected]"

RUN echo 'We are running some # of cool things'
RUN yum update 
RUN yum install -y openssh-server
RUN mkdir -p /var/run/sshd

# 設定root ssh遠端登入密碼
RUN echo "root:123456" | chpasswd

RUN yum install -y mysql-server
RUN yum install -y java-1.7.0-openjdk

# 安裝tomcat 等……

# 掛載硬碟,用於儲存 log
VOLUME ["/var/log/", "/var/volume2"]

# 容器開放22埠
EXPOSE 22

# 容器開放 8080埠
EXPOSE 8080

# 設定Tomcat初始化執行,SSH終端伺服器作為後臺執行,這樣 docker run image的時候,這些服務就自動啟動了
ENTRYPOINT service tomcat start && /usr/sbin/sshd -D

完整的 DockerFiler,可以參考官方文件

應用場景

Docker目前有以下應用場景:

  • 測試:Docker 很適合用於測試釋出,將 Docker 封裝後可以直接提供給測試人員進行執行,不再需要測試人員與運維、開發進行配合,進行環境搭建與部署。
  • 測試資料分離:在測試中,經常由於測試場景變換,需要修改依賴的資料庫資料或者清空變動 memcache、Redis 中的快取資料。Docker 相較於傳統的虛擬機器,更輕量與方便。可以很容易的將這些資料分離到不同的映象中,根據不同需要隨時進行切換。
  • 開發:開發人員共同使用同一個 Docker 映象,同時修改的原始碼都被掛載到本地磁碟。不再因為環境的不同而造成的不同程式行為而傷透腦筋,同時新人到崗時也能迅速建立開發、編譯環境。
  • PaaS 雲服務:Docker 可以支援命令列封裝與程式設計,通過自動載入與服務自發現,可以很方便的將封裝於 Docker 映象中的服務擴充套件成雲服務。類似像 Doc 轉換預覽這樣的服務封裝於映象中,根據業務請求的情況隨時增加和減少容器的執行數量,隨需應變。
  • 使用 Docker 來做分步式叢集模擬

現有缺陷

  • 無法修改 hosts 檔案,不能自己做域名解析。一種常用的方法是安裝dnsmasq 。
  • VM 的系統時間是 UTC 時間,貌似沒辦法修改。辦法倒也不是沒有,最常用的辦法是將宿主機器的/etc/localtime 對映到映象的/etc/localtime:ro 上去。但是這隻能使映象與宿主機器保持時區一致,假如希望不同的映象使用不同時區,只有在每次啟動時通過CMD 或者 ENTRPOINT命令來自動調整時區。
  • 目前還沒找到辦法將 Container 的 IP 改成靜態 IP,重啟容器的時候,IP 可能會發生變化。
  • 受限於 Lxc,外圍環境必須為 Linux,而且核心版本必須大於2.6.27。
  • 現在還不支援記憶體轉儲及執行狀態匯出。

Docker 現在才1.0版本,這些問題相信未來都將會解決。