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架構,主要由下面三部分組成:

  1. Docker daemon: 運行在宿主機上,Docker守護進程,用戶通過Docker client(Docker命令)與Docker daemon交互
  2. Docker client: Docker 命令行工具,是用戶使用Docker的主要方式,Docker client與Docker daemon通信並將結果返回給用戶,Docker client也可以通過socket或者RESTful api訪問遠程的Docker daemon
  3. Docker hub/registry: 共享和管理Docker鏡像,用戶可以上傳或者下載上面的鏡像,官方地址為registry.hub.docker.com,也可以搭建自己私有的Docker registry。

了解了Docker的組成,再來了解一下Docker的兩個主要概念:

  1. Docker image:鏡像是只讀的,鏡像中包含有需要運行的文件。鏡像用來創建container,一個鏡像可以運行多個container;鏡像可以通過Dockerfile創建,也可以從Docker hub/registry上下載。
  2. 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:latestdocker 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 psCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES50a1261f7a8b docker_test:latest "/bin/bash" 7 seconds ago Up 6 seconds sleepy_ptolemy#目前只有一個container id為50a1261f7a8b的容器正在運行

啟動或停止某個container使用docker start/stop container_id:

xzs@host:~(0)$ docker stop 50a1261f7a8b50a1261f7a8bxzs@host:~(0)$ docker ps -a | grep 50a1261f7a8b50a1261f7a8b docker_test:latest "/bin/bash" 2 minutes ago Exited (0) 14 seconds ago sleepy_ptolemy#執行docker stop後,該容器的狀態變更為Exited

使用docker commit可以將container的變化作為一個新的鏡像,比如:

xzs@host:~(0)$ docker commit -m="test docker commit" 50a1261f7a8b docker_test55831c956ebf46a1f9036504abb1b29d7e12166f18f779cccce66f5dc85de38exzs@host:~(0)$ docker images | grep docker_testdocker_test latest 55831c956ebf 10 seconds ago 290.7 MB

除了從Docker hub上下載鏡像,也可以寫Dockerfile創建一個鏡像,以創建一個Django程序為例,Dockerfile如下所示:

xzs@host:/tmp/docker(0)$ cat DockerfileFROM ubuntu:12.04MAINTAINER Your NameRUN apt-get updateRUN apt-get install -y python-software-properties python-pipADD myproject /opt/codeRUN pip install -r /opt/code/requirement.txt

寫完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/testdocker push docker.example.com/test

經過長時間使用,主機上存儲了很多已無用的鏡像,想將它們刪除則用docker rm或者docker rmi,比如:

docker rm container_iddocker rmi image_id

Docker生態

隨著Docker迅速火遍全球, 以Docker為基礎的生態系統也迅速的發展起來,從以部署和運行container為基礎的CoreOS到各種各樣的管理工具和PaaS軟體,Docker以及生態產品都在迅猛發展,以下介紹幾個代表性的軟體。

首先介紹CoreOS,它的出現極大地推動了Docker技術的推廣和發展,CoreOS是專門為大規模服務部署而設計的一種新的Linux發行版,通過運行輕量級的容器方便擴展和維護大規模的服務。它具有以下特點:

  1. CoreOS使用container管理服務(容器即服務),即以容器的角度去管理服務,服務的代碼和依賴都打包到容器里,打包後的容器直接在CoreOS上運行管理。通過容器用戶不再需要關注虛擬機環境等,極大地降低了服務和系統環境的耦合性。另外部署在CoreOS的多個容器都運行在各自獨立的環境中,不會相互影響。
  2. CoreOS專門為cluster等大規模部署而設計,提供了Etcd進行服務發現,以及Fleet管理容器保證服務可用。
  3. CoreOS更加精簡,比如RAM使用比普通Linux低40%。
  4. 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。

本文轉自美團點評技術學院,未經作者許可,不允許私自轉載。


推薦閱讀:

深度調查:24%的Docker鏡像都存在嚴重漏洞
密碼1212@KubeCon北美峰會幹貨直播培訓課
把docker鏡像當作桌面系統來用
你所不了解的的Docker
基於OSS搭建私有(跨區域)Docker鏡像倉庫

TAG:Docker | Linux | 虚拟机 |