Docker 非常棒喉悴! 它使軟件開發(fā)者無需擔心配置和依賴性拧烦,在任何地方打包冻河,發(fā)送和運行他們的應用程序。而在與 Kubernetes 相結(jié)合后棒动,它使應用集群部署和管理變得更方便糙申。這使得 Docker 深受軟件開發(fā)者的喜愛,越來越多的開發(fā)者開始使用 Docker船惨。
那么 Docker 到底是什么柜裸?
它是構(gòu)建、測試粱锐、部署和發(fā)布容器化應用的平臺疙挺。稱其為平臺是因為 Docker 其實是一套用于管理與容器相關的所有事物的工具。作為 Docker 的核心怜浅,接下來我們將深入探討容器衔统。
什么是容器?
容器提供了在計算機上的隔離環(huán)境中安裝和運行應用程序的方法海雪。在容器內(nèi)運行的應用程序僅可使用于為該容器分配的資源,例如:CPU舱殿,內(nèi)存奥裸,磁盤,進程空間沪袭,用戶湾宙,網(wǎng)絡樟氢,卷等。在使用有限的容器資源的同時侠鳄,并不與其他容器沖突埠啃。您可以將容器視為簡易計算機上運行應用程序的隔離沙箱。
這個概念聽起來很熟悉伟恶,有些類似于虛擬機碴开。但它們有一個關鍵的區(qū)別:容器使用的一種非常不同的,輕量的技術來實現(xiàn)資源隔離博秫。容器利用了底層 Linux 內(nèi)核的功能潦牛,而不是虛擬機采用的 hypervisor 的方法。換句話說挡育,容器調(diào)用 Linux 命令來分配和隔離出一組資源巴碗,然后在此空間中運行您的應用程序。我們快速來看下兩個這樣的功能:
Namespaces
簡單的講就是即寒,Linux namespace 允許用戶在獨立進程之間隔離 CPU 等資源橡淆。進程的訪問權(quán)限及可見性僅限于其所在的 Namespaces 。因此母赵,用戶無需擔心在一個 Namespace 內(nèi)運行的進程與在另一個 Namespace 內(nèi)運行的進程沖突逸爵。甚至可以同一臺機器上的不同容器中運行具有相同 PID 的進程。同樣的市咽,兩個不同容器中的應用程序可以使用相同的端口痊银。
Cgroups
Cgroups 允許對可用資源設置限制和約束。例如施绎,您可以在一臺擁有 16 G 內(nèi)存的計算機上創(chuàng)建一個 Namespace 溯革,限制其內(nèi)部進程可用內(nèi)存為 1 GB。
到這谷醉,您可能已經(jīng)猜到 Docker 的工作原理了致稀。當您請求 Docker 運行容器時,Docker 會在您的計算機上設置一個資源隔離的環(huán)境俱尼。然后 Docker 會將打包的應用程序和關聯(lián)的文件復制到 Namespace 內(nèi)的文件系統(tǒng)中抖单,此時環(huán)境的配置就完成了。之后 Docker 會執(zhí)行您指定的命令運行應用程序遇八。
簡而言之矛绘,Docker 通過使用 Linux namespace 和 cgroup(以及其他一些命令)來協(xié)調(diào)配置容器,將應用程序文件復制到為容器分配的磁盤刃永,然后運行啟動命令货矮。Docker 還附帶了許多其他用于管理容器的工具,例如:列出正在運行的容器斯够,停止容器囚玫,發(fā)布容器鏡像等許多其他工具喧锦。
與虛擬機相比,容器更輕量且速度更快抓督,因為它利用了 Linux 底層操作系統(tǒng)在隔離的環(huán)境中運行燃少。虛擬機的 hypervisor 創(chuàng)建了一個非常牢固的邊界,以防止應用程序突破它铃在,而容器的邊界不那么強大阵具。另一個區(qū)別是,由于 Namespace 和 Cgroups 功能僅在 Linux 上可用涌穆,因此容器無法在其他操作系統(tǒng)上運行怔昨。此時您可能想知道 Docker 如何在 macOS 或 Windows 上運行? Docker 實際上使用了一個技巧宿稀,并在非 Linux 操作系統(tǒng)上安裝 Linux 虛擬機趁舀,然后在虛擬機內(nèi)運行容器。
讓我們利用目前為止學到的所有內(nèi)容祝沸,從頭開始創(chuàng)建和運行 Docker 容器矮烹。如果你還沒有將 Docker 安裝在你的機器上,可以參考這里[1]安裝 Docker罩锐。在這個示例中奉狈,我們將創(chuàng)建一個 Docker 容器,下載一個用 C語言寫的 Web 服務涩惑,編譯并運行它仁期,然后使用瀏覽器訪問這個 Web 服務。
我們將從所有 Docker 項目開始的地方從創(chuàng)建一個 Dockerfile 開始竭恬。此文件描述了如何創(chuàng)建用于運行容器的 Docker 鏡像跛蛋。既然我們還沒有聊到鏡像,那么讓我們看一下鏡像的官方定義[2]:
鏡像是一個可執(zhí)行包痊硕,其包含運行應用程序所需的代碼赊级、運行時、庫岔绸、環(huán)境變量和配置文件理逊,容器是鏡像的運行時實例。
簡單的講盒揉,當你要求 Docker 運行一個容器時晋被,你必須給它一個包含如下內(nèi)容的鏡像:
- 包含應用程序及其所有依賴的文件系統(tǒng)快照。
- 容器啟動時的運行命令刚盈。
在 Docker 的世界墨微,使用別人的鏡像作為基礎鏡像來創(chuàng)建自己的鏡像是十分普遍的。例如扁掸,官方 reds Docker 鏡像就是基于 Debian 文件系統(tǒng)快照(rootfs tarball)翘县,并安裝在其上配置 Redis。
在我們的示例中谴分,我們選擇 Alpine Linux 為基礎鏡像锈麸。當您在 Docker 中看到 “alpine” 時,它通常意味著一個精簡的基本鏡像牺蹄。 Alpine Linux 鏡像大小只有約為5 MB忘伞!
在您的計算機創(chuàng)建一個新目錄(例如 dockerprj),然后新建一個 Dockerfile 文件沙兰。
umermansoor:dockerprj$ touch Dockerfile
將如下內(nèi)容粘貼到 Dockerfile:
# Use Alpine Linux rootfs tarball to base our image on
FROM alpine:3.9
# Set the working directory to be '/home'
WORKDIR '/home'
# Setup our application on container's file system
RUN wget http://www.cs.cmu.edu/afs/cs/academic/class/15213-00/www/class28/tiny.c \
&& apk add build-base \
&& gcc tiny.c -o tiny \
&& echo 'Hello World' >> index.html
# Start the web server. This is container's entry point
CMD ["./tiny", "8082"]
# Expose port 8082
EXPOSE 8082
這個Dockerfile 包含創(chuàng)建鏡像的內(nèi)容說明氓奈。我們創(chuàng)建鏡像基于 Alpine Linux(rootfs tarball),并將工作目錄設置為 /home 鼎天。接下來下載舀奶,編譯并創(chuàng)建了一個用 C 編寫的簡單 Web 服務器的可執(zhí)行文件,然后指定在運行容器時要執(zhí)行的命令斋射,并將容器端口 8082 暴露給主機育勺。
現(xiàn)在,我們就可以構(gòu)建鏡像了罗岖。在 Dockerfile 的同級目錄運行 docker build 命令:
umermansoor:dockerprj$ docker build -t codeahoydocker .
如果這個命令成功了涧至,您將看到:
Successfully tagged codeahoydocker:latest
此時我們的鏡像就創(chuàng)建成功了,該鏡像主要包括:
- 文件系統(tǒng)快照(Alpine Linux 和 我們安裝的 Web 服務)
- 啟動命令(./tiny 8092)
既然成功構(gòu)建了鏡像桑包,那么我們可以使用如下命令運行容器南蓬。
umermansoor:dockerprj$ docker run -p 8082:8082 codeahoydocker:latest
讓我們了解下這里發(fā)生了什么。
通過 docker run 命令哑了,我們請求 Docker 基于 codeahoydocker:latest 鏡像創(chuàng)建和啟動一個容器赘方。-p 8082:8082 將本地的 8082 端口映射到容器的 8082 端口(容器內(nèi)的 Web 服務器正在監(jiān)聽 8082 端口上的連接)。打開你的瀏覽器并訪問 localhost:8082/index.html 垒手。你將可以看到 Hello World 信息蒜焊。
最后我想補充一點,雖然 Docker 非常棒科贬,而且對于大多數(shù)項目來說它是一個不錯的選擇泳梆,但我們并非處處都要使用它。在我的工作中榜掌,Docker 與 Kubernetes 結(jié)合使用优妙,可以非常輕松地部署和管理后端微服務,我們不必為每個服務配置新的運行環(huán)境憎账。另一方面套硼,對于性能密集型應用程序,Docker 可能不是最佳選擇胞皱。我經(jīng)手的其中一個項目必須處理來自移動游戲客戶端的 TCP 長連接(每臺機器1000個)邪意,這時 Docker 網(wǎng)絡出現(xiàn)了很多問題九妈,導致無法將它用于該項目。
寫在最后
點關注雾鬼,不迷路萌朱;Java蘇先生每天更新Java相關技術及資訊文章