Docker系列之一:入門介紹
Docker簡介
Docker是DotCloud開源的、可以將任何應用包裝在Linux container中運行的工具。2013年3月發布首個版本,當前最新版本為1.3。Docker基于Go語言開發,代碼托管在Github上,目前超 過10000次commit。基于Docker的沙箱環境可以實現輕型隔離,多個容器間不會相互影響;Docker可以自動化打包和部署任何應用,方便地 創建一個輕量級私有PaaS云,也可以用于搭建開發測試環境以及部署可擴展的web應用等。
Docker vs VM
從下圖可以看出,VM是一個運行在宿主機之上的完整的操作系統,VM運行自身操作系統會占用較多的CPU、內存、硬盤資源。Docker不同于 VM,只包含應用程序以及依賴庫,基于libcontainer運行在宿主機上,并處于一個隔離的環境中,這使得Docker更加輕量高效,啟動容器只需 幾秒鐘之內完成。由于Docker輕量、資源占用少,使得Docker可以輕易的應用到構建標準化的應用中。但Docker目前還不夠完善,比如隔離效果 不如VM,共享宿主機操作系統的一些基礎庫等;網絡配置功能相對簡單,主要以橋接方式為主;查看日志也不夠方便靈活。
另外,IBM發表了一篇關于虛擬機和Linux container性能對比的論文, 論文中實際測試了虛擬機和Linux container在CPU、內存、存儲IO以及網絡的負載情況,結果顯示Docker容器本身幾乎沒有什么開銷,但是使用AUFS會一定的性能損耗,不 如使用Docker Volume,Docker的NAT在較高網絡數據傳輸中會引入較大的工作負載,帶來額外的開銷。不過container的性能與native相差不多, 各方面的性能都一般等于或者優于虛擬機。Container和虛擬機在IO密集的應用中都需要調整優化以更好的支持IO操作,兩者在IO密集型的應用中都 應該謹慎使用。
Docker Component
Docker是CS架構,主要由下面三部分組成:
- Docker daemon: 運行在宿主機上,Docker守護進程,用戶通過Docker client(Docker命令)與Docker daemon交互
- Docker client: Docker 命令行工具,是用戶使用Docker的主要方式,Docker client與Docker daemon通信并將結果返回給用戶,Docker client也可以通過socket或者RESTful api訪問遠程的Docker daemon
- Docker hub/registry: 共享和管理Docker鏡像,用戶可以上傳或者下載上面的鏡像,官方地址為https://registry.hub.docker.com/,也可以搭建自己私有的Docker registry。
了解了Docker的組成,再來了解一下Docker的兩個主要概念:
- Docker image:鏡像是只讀的,鏡像中包含有需要運行的文件。鏡像用來創建container,一個鏡像可以運行多個container;鏡像可以通過Dockerfile創建,也可以從Docker hub/registry上下載。
- Docker container:容器是Docker的運行組件,啟動一個鏡像就是一個容器,容器是一個隔離環境,多個容器之間不會相互影響,保證容器中的程序運行在一個相對安全的環境中。
Docker網絡
Docker的網絡功能相對簡單,沒有過多復雜的配置,Docker默認使用birdge橋接方式與容器通信,啟動Docker后,宿主機上會產生docker0這樣一個虛擬網絡接口, docker0不是一個普通的網絡接口, 它是一個虛擬的以太網橋,可以為綁定到docker0上面的網絡接口自動轉發數據包,這樣可以使容器與宿主機之間相互通信。每次Docker創建一個容器,會產生一對虛擬接口,在宿主機上執行ifconfig,會發現多了一個類似veth****這樣的網絡接口,它會綁定到docker0上,由于所有容器都綁定到docker0上,容器之間也就可以通信。
在宿主機上執行ifconfig,會看到docker0這個網絡接口, 啟動一個container,再次執行ifconfig, 會有一個類似veth****的interface,每個container的缺省路由是宿主機上docker0的ip,在container中執行netstat -r可以看到如下圖所示內容:
容器中的默認網關跟docker0的地址是一樣的:
當容器退出之后,veth*虛擬接口也會被銷毀。
除bridge方式,Docker還支持host、container、none三種網絡通信方式,使用其它通信方式,只要在Docker啟動時,指定--net參數即可,比如:
docker run -i -t --net=host ubuntu /bin/bash
host方式可以讓容器無需創建自己的網絡協議棧,而直接訪問宿主機的網絡接口,在容器中執行ip addr會發現與宿主機的網絡配置是一樣的,host方式讓容器直接使用宿主機的網絡接口,傳輸數據的效率會更加高效,避免bridge方式帶來的額外開 銷,但是這種方式也可以讓容器訪問宿主機的D-bus等網絡服務,可能會帶來意想不到的安全問題,應謹慎使用host方式;container方式可以讓 容器共享一個已經存在容易的網絡配置; none方式不會對容器的網絡做任務配置,需要用戶自己去定制。
Docker 使用
首先要在宿主機上安裝Docker,Docker安裝參考官方安裝文檔。
Docker命令也比較類似Git,支持push以及pull操作上傳以及下載Docker鏡像。
查看當前Docker的版本
docker version
查看當前系統Docker信息
docker info
查看宿主機上的鏡像,Docker鏡像保存在/var/lib/docker目錄下:
docker images
從Docker hub上下載某個鏡像:
docker pull ubuntu:latest docker pull ubuntu:latest
執行docker pull ubuntu會將Ubuntu這個倉庫下面的所有鏡像下載到本地repository。
啟動一個容器使用docker run:
docker run -i -t ubuntu /bin/bash 啟動一個容器 docker run -i -t --rm ubuntu /bin/bash --rm表示容器退出后立即刪除該容器 docker run -t -i --name test_container ubuntu /bin/bash --name指定容器的名稱,否則會隨機分配一個名稱 docker run -t -i --net=host ubuntu /bin/bash --net=host容器以Host方式進行網絡通信 docker run -t -i -v /host:/container ubuntu /bin/bash -v綁定掛在一個Volume,在宿主機和Docker容器中共享文件或目錄
查看當前有哪些容器正在運行,使用docker ps:
xzs@host:~(0)$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 50a1261f7a8b docker_test:latest "/bin/bash" 7 seconds ago Up 6 seconds sleepy_ptolemy目前只有一個container id為50a1261f7a8b的容器正在運行</pre>
啟動或停止某個container使用docker start/stop container_id:</p>
xzs@host:~(0)$ docker stop 50a1261f7a8b 50a1261f7a8bxzs@host:~(0)$ docker ps -a | grep 50a1261f7a8b 50a1261f7a8b docker_test:latest "/bin/bash" 2 minutes ago Exited (0) 14 seconds ago sleepy_ptolemy
執行docker stop后,該容器的狀態變更為Exited</pre>
使用docker commit可以將container的變化作為一個新的鏡像,比如:</p>
xzs@host:~(0)$ docker commit -m="test docker commit" 50a1261f7a8b docker_test 55831c956ebf46a1f9036504abb1b29d7e12166f18f779cccce66f5dc85de38exzs@host:~(0)$ docker images | grep docker_test docker_test latest 55831c956ebf 10 seconds ago 290.7 MB</pre>
除了從Docker hub上下載鏡像,也可以寫Dockerfile創建一個鏡像,以創建一個Django程序為例,Dockerfile如下所示:
xzs@host:/tmp/docker(0)$ cat Dockerfile FROM ubuntu:12.04 MAINTAINER Your NameRUN apt-get update RUN apt-get install -y python-software-properties python-pip
ADD myproject /opt/code
RUN pip install -r /opt/code/requirement.txt</pre>
寫完Dockerfile,在Dockerfile所在目錄執行docker build創建鏡像:
docker build -t docker_test . docker run -i -t docker_test /bin/bash -c "cd /opt/code;python manage.py runserver 0.0.0.0:8080"將制作的鏡像上傳到private registry:
docker tag test docker.example.com/test docker push docker.example.com/test經過長時間使用,主機上存儲了很多已無用的鏡像,想將它們刪除則用docker rm或者docker rmi,比如:
docker rm container_id docker rmi image_idDocker生態
隨著Docker迅速火遍全球, 以Docker為基礎的生態系統也迅速的發展起來,從以部署和運行container為基礎的CoreOS到各種各樣的管理工具和PaaS軟件,Docker以及生態產品都在迅猛發展,以下介紹幾個代表性的軟件。
首先介紹CoreOS,它的出現極大地推動了Docker技術的推廣和發展,CoreOS是專門為大規模服務部署而設計的一種新的Linux發行版,通過運行輕量級的容器方便擴展和維護大規模的服務。它具有以下特點:
- CoreOS使用container管理服務(容器即服務),即以容器的角度去管理服務,服務的代碼和依賴都打包到容器里,打包后的容器直接在 CoreOS上運行管理。通過容器用戶不再需要關注虛擬機環境等,極大地降低了服務和系統環境的耦合性。另外部署在CoreOS的多個容器都運行在各自獨 立的環境中,不會相互影響。
- CoreOS專門為cluster等大規模部署而設計,提供了Etcd進行服務發現,以及Fleet管理容器保證服務可用。
- CoreOS更加精簡,比如RAM使用比普通Linux低40%。
- CoreOS采用雙分區模式(Dual-Partition),主分區為主動模式,負責系統運行,被動模式分區負責系統更新,更新時將整個CoreOS系統下載下來。
CoreOS是為集群服務而設計的,提供了Etcd、Fleet等管理工具管理容器和服務。Etcd是一種類似Zookeeper的分布式 key/value存儲服務,用于服務發現和配置管理。Fleet是容器管理工具,保證服務的可用性,當某個機器的服務不可用時,Fleet會將服務遷移 到其它機器上運行。
Docker生態中還有一個非常重要的容器管理工具--Kubernetes,它是Google開源的用于在集群環境中管理、維護、自動擴展容器, 通過Kubernetes可以很方便地在多個機器上管理和部署容器服務。現在已經得到IBM、Microsoft、RedHat等多個大公司的支持。
在Kubernetes中pod是一個基本單元,一個pod可以是提供相同功能的多個container,這些容器會被部署在同一個minion 上。Replication controller定義了多個pod或者容器需要運行,如果當前集群中運行的pod或容器達不到配置的數量,replication controller會調度容器在多個minion上運行,保證集群中的pod數量。service則定義真實對外提供的服務,一個service會對應 后端運行的多個container。Kubernetes的架構由一個master和多個minion組成,master通過api提供服務,接受 kubectl的請求來調度管理整個集群。minion是運行Kubelet的機器,它接受master的指令創建pod或者容器。
最后介紹一下基于Docker實現的PaaS軟件,Docker PaaS軟件中以Deis和Flynn最為知名。Deis是基于Docker和CoreOS實現的輕量級的PaaS,受到Heroku的啟發,遵循“十二要素” 構建應用方法。Deis是以應用程序為中心設計的,分為build、release、run三個階段,用戶執行"git push"后,Deis使用Docker 容器編譯并將編譯結果保存在Docker鏡像;發布階段,一次build和配置文件產生一個數字標識的發布鏡像,將發布鏡像保存到Docker registry中以供后續發布到線上運行;運行階段應用鏡像會被調度到主機上運行,并更新相應的路由。Flynn與Deis類似,也是以應用為中 心,Flynn組件分為兩層,layer0是底層資源的抽象,主要負責資源調度以及服務發現等,為上層應用容器的運行提供底層資源調度支持;layer1 處理具體應用,通過Docker容器編譯、部署和維護上層應用程序。
總結
Docker從2013年發布第一個版本以來,已經火遍全球,技術迭代也比較頻繁,其周邊產品和技術也越來越豐富,由于Docker更新頻繁,會出現新版本有時不兼容舊版本的情況,Docker周邊產品基本都處于開發階段還不具備生產環境下使用。
Docker的輕量級容器不僅實現了資源隔離,而且幾乎可以運行在任何地方,使得部署和擴展變得非常容易,隨著Docker的日趨完善,希望Docker被越來越多的公司應用到生產環境中。下一篇將詳細介紹美團如何使用Docker。
參考文獻