Docker
是時下熱門的容器技術(shù),相信作為一名開發(fā)人員,你一定聽說過或者使用過,很多人會把Docker
理解為一個輕量級虛擬機,但其實Docker
與虛擬機(VM
)是兩種不同的計算機虛擬化技術(shù),也有很多人會覺得,有了虛擬機,那為什么還要使用Docker
呢?
帶著心里的一點點疑問,讓我們一起來學習Docker
吧。
我們仔細想想,在沒有計算虛擬化技術(shù)的“遠古”年代,如果我們要部署一個應(yīng)用程序(Application
),一般的步驟是怎么樣的?
第一步肯定是先要準備一臺物理服務(wù)器,然后在物理服務(wù)器上安裝一個操作系統(tǒng)(Operating System
),有了操作系統(tǒng)之后,便在操作系統(tǒng)上安裝運行我們的應(yīng)用程序,這個過程可以用下面的圖來表示:
物理服務(wù)器部署應(yīng)用示意圖
那么,這種方式有什么問題呢?其實,在物理機上部署應(yīng)用有以下幾個缺點:
部署非常慢:因為我們得先準備硬件服務(wù)器,接著還要安裝操作系統(tǒng),然后再部署應(yīng)用程序,而且應(yīng)用程序還有很多的依賴軟件,所以這個過程是比較慢的。
成本非常高:主要是物理器成本太高,即使是部署一個簡單的應(yīng)用,也需要一臺服務(wù)器。
資源浪費:如果應(yīng)用太簡單,也容易浪費硬件資源,比如CPU
和內(nèi)存
遷移和擴展太慢:如果需要遷移應(yīng)用,或者擴展應(yīng)用,都要再準備其他的物理服務(wù)器,過程很麻煩,也很慢。
那么有什么辦法可以解決這些問題呢?答案便是虛擬化技術(shù)。
談到計算機的虛擬化技術(shù),我們直接想到的便是虛擬機,虛擬機允許我們在一臺物理計算機模擬出多臺機器,簡單地理解,虛擬化技術(shù)就是在一臺物理計算機上,通過中間虛擬軟件層Hypervisor
隔離CPU
、內(nèi)存等硬件資源,虛擬出多臺虛擬服務(wù)器,這樣做的話,一臺物理服務(wù)器便可以安裝多個應(yīng)用程序,達到資源利用的最大化,而且多個應(yīng)用之間相互隔離,如下圖所示:
虛擬機上部署應(yīng)用示意圖
可以把資源分配到不同的虛擬機,達到硬件資源的最大化利用
與直接在物理機上部署應(yīng)用,虛擬更容易擴展應(yīng)用。
云服務(wù):通過虛擬機虛擬出不同的物理資源,可以快速搭建云服務(wù)。
虛擬機的不足之外來自于對物理服務(wù)器資源的消耗,當我們在物理服務(wù)器創(chuàng)建一臺虛擬機時,便需要虛擬出一套硬件并在上面運行完整的操作系統(tǒng),每臺虛擬機都占用許多的服務(wù)器資源。
相對于虛擬機的笨重,Docker
則更顯得輕量化,因此不會占用太多的系統(tǒng)資源。
Docker
是使用時下很火的Golang
語言進行開發(fā)的,其技術(shù)核心是Linux
內(nèi)核的Cgroup
,Namespace
和AUFS
類的Union FS
等技術(shù),這些技術(shù)都是Linux
內(nèi)核中早已存在很多年的技術(shù),所以嚴格來說并不是一個完全創(chuàng)新的技術(shù),Docker
通過這些底層的Linux
技術(shù),對Linux
進程進行封裝隔離,而被隔離的進程也被稱為容器,完全獨立于宿主機的進程。
所以Docker
是容器技術(shù)的一種實現(xiàn),也是操作系統(tǒng)層面的一種虛擬化,與虛擬機的通過一套硬件再安裝操作系統(tǒng)完全不同。
Docker容器與系統(tǒng)關(guān)系示意圖
Docker
是在操作系統(tǒng)進程層面的隔離,而虛擬機是在物理資源層面的隔離,兩者完全不同,另外,我們也可以通過下面的一個比較,了解兩者的根本性差異。
容器與虛擬機的比較【摘自《Docker-從入門到實踐》】
從上面的容器與虛擬機的對比中,我們明白了容器技術(shù)的優(yōu)勢。
開發(fā)環(huán)境與生產(chǎn)環(huán)境折射的是開發(fā)人員與運維人員之間的矛盾,也許我們常常會聽到開發(fā)人員對運維人員說的這樣一句話:“在我的電腦運行沒問題,怎么到了你那里就出問題了,肯定是你的問題”,而運維人員是認為是開發(fā)人員的問題。
開發(fā)人員需要在本機安裝各種各樣的測試環(huán)境,因此開發(fā)的項目需要軟件越多,依賴越多,安裝的環(huán)境也就越復(fù)雜。
同樣的,運維人員需要為開發(fā)人員開發(fā)的項目提供生產(chǎn)環(huán)境,而運維人員除了應(yīng)對軟件之間的依賴,還需要考慮安裝軟件與硬件之間的兼容性問題。
就是這樣,所以我們經(jīng)??吹介_發(fā)與運維相互甩鍋,怎么解決這個問題呢?
容器就是一個不錯的解決方案,容器能成為開發(fā)與運維之間溝通的語言,因為容器就像一個集裝箱一樣,提供了軟件運行的最小化環(huán)境,將應(yīng)用與其需要的環(huán)境一起打包成為鏡像,便可以在開發(fā)與運維之間溝通與傳輸。
Docker
分為社區(qū)版(CE
)和企業(yè)版(EE
)兩個版本,社區(qū)版本可以免費使用,而企業(yè)版則需要付費使用,對于我們個人開發(fā)者或小企業(yè)來說,一般是使用社區(qū)版的。
Docker CE
有三個更新頻道,分別為stable
、test
、nightly
,stable
是穩(wěn)定版本,test
是測試后的預(yù)發(fā)布版本,而nightly
則是開發(fā)中準備在下一個版本正式發(fā)布的版本,我們可以根據(jù)自己的需求下載安裝。
好了,通過前面的介紹,我們應(yīng)該對Docker
有了初步的了解,下面開始進入Docker
的學習之旅了。
而學習Docker
的第一步,從安裝Docker
運行環(huán)境開始,我們以Docker
的社區(qū)版本(CE
)安裝為例,
Docker
社區(qū)版本提供了Mac OS
,Microsoft Windows
和Linux
(Centos
,Ubuntu
,Fedora
,Debian
)等操作系統(tǒng)的安裝包,同時也支持在云服務(wù)器上的安裝,比如AWS Cloud
。
Docker
為Windows
提供了一個桌面應(yīng)用程序管理的安裝包(Docker Desktop for Windows
),不過對系統(tǒng)有以下幾點要求:
必須是64
位Windows10
專業(yè)版,企業(yè)版,教育版,構(gòu)建在15063
或更高版本,
在BIOS
中啟用虛擬化。通常,默認情況下啟用虛擬化。
至少有4GB
內(nèi)存。
CPU
支持SLAT
。
如果操作系統(tǒng)滿足上面的要求,則可以直接下載安裝包直接安裝,在安裝成功后,Docker
并不會自動啟動,需要我們自己啟動,我們可以開始菜單中找到Docker
,如下圖,單擊啟動便可啟動。
如果系統(tǒng)達不到上面的要求,比如說你用的是Windows 7
操作系統(tǒng),這時候要想使用Docker
,便需要借助Docker Toolbox
,Docker Toolbox
是Docker
提供的在比較舊的Mac OS
,Windows
操作系統(tǒng)上安裝Docker
環(huán)境的工具集。
Docker Toolbox
包括docker-cli(就是我們在終端使用的docker命令行工具)
,docker-compose(多容器管理工具)
,docker-mecahine
,VirtualBox(虛擬機)
,Kitematic(docker的GUI管理工具)
。
本質(zhì)上使用Docker Toolbox
安裝Docker
環(huán)境,實際上是在VirtualBox
中創(chuàng)建一個Linux
虛擬機,并在虛擬機上安裝Docker
另外,在安裝過程中會開啟Windows
的Hyper-V
模塊(Windows
操作系統(tǒng)實現(xiàn)虛擬化的一種技術(shù)),這里面有個要注意的點是如果開啟了Hyper-V
,則VirtualBox
不再生效了。
如同Windows
操作系統(tǒng)一樣,Docker
為Mac OS
也一樣提供一個桌面應(yīng)用程序(Docker Desktop for Mac
),比較簡單,從docker
官網(wǎng)上下載Dokcer.dmg
安裝,打開Docker.dmg
,如下圖所示:
直接拖動Docker
圖標便完成了安裝。
對于比較老的Mac OS
操作系統(tǒng),也可以像Windows
一樣,使用Docker Toolbox
,這點可以參考上面的介紹。
在Mac OS
上安裝完成之后,在Application
中找到Docker
圖標,雙擊打開便可以啟動Docker
了,如下:
在Linux
操作系統(tǒng)上的安裝,主要以Centos7
為例,其他Linux
系統(tǒng)的發(fā)行版本,如Ubuntu
,Debian
,Fedora
等,可以自行查詢Docker
的官方文檔。
可能有些Linux
預(yù)先安裝Docker
,但一般版本比較舊,所以可以先執(zhí)行以下代碼來刪除舊版本的Docker
。
通過上面幾種方式安裝了Docker
之后,我們可以通過下面的方法來檢測安裝是否成功。
運行上面的命令之后,如果有如下圖所示的輸出結(jié)果,則說明安裝已經(jīng)成功了。
鏡像(Image
)、容器(Container
)與倉庫(Repository
),這三個是docker
中最基本也是最核心的概念,對這三個概念的掌握與理解,是學習docker
的關(guān)鍵。
什么是Docker
的鏡像?
Docker
本質(zhì)上是一個運行在Linux
操作系統(tǒng)上的應(yīng)用,而Linux
操作系統(tǒng)分為內(nèi)核和用戶空間,無論是Centos
還是Ubuntu
,都是在啟動內(nèi)核之后,通過掛載Root
文件系統(tǒng)來提供用戶空間的,而Docker鏡像就是一個Root文件系統(tǒng)。
Docker
鏡像是一個特殊的文件系統(tǒng),提供容器運行時所需的程序、庫、資源、配置等文件,另外還包含了一些為運行時準備的一些配置參數(shù)(如匿名卷、環(huán)境變量、用戶等)。
鏡像是一個靜態(tài)的概念,不包含任何動態(tài)數(shù)據(jù),其內(nèi)容在構(gòu)建之后也不會被改變。
下面的命令是一些對鏡像的基本操作,如下:
由于我們前面已經(jīng)拉取了hello-world
鏡像,所以會輸出下面的內(nèi)容:
下面的命令也一樣可以查看本地的鏡像列表,而且寫法更簡潔。
前面我們已經(jīng)演示過使用docker pull
命令拉取了hello-world
鏡像了,當然使用docker image pull
命令也是一樣的。
一般默認是從Docker Hub
上拉取鏡像的,Docker Hub
是Docker
官方提供的鏡像倉庫服務(wù)(Docker Registry
),有大量官方或第三方鏡像供我們使用,比如我們可以在命令行中輸入下面的命令直接拉取一個Centos
鏡像:
docker pull
命令的完整寫法如下:
拉取一個鏡像,需要指定Docker Registry
的地址和端口號,默認是Docker Hub
,還需要指定倉庫名和標簽,倉庫名和標簽唯一確定一個鏡像,而標簽是可能省略,如果省略,則默認使用latest作為標簽名,另外,倉庫名則由作者名和軟件名組成。
那么,我們上面使用centos
,那是因為省略作者名,則作者名library
,表示Docker
官方的鏡像,所以上面的命令等同于:
因此,如果拉取非官方的第三方鏡像,則需要指定完整倉庫名,如下:
使用docker run
命令,可以通過鏡像創(chuàng)建一個容器,如下:
當本地有些鏡像我們不需要時,那我們也可以刪除該鏡像,以節(jié)省存儲空間,不過要注意,如果有使用該鏡像創(chuàng)建的容器未刪除,則不允許刪除鏡像。
刪除鏡像的快捷命令:
好了,關(guān)于Docker
鏡像的相關(guān)知識,我們就簡單地介紹到這里,有機會的話,我們單獨寫一篇文章來談?wù)?,特別構(gòu)建Docker
鏡像部分的相關(guān)知識,有必要深入再學習一下。
Docker
的鏡像是用于生成容器的模板,鏡像分層的,鏡像與容器的關(guān)系,就是面向?qū)ο缶幊讨蓄惻c對象的關(guān)系,我們定好每一個類,然后使用類創(chuàng)建對象,對應(yīng)到Docker
的使用上,則是構(gòu)建好每一個鏡像,然后使用鏡像創(chuàng)建我們需要的容器。
啟動容器有兩種方式,一種是我們前面已經(jīng)介紹過的,使用docker run
命令通過鏡像創(chuàng)建一個全新的容器,如下:
另外一種啟動容器的方式就是啟動一個已經(jīng)停止運行的容器:
要停止正在運行的容器可以使用docker container stop
或docker stop
命令,如下:
如果要查看本地所有的容器,可以使用docker container ls
命令:
查看所有容器也有簡潔的寫法,如下:
我們也可以使用docker container rm
命令,或簡潔的寫法docker rm
命令來刪除容器,不過不允許刪除正在運行的容器,因此如果要刪除的話,就必須先停止容器,
當我們需要批量刪除所有容器,可以用下面的命令:
在前面的例子中,我們使用兩種方式構(gòu)建鏡像,構(gòu)建完成之后,可以在本地運行鏡像,生成容器,但如果在更多的服務(wù)器運行鏡像呢?很明顯,這時候我們需要一個可以讓我們集中存儲和分發(fā)鏡像的服務(wù),就像Github可以讓我們自己存儲和分發(fā)代碼一樣。
Docker Hub
就是Docker提供用于存儲和分布鏡像的官方Docker Registry
,也是默認的Registry
,其網(wǎng)址為https://hub.docker.com
,前面我們使用docker pull
命令便從Docker Hub
上拉取鏡像。
Docker Hub
有很多官方或其他開發(fā)提供的高質(zhì)量鏡像供我們使用,當然,如果要將我們自己構(gòu)建的鏡像上傳到Docker Hub
上,我們需要在Docker Hub
上注冊一個賬號,然后把自己在本地構(gòu)建的鏡像發(fā)送到Docker Hub
的倉庫當中,Docker Registry
包含很多個倉庫,每個倉庫對應(yīng)多個標簽,不同標簽對應(yīng)一個軟件的不同版本。
在安裝好并啟動了Docker
之后,我們可以使用在命令行中使用docker
命令操作docker,比如我們使用如下命令打印docker
的版本信息。
其結(jié)果如下:
從上面的圖中,我們看到打出了兩個部分的信息:Client
和Server
。
這是因為Docker
跟大部分服務(wù)端軟件一樣(如MySQL
),都是使用C/S
的架構(gòu)模型,也就是通過客戶端調(diào)用服務(wù)器,只是我們現(xiàn)在剛好服務(wù)端和客戶端都在同一臺機器上而已。
因此,我們可以使用下面的圖來表示Docker
的架構(gòu),DOCKER_HOST
是Docker server
,而Clinet便是我們在命令中使用docker
命令。
docker server
為客戶端提供了容器、鏡像、數(shù)據(jù)卷、網(wǎng)絡(luò)管理等功能,其實,這些功能都是由Docker Engine
來實現(xiàn)的。
dockerd
:服務(wù)器守護進程。
Client docker Cli
:命令行接口
REST API
:除了cli命令行接口,也可以通過REST API
調(diào)用docker
下面是Docker Engine
的示例圖:
作為一名開發(fā)人員,在學習或開發(fā)過程中,總需要安裝各種各樣的開發(fā)環(huán)境,另外,一個技術(shù)團隊在開發(fā)項目的過程,也常常需要統(tǒng)一開發(fā)環(huán)境,這樣可能避免環(huán)境不一致引發(fā)的一些問題。
雖然使用虛擬機可以解決上面的問題,但虛擬機太重,對宿主機資源消耗太大,而作為輕量級容器技術(shù),Docker
可以簡單輕松地解決上述問題,讓開發(fā)環(huán)境的安裝以及應(yīng)用的部署變得非常簡單,而且使用Docker
,比在虛擬機安裝操作系統(tǒng),要簡單得多。