的日常工作中會經常進行鏡像構建操作。構建Docker鏡像非常簡單,而且方法也有幾種。
3.3.1. 手工創建
這個方法最簡單直接的方法。其流程是啟動一個容器,在里面進行一些列安裝、配置操作,然后運行docker commit命令來將容器commit為一個新鏡像。
$ sudo docker run -t -i ubuntu bash root@c4be1df52810:/# apt-get update root@c4be1df52810:/# apt-get -y install redis-server root@c4be1df52810:/# exit
通過下面的命令得到剛才容器的ID號并進行commit操作。
$ sudo docker ps -q -l c4be1df52810 $ sudo docker commit -m="manually created image" -a="bin liu" -run='{"CMD":["/usr/bin/redis-server"], "PortSpecs": ["6379"]}' c4be1df52810 liubin/redis:manually Warning: '-run' is deprecated, it will be removed soon. See usage. 744ce29b2fcf0ad7ad8b2a89c874db51376c3fdd65d1f4f0c6f233b72f8c3400
注意上面的警告信息,在docker commit命令指定-run選項已經不被推薦了,這里為了說明這個例子而故意使用了這個選項。建議創建鏡像還是使用Dockerfile的方式,即能將創建過程代碼化、透明化,還能進行版本化。
再次運行docker images命令,就應該能看到我們剛才通過docker commit命令創建的鏡像了(鏡像ID為744ce29b2fcf,鏡像名為liubin/redis:manually)。
3.3.2. 使用Dockerfile文件
使用Dockerfile構建Docker鏡像
這是一個官方推薦的方法,即將構建鏡像的過程代碼化,比如要安裝什么軟件,拷貝什么文件,進行什么樣的配置等都用代碼進行描述,然后運行docker build命令來創建鏡像文件。官方的自動構建即是基于保存在GitHub等代碼托管服務上的Dockerfile進行的。Dockerfile即是具體的用于構建的配置文件名,也是這類文件的類型名稱。
使用Dockerfile構建Docker鏡像非常簡單,我們只需要創建一個名為Dockerfile的文件,并編寫相應的安裝、配置腳本就可以了。我們還是以上面安裝Redis服務為例,看看如何使用Dockerfile構建一個鏡像。
首先,創建一個redis文件夾(文件夾名任意,無任何限制),并進入該文件夾,然后創建一個Dockerfile文件。這個文件的文件名是固定的,其內容如下。
FROM ubuntu MAINTAINER bin liuRUN apt-get update RUN apt-get -y install redis-server EXPOSE 6379 ENTRYPOINT ["/usr/bin/redis-server"]
Dockerfile文件的語法非常簡單,每一行都是一條指令,注釋則以#開頭。每條指令都是“指令名稱 參數”的形式,指令名稱一般都是大寫。比如FROM指令表明了我們的鏡像的基礎鏡像(嚴格來說叫父鏡像,我們的所有操作都將以此鏡像為基礎),這里是ubuntu,但實際上它可以是存在的任何鏡像,比如liubin/ruby。RUN指令則用來在構建過程中執行各種命令、腳本,比如這里是apt-get命令,你也可以指定一個很復雜很長的腳本文件路徑。AUFS有42層文件系統的限制注 7,這時候我們可以通過在RUN指令中執行多條命令,即cmd1 && cmd2 && cmd3 && ...這種形式就可以可避免該問題了。EXPOSE表示此鏡像將對外提供6379端口的服務。ENTRYPOINT則指定了啟動該鏡像時的默認運行程序。
注 7 https://github.com/dotcloud/docker/issues/1171
具體的Dockerfile語法在官方網站注 8有詳細說明,相信花個10分鐘就能通讀一遍,這里唯一比較容易混淆的就是ENTRYPOINT和CMD指令了,關于它們的區別,還是留作每位讀者自己的課題去研究一下吧。
注 8 https://docs.docker.com/reference/builder/
Dockerfile準備好了之后,運行docker build命令即可構建鏡像了。
$ sudo docker build -t liubin/redis:dockerfile .
這里-t表示為構建好的鏡像設置一個倉庫名稱和Tag(如果省略Tag的話則默認使用latest)。最后的一個.表示Dockerfile文件的所在路徑,由于我們是在同一文件夾下運行docker build命令,所以使用了.。
由于篇幅所限,這里我們就省略了docker build命令的輸出。不過如果你親自動手執行docker build命令的話,那么從它的輸出應該很容易理解,Dockerfile里的每一條指令,都對應著構建過程中的每一步,而且每一步都會生成一個新的類似容器的哈希值一樣的鏡像層ID。也正是這些層,使得鏡像能共享很多信息,并且能進行版本管理、繼承和分支關系管理等。這除了能節省大量磁盤空間之外,還能在構建鏡像的時候通過使用已經構建過的層(即緩存)來大大加快了鏡像構建的速度。比如在我們在使用Dockerfile進行構建鏡像時,如果在某一步出錯了,那么實際上之前步驟的操作已經被提交了,修改Dockerfile后再次進行構建的話,Docker足夠聰明到則會從出錯的地方開始重新構建,因為前面的指令執行結構都已經被緩存了。
如果你使用docker history命令來查看該鏡像的歷史信息,你會發現它的輸出和docker build的記錄是相匹配的,每一條Dockerfile中的指令都會創建一個鏡像層。此命令還能查看每個鏡像層所占空間大小,即SIZE列的內容。比如本例中MAINTAINER這樣指令,實際上它只是關于鏡像的元數據,并不占用額外的磁盤空間,所以它的層大小為0字節。而RUN apt-get -y install redis-server創建的層則會在鏡像中增加文件,所以是需要占用磁盤空間的。
自動構建(Automated Builds)
Docker Hub的目的之一就是要成為應用程序交換的中轉站,它還支持自動構建功能。自動構建的Dockerfile可以托管在GitHub或者Bitbucket上,當我們將代碼提交并push到托管倉庫的時候,Docker Hub會自動通過webhook來啟動鏡像構建任務。
配置自動構建很簡單,只需要在Docker Hub中綁定GitHub或者Bitbucket賬號就可以了,如何具體操作這里不做詳細說明了。
3.3.3. 使用Packer
Packer注 10是一個通過配置文件創建一致機器鏡像(identical machine images)的非常方便的工具。Packer同樣出自Vagrant的作者Mitchell Hashimoto之手。它支持虛擬機VirtualBox和VMWare等虛擬機軟件,以及Amazon EC2、DigitalOcean、GCE以及OpenStack等云平臺,最新版的Packer也增加了對Docker的支持。
Packer的使用也比較簡單,這里我們就舉例說明了,讀者可以自己試一下。
3.4. 發布鏡像
如果你愿意,還可以將在本地制作鏡像push到Docker Hub上和其他人分享你的工作成果。
首先你要有一個Docker Hub賬號并已經為登錄狀態,這樣才能往Docker Hub上push鏡像文件。注冊Docker Hub賬號只能通過網站注冊注 11,這里我們假設各位讀者已經擁有Docker Hub了賬號。
登錄Docker Hub通過docker login命令。
登錄成功后,我們就可以push鏡像了。注意這里我們沒有指定Tag,Docker知道如何去做。
$ sudo docker push liubin/redis
我們前面說過,鏡像文件是分層的,很多鏡像文件可以共用很多層。比如我們這次往服務器push鏡像的時候,實際push的只有一層(744ce29b2fcf)而已,這是因為我們的鏡像文件是基于ubuntu這個base鏡像創建的,而ubuntu鏡像早已經在遠程倉庫中了。
我們在層744ce29b2fcf中對應的操作是bash命令,并在容器中安裝了Redis。而這次修改只有不到6M的容量增加,而如果只是修改配置文件的話,那么一次push操作可能只需要耗費幾K的網絡帶寬而已。
4. DockerCon14總結
首屆Docker大會(DockerCon14)于當地時間6月9日~6月10日在舊金山舉行。相對于計劃中的500個參會名額,最終有超過900人報名,并提交了超過150個演講申請。
關于這次Docker大會的更多信息可以參考其官方網站:http://www.dockercon.com/。
4.1. Docker官方發布的產品和服務
4.1.1. Docker 1.0的發布及商業支持
在這次大會上最重要的事情莫過于Docker 1.0的發布了。Docker 1.0已經可以在Red Hat、Debian、Ubuntu、Fedora、SuSE等主流Linux系統下運行,在功能、穩定性以及軟件質量上都已經達到了企業使用的標準,文檔也更加系統、完善。并且提供了Docker Hub云服務,方便開發者和企業進行應用分發。最重要的是Docker, Inc.還宣布了對Docker的商業支持,尤其是對Docker 1.0版本的長期支持。此外,Docker, Inc.還會提供Docker相關的培訓、咨詢等工作。
4.1.2. Docker Engine + Docker Hub
同時從1.0開始,Docker的架構也發生了較大的變化。Docker已經從單一的軟件轉變為了一個構建、發布、運行分布式應用的平臺。
新的Docker平臺由Docker Engine(運行環境 + 打包工具)、Docker Hub(API + 生態系統)兩部分組成。
Docker引擎
Docker引擎是一組開源軟件,位于Docker平臺的核心位置。它提供了容器運行時以及打包、管理等工具。
Docker Hub
Docker Hub是一個云端的分布式應用服務,它專注于內容、協作和工作流。
Docker Hub可以看作是原來Docker index服務的升級版。Docker Hub除了可以托管Docker鏡像之外,還提供了包括更管理、團隊協作、生命周期流程自動化等功能,以及對第三方工具和服務的集成。
在Docker, Inc.看來,典型的基于Docker Hub的軟件開發生命周期為:在本地基于Docker引擎開發 -> 打包應用程序 -> 將應用程序push到Docker Hub -> 從Docker Hub上下載此應用鏡像并運行。它將鏡像構建的任務交給Dev,將鏡像部署的任務交給Ops。