這篇文章我們將來(lái)介紹一下 Docker 的基本情況,主要包括如下幾個(gè)部分:
- Docker 是什么;
- Docker v.s. 虛擬機(jī);
- Docker 的應(yīng)用場(chǎng)景;
- Docker 架構(gòu)淺析。
1. Docker 是什么
相信有很多同學(xué)在平時(shí)的工作或者學(xué)習(xí)中應(yīng)該都或多或少地使用過(guò) Docker 了,那么 Docker 究竟是什么呢?有沒(méi)有一個(gè)準(zhǔn)確的定義來(lái)定義 Docker 呢?我們不妨先來(lái)看一下官方是如何來(lái)定義 Docker 的。
Docker is an open platform for developing, shipping, and running applications. Docker enables you to separate your applications from your infrastructure so you can deliver software quickly. With Docker, you can manage your infrastructure in the same ways you manage your applications. By taking advantage of Docker’s methodologies for shipping, testing, and deploying code quickly, you can significantly reduce the delay between writing code and running it in production.
簡(jiǎn)單翻譯下就是:
Docker 是一個(gè)開(kāi)源的平臺(tái),我們可以用 Docker 來(lái)開(kāi)發(fā)、部署和運(yùn)行我們的應(yīng)用程序。Docker 可以幫助我們將應(yīng)用程序和底層基礎(chǔ)設(shè)施進(jìn)行分離,以幫助我們更快的實(shí)現(xiàn)交付。通過(guò) Docker 技術(shù),我們可以像管理我們的應(yīng)用一樣管理我們的基礎(chǔ)設(shè)施(比如基礎(chǔ)依賴等,這里的具體技術(shù)其實(shí)就是鏡像)。通過(guò) Docker 技術(shù),我們可以精簡(jiǎn)我們的整個(gè)開(kāi)發(fā)和交互流程。
這里面的幾個(gè)核心點(diǎn)包括:
-
平臺(tái)(platform):官方將 Docker 定義為一個(gè)平臺(tái),但是其實(shí)更準(zhǔn)確的來(lái)說(shuō),Docker 其實(shí)是一個(gè)技術(shù)棧,包括 Docker 鏡像,可以類比為程序,是磁盤上面的靜態(tài)文件,可以通過(guò) Docker 來(lái)啟動(dòng)運(yùn)行;Docker 容器,也就是 Docker 鏡像的運(yùn)行時(shí)實(shí)例;Docker Daemon,用來(lái)管理機(jī)器上的鏡像、容器等。
-
應(yīng)用程序和底層基礎(chǔ)設(shè)施分離:傳統(tǒng)的軟件開(kāi)發(fā)模式是我們先開(kāi)發(fā)好我們的應(yīng)用,然后在線上環(huán)境或者測(cè)試環(huán)境上先安裝應(yīng)用的基礎(chǔ)依賴,比如像一些 C++ 的二進(jìn)制文件會(huì)依賴一些操作系統(tǒng)的動(dòng)態(tài)鏈接庫(kù)。
依賴安裝完成之后,然后將應(yīng)用程序部署上去。使用 Docker 的鏡像技術(shù)我們可以將這些依賴和應(yīng)用程序都打包到鏡像中,然后測(cè)試或者正式上線的時(shí)候只需要將整個(gè)鏡像部署上去就可以了,不需要關(guān)心目標(biāo)服務(wù)器上面的基礎(chǔ)環(huán)境,這也就是應(yīng)用程序和基礎(chǔ)設(shè)施分離。也是精簡(jiǎn)開(kāi)發(fā)流程的核心的所在。
熟悉 Docker 的同學(xué)肯定會(huì)意識(shí)到這里對(duì) Docker 的定義其實(shí)少了很多東西,確實(shí)是這樣的,比如 Docker 的隔離性和資源限制在定義里面都沒(méi)有體現(xiàn)出來(lái)。定義還是從一種更加宏觀的角度來(lái)介紹 Docker,也沒(méi)錯(cuò)。
2. Docker v.s. 虛擬機(jī)
很多人學(xué)習(xí) Docker 的過(guò)程中都會(huì)看到有人把 Docker 拿來(lái)和虛擬機(jī)做對(duì)比,也就是下面這張圖。左邊是 Docker 的架構(gòu),右邊是虛擬機(jī)的架構(gòu)圖。我們可以看到 Docker 和虛擬機(jī)的主要區(qū)別有:
- 所有的 Docker 應(yīng)用共享一個(gè)宿主機(jī)操作系統(tǒng),每個(gè)虛擬機(jī)有自己的操作系統(tǒng);
- 每個(gè) Docker 應(yīng)用通過(guò) Docker 層和宿主機(jī)的操作系統(tǒng)交互,而虛擬機(jī)應(yīng)用直接和操作系統(tǒng)交互。
但是上圖左邊的圖中的 Docker 的位置其實(shí)很不嚴(yán)謹(jǐn),實(shí)際上 Docker 并不會(huì)像 Hypervisor 那樣對(duì)應(yīng)用進(jìn)程的隔離環(huán)境負(fù)責(zé),也不會(huì)創(chuàng)建任何實(shí)體的容器,真正對(duì)環(huán)境負(fù)責(zé)的是宿主機(jī)操作系統(tǒng)本身。所以上圖中 Docker 的問(wèn)題應(yīng)該是處于靠邊的位置,因?yàn)橥ㄟ^(guò) Docker 啟動(dòng)的容器本質(zhì)上和操作系統(tǒng)中運(yùn)行的進(jìn)程并沒(méi)有本質(zhì)的區(qū)別。這個(gè)我們后面再細(xì)說(shuō)。
3. Docker 的應(yīng)用場(chǎng)景
應(yīng)用交付
Docker 技術(shù)為應(yīng)用交付領(lǐng)域帶來(lái)的最大的變化就是開(kāi)發(fā)環(huán)境的一致性。傳統(tǒng)的開(kāi)發(fā)方式需要開(kāi)發(fā)者自己在本地進(jìn)行開(kāi)發(fā),但是本地的開(kāi)發(fā)環(huán)境和遠(yuǎn)端的測(cè)試和正式環(huán)境還是存在差異,所以每次開(kāi)發(fā)完成都需要反復(fù)比對(duì)環(huán)境的差異,包括操作系統(tǒng)以及操作系統(tǒng)里面的依賴軟件包是否齊全,非常的麻煩。
但是使用 Docker 鏡像,我們可以將所有的環(huán)境依賴都打包到鏡像中,然后通過(guò)鏡像來(lái)傳輸,這樣會(huì)更加地高效。
試想下面幾種場(chǎng)景:
- 開(kāi)發(fā)者在本地編寫代碼進(jìn)行開(kāi)發(fā),然后通過(guò) Docker 鏡像和其他協(xié)作者共享;
- 使用 Docker 技術(shù)將應(yīng)用 push 到測(cè)試環(huán)境,自動(dòng)觸發(fā)自動(dòng)化 test case;
- 當(dāng)開(kāi)發(fā)者發(fā)現(xiàn)應(yīng)用程序的 bug 時(shí),可以在本地開(kāi)發(fā)環(huán)境進(jìn)行修復(fù)。修復(fù)完之后再將應(yīng)用重新部署到測(cè)試環(huán)境進(jìn)行測(cè)試驗(yàn)證;
- 當(dāng)測(cè)試完成之后,需要給客戶的環(huán)境升級(jí),只要把修復(fù)完的應(yīng)用鏡像推送到客戶可以訪問(wèn)的鏡像中心即可。
多版本混合部署
隨著產(chǎn)品的不斷更新?lián)Q代,一臺(tái)服務(wù)器上部署同一個(gè)應(yīng)用的多個(gè)版本在企業(yè)內(nèi)部非常常見(jiàn)。但一臺(tái)服務(wù)器上部署同一個(gè)軟件的多個(gè)版本,文件路徑、端口等資源往往會(huì)發(fā)生沖突,造成多個(gè)版本無(wú)法共存的問(wèn)題。
如果用 docker,這個(gè)問(wèn)題將非常簡(jiǎn)單。由于每個(gè)容器都有自己獨(dú)立的文件系統(tǒng),所以根本不存在文件路徑?jīng)_突的問(wèn)題;對(duì)于端口沖突問(wèn)題,只需要在啟動(dòng)容器時(shí)指定不同的端口映射即可解決問(wèn)題。
內(nèi)部開(kāi)發(fā)測(cè)試環(huán)境
傳統(tǒng)的開(kāi)發(fā)測(cè)試環(huán)境都是由運(yùn)維人員進(jìn)行專門的環(huán)境配置而搭建出來(lái)的,而且需要運(yùn)維人員進(jìn)行專門維護(hù)。環(huán)境一旦出現(xiàn)問(wèn)題,恢復(fù)起來(lái)也很麻煩。
借助于 Docker 技術(shù),我們將應(yīng)用程序需要的依賴都固化到 Docker 鏡像中,然后在對(duì)應(yīng)的 Docker 容器中進(jìn)行開(kāi)發(fā)測(cè)試。就算環(huán)境出現(xiàn)問(wèn)題,我們只要將當(dāng)前容器刪除重新啟動(dòng)即可恢復(fù)。
使用 Docker 鏡像來(lái)維護(hù)內(nèi)部開(kāi)發(fā)測(cè)試環(huán)境還有另一個(gè)好處就是 DevOps,傳統(tǒng)的應(yīng)用開(kāi)發(fā)部署要跨兩個(gè)團(tuán)隊(duì):開(kāi)發(fā)團(tuán)隊(duì)負(fù)責(zé)開(kāi)發(fā),運(yùn)維團(tuán)隊(duì)服務(wù)部署,一旦涉及到跨團(tuán)隊(duì)合作就要牽扯到溝通成本。而且開(kāi)發(fā)作為應(yīng)用的 owner,實(shí)際上對(duì)其依賴環(huán)境會(huì)更加的熟悉才對(duì)。
通過(guò) Docker 鏡像技術(shù),開(kāi)發(fā)人員在開(kāi)發(fā)應(yīng)用的過(guò)程中就將這些依賴固化到鏡像中。在環(huán)境部署環(huán)節(jié),即使需要運(yùn)維人員參與,也只是負(fù)責(zé)拉起 Docker。整個(gè)過(guò)程都會(huì)更加的高效。
Docker 的使用場(chǎng)景是非常多的,在這里我們主要討論幾種主要的應(yīng)用場(chǎng)景。
4. Docker 架構(gòu)淺析
很多人說(shuō) Docker 是簡(jiǎn)單的 Server-Client 的架構(gòu),其實(shí)并不一定準(zhǔn)確。Docker 的架構(gòu)比較復(fù)雜,并不是純粹的只有 Server 和 Client。下圖是 Docker 架構(gòu)的一個(gè)詳細(xì)的圖。幾個(gè)主要的組成部分有:
- Docker Client;
- Docker Daemon;
- Docker Registry。
Docker Client
我們安裝完 Docker 包之后,直接使用敲命令:docker
,界面是有提示的,這個(gè) docker 就是 docker client。
docker client 都是用來(lái)和 docker daemon 交互的。
Docker Daemon
docker daemon 是一個(gè) docker 后臺(tái)運(yùn)行的守護(hù)進(jìn)程,我們的 docker client 的命令就是和 Docker Daemon 來(lái)進(jìn)行交互的。
Docker daemon 啟動(dòng)可以使用 service 或者 systemctl 操作.
service docker start
systemctl start docker.service
然后我們使用 ps 命令就能看到 docker daemon 進(jìn)程了。
$ ps aux | grep dockerd
root 10214 1.2 0.0 1014252 23768 ? Ssl 00:58 0:00 /usr/bin/dockerd-current --add-runtime docker-runc=/usr/libexec/docker/docker-runc-current --default-runtime=docker-runc --exec-opt native.cgroupdriver=systemd --userland-proxy-path=/usr/libexec/docker/docker-proxy-current --init-path=/usr/libexec/docker/docker-init-current --seccomp-profile=/etc/docker/seccomp.json --selinux-enabled --log-driver=journald --signature-verification=false --storage-driver overlay2
然后我們查看和 client 交互的 socket 文件也存在了。
$ll /var/run/docker.sock
srw-rw---- 1 root root 0 Dec 3 00:58 /var/run/docker.sock
Docker Registry
Registry 中文一般翻譯為注冊(cè)中心,是用來(lái)存儲(chǔ) Docker 鏡像的地方。Docker Registry 有多種不同的表現(xiàn),比如 Docker Hub 就是一個(gè)公開(kāi)的注冊(cè)中心,同時(shí)各大云廠商也提供了自己的注冊(cè)中心,比如阿里云、騰訊云等,甚至你可以搭建自己的私有注冊(cè)中心。
Docker 默認(rèn)使用 Docker Hub,比如我們執(zhí)行 docker pull <image-name>
時(shí),Docker 默認(rèn)去 Docker Hub 中尋找名字為 image-name 的鏡像。如果使用自己的 Registry 需要進(jìn)行單獨(dú)的配置。
Docker Images
Image 一般中文稱之為鏡像。官方對(duì)鏡像的定義比較復(fù)雜,我一般使用類比的方式來(lái)理解鏡像。鏡像可以理解成計(jì)算機(jī)系統(tǒng)中的程序,也就是靜態(tài)的位于磁盤上面可以通過(guò)特定方式執(zhí)行的文件(程序是操作系統(tǒng)可以識(shí)別的特定的二進(jìn)制文件,Docker 鏡像是可以被 Docker Daemon 識(shí)別并執(zhí)行的特定文件)。
鏡像和普通的可執(zhí)行文件的區(qū)別在于鏡像是分層架構(gòu),每個(gè)鏡像一般都依賴于一個(gè)基礎(chǔ)鏡像。最基本的鏡像叫 scratch 鏡像。當(dāng)然我們也可以構(gòu)建自己的鏡像,然后發(fā)布到鏡像中心別人就也可以使用了。
Docker 鏡像的構(gòu)建是通過(guò)一個(gè) DSL 語(yǔ)言來(lái)編寫的,叫 Dockerfile。后文我們會(huì)細(xì)說(shuō),這里就先不贅述了。
Docker Container
Container 也就是容器。Docker 官方對(duì)容器的定義非常的優(yōu)雅。
A container is a runnable instance of an image.
翻譯過(guò)來(lái)就是:
容器是鏡像的運(yùn)行實(shí)例。
這個(gè)定義和進(jìn)程的定義非常類似:進(jìn)程是程序的運(yùn)行實(shí)例。這樣我們就可以將鏡像類比為程序,容器類比為進(jìn)程,這樣就更好理解了。
我們可以使用 Docker 的 CLI 命令或者 API 來(lái)創(chuàng)建、啟動(dòng)、停止和刪除容器等操作。同時(shí)對(duì)于運(yùn)行狀態(tài)的容器我們可以登錄進(jìn)去,類似 ssh 命令等操作。
容器默認(rèn)是和其他容器以及其宿主機(jī)隔離開(kāi)的。具體的隔離策略可以進(jìn)行自定義設(shè)置。
5. 總結(jié)
本篇文章先從宏觀角度介紹了 Docker 的定位和應(yīng)用場(chǎng)景,然后又淺析了 Docker 的架構(gòu),學(xué)完本篇文章,對(duì)于完全的新手已經(jīng)對(duì) Docker 有一個(gè)基本的認(rèn)識(shí)了。后面我們將循序漸進(jìn),不斷深入介紹 Docker 技術(shù)。