歡迎光臨
每天分享高質量文章

Docker 工作原理及容器化簡易指南

 

Docker 非常棒! 它使軟體開發者無需擔心配置和依賴性,在任何地方打包,發送和運行他們的應用程式。而在與 Kubernetes 相結合後,它使應用集群部署和管理變得更方便。這使得 Docker 深受軟體開發者的喜愛,越來越多的開發者開始使用 Docker。
那麼 Docker 到底是什麼?
它是構建、測試、部署和發佈容器化應用的平臺。稱其為平臺是因為 Docker 其實是一套用於管理與容器相關的所有事物的工具。作為 Docker 的核心,接下來我們將深入探討容器。

 

什麼是容器?

 

容器提供了在計算機上的隔離環境中安裝和運行應用程式的方法。在容器內運行的應用程式僅可使用於為該容器分配的資源,例如:CPU,記憶體,磁盤,行程空間,用戶,網絡,捲等。在使用有限的容器資源的同時,並不與其他容器衝突。您可以將容器視為簡易計算機上運行應用程式的隔離沙箱。
這個概念聽起來很熟悉,有些類似於虛擬機。但它們有一個關鍵的區別:容器使用的一種非常不同的,輕量的技術來實現資源隔離。容器利用了底層 Linux 內核的功能,而不是虛擬機採用的 hypervisor 的方法。換句話說,容器呼叫 Linux 命令來分配和隔離出一組資源,然後在此空間中運行您的應用程式。我們快速來看下兩個這樣的功能:
Namespaces
簡單的講就是,Linux namespace 允許用戶在獨立行程之間隔離 CPU 等資源。行程的訪問權限及可見性僅限於其所在的 Namespaces 。因此,用戶無需擔心在一個 Namespace 內運行的行程與在另一個 Namespace 內運行的行程衝突。甚至可以同一臺機器上的不同容器中運行具有相同 PID 的行程。同樣的,兩個不同容器中的應用程式可以使用相同的端口。
Cgroups
Cgroups 允許對可用資源設置限制和約束。例如,您可以在一臺擁有 16 G 記憶體的計算機上創建一個 Namespace ,限制其內部行程可用記憶體為 1 GB。
到這,您可能已經猜到 Docker 的工作原理了。當您請求 Docker 運行容器時,Docker 會在您的計算機上設置一個資源隔離的環境。然後 Docker 會將打包的應用程式和關聯的檔案複製到 Namespace 內的檔案系統中,此時環境的配置就完成了。之後 Docker 會執行您指定的命令運行應用程式。
簡而言之,Docker 通過使用 Linux namespace 和 cgroup(以及其他一些命令)來協調配置容器,將應用程式檔案複製到為容器分配的磁盤,然後運行啟動命令。Docker 還附帶了許多其他用於管理容器的工具,例如:列出正在運行的容器,停止容器,發佈容器鏡像等許多其他工具。
與虛擬機相比,容器更輕量且速度更快,因為它利用了 Linux 底層操作系統在隔離的環境中運行。虛擬機的 hypervisor 創建了一個非常牢固的邊界,以防止應用程式突破它,而容器的邊界不那麼強大。另一個區別是,由於 Namespace 和 Cgroups 功能僅在 Linux 上可用,因此容器無法在其他操作系統上運行。此時您可能想知道 Docker 如何在 macOS 或 Windows 上運行? Docker 實際上使用了一個技巧,併在非 Linux 操作系統上安裝 Linux 虛擬機,然後在虛擬機內運行容器。
讓我們利用目前為止學到的所有內容,從頭開始創建和運行 Docker 容器。如果你還沒有將 Docker 安裝在你的機器上,可以參考這裡[1]安裝 Docker。在這個示例中,我們將創建一個 Docker 容器,下載一個用 C語言寫的 Web 服務,編譯並運行它,然後使用瀏覽器訪問這個 Web 服務。
我們將從所有 Docker 專案開始的地方從創建一個 Dockerfile 開始。此檔案描述瞭如何創建用於運行容器的 Docker 鏡像。既然我們還沒有聊到鏡像,那麼讓我們看一下鏡像的官方定義[2]:
鏡像是一個可執行包,其包含運行應用程式所需的代碼、運行時、庫、環境變數和配置檔案,容器是鏡像的運行時實體。
簡單的講,當你要求 Docker 運行一個容器時,你必須給它一個包含如下內容的鏡像:
  1. 包含應用程式及其所有依賴的檔案系統快照。

  2. 容器啟動時的運行命令。

在 Docker 的世界,使用別人的鏡像作為基礎鏡像來創建自己的鏡像是十分普遍的。例如,官方 reds Docker 鏡像就是基於 Debian 檔案系統快照(rootfs tarball),並安裝在其上配置 Redis。
在我們的示例中,我們選擇 Alpine Linux 為基礎鏡像。當您在 Docker 中看到 “alpine” 時,它通常意味著一個精簡的基本鏡像。 Alpine Linux 鏡像大小隻有約為5 MB!
在您的計算機創建一個新目錄(例如 dockerprj),然後新建一個 Dockerfile 檔案。
 
  1. umermansoor:dockerprj$ touch Dockerfile
將如下內容粘貼到 Dockerfile:
  1. # Use Alpine Linux rootfs tarball to base our image on
  2. FROM alpine:3.9
  3. # Set the working directory to be '/home'
  4. WORKDIR '/home'
  5. # Setup our application on container's file system
  6. RUN wget http://www.cs.cmu.edu/afs/cs/academic/class/15213-s00/www/class28/tiny.c \
  7. && apk add build-base \
  8. && gcc tiny.c -o tiny \
  9. && echo 'Hello World' >> index.html
  10. # Start the web server. This is container's entry point
  11. CMD ["./tiny", "8082"]
  12. # Expose port 8082
  13. EXPOSE 8082
這個Dockerfile 包含創建鏡像的內容說明。我們創建鏡像基於 Alpine Linux(rootfs tarball),並將工作目錄設置為 /home 。接下來下載,編譯並創建了一個用 C 編寫的簡單 Web 服務器的可執行檔案,然後指定在運行容器時要執行的命令,並將容器端口 8082 暴露給主機。
現在,我們就可以構建鏡像了。在 Dockerfile 的同級目錄運行 docker build 命令:
  1. umermansoor:dockerprj$ docker build -t codeahoydocker .
如果這個命令成功了,您將看到:
  1. Successfully tagged codeahoydocker:latest
此時我們的鏡像就創建成功了,該鏡像主要包括:
  1. 檔案系統快照(Alpine Linux 和 我們安裝的 Web 服務)

  2. 啟動命令(./tiny 8092)

既然成功構建了鏡像,那麼我們可以使用如下命令運行容器。
  1. umermansoor:dockerprj$ docker run -p 8082:8082 codeahoydocker:latest
讓我們瞭解下這裡發生了什麼。
通過 docker run 命令,我們請求 Docker 基於 codeahoydocker:latest 鏡像創建和啟動一個容器。-p 8082:8082 將本地的 8082 端口映射到容器的 8082 端口(容器內的 Web 服務器正在監聽 8082 端口上的連接)。打開你的瀏覽器並訪問 localhost:8082/index.html 。你將可以看到 Hello World 信息。
最後我想補充一點,雖然 Docker 非常棒,而且對於大多數專案來說它是一個不錯的選擇,但我們並非處處都要使用它。在我的工作中,Docker 與 Kubernetes 結合使用,可以非常輕鬆地部署和管理後端微服務,我們不必為每個服務配置新的運行環境。另一方面,對於性能密集型應用程式,Docker 可能不是最佳選擇。我經手的其中一個專案必須處理來自移動游戲客戶端的 TCP 長連接(每台機器1000個),這時 Docker 網絡出現了很多問題,導致無法將它用於該專案。
希望上面這些內容有用。
相關鏈接:
  1. https://docs.docker.com/install/

  2. https://docs.docker.com/get-started/#images-and-containers

原文鏈接:https://codeahoy.com/2019/04/12/what-are-containers-a-simple-guide-to-containerization-and-how-docker-works/
赞(0)

分享創造快樂