文章目錄
- 一、Docker:容器化應用的基石
- 1.1 環境
- 1.2 Docker 是什么
- 1.3 Docker鏡像
- 1.3.1 基礎鏡像(Base Image)
- 1.3.2 Dockerfile
- 1.3.3 容器鏡像(Container Image)
- 1.4 Registry
- 1.5 容器
- 1.6 Docker VS 虛擬機
- 二、Docker 的架構原理
- 2.1 C/S軟件架構
- 2.2 docker 命令
- 2.2.1 docker build
- 2.2.2 docker pull/push
- 2.2.3 docker run
- 三、Docker部署工具
- 3.1 Docker Compose :多容器部署
- 3.2 Docker Swarm :集群部署
- 3.3 Kubernetes :開源的容器編排平臺
- 四、總結
- 全文參考《Docker 是什么?》
- golang全棧指南:
一、Docker:容器化應用的基石
1.1 環境
??我們經常能聽到程序員說"這個程序在我環境里明明是好的啊,怎么到你這就不行了呢"?注意這里的關鍵詞,程序和環境。程序是跑在操作系統上的,而操作系統上又裝了各種不同版本的依賴庫和配置,這些被程序所依賴的信息,我們統稱為"環境"。
??作為一個程序員,如果你想安裝一個 vim
文本編輯器,在不同環境里你得執行不同的命令。在 ubuntu,你需要執行 apt-get install vim
,在 centos 里,你需要執行 yum install vim
。裝個小軟件尚且如此,要是你想將自己寫的代碼部署到各個不同操作系統的服務器上,那依賴的軟件和配置就更多了,需要針對每個環境單獨寫一套部署腳本,太麻煩了。
1.2 Docker 是什么
??Docker 是一種開源的容器化平臺,它允許開發者將應用程序及其依賴的環境打包到一個獨立的容器中,作為代碼和操作系統之間的中間層。
Docker 有三大核心組件,分別是鏡像(Image)、容器(Container)和倉庫(Repository):
- Docker 鏡像:是一個只讀的模板,用于創建 Docker 容器。它包含了容器運行所需的代碼、運行時環境、庫、環境變量和配置文件等。
- 容器:鏡像的可寫運行實例,它包含了運行應用程序所需要的一切,包括代碼、運行時、系統工具、系統庫等。容器通過鏡像創建,可以被啟動、停止、刪除等。
- Docker 倉庫:存儲和分發鏡像的場所,分為公共倉庫(Docker Hub)和私有倉庫。
1.3 Docker鏡像
1.3.1 基礎鏡像(Base Image)
??容器是一個輕量級、可移植的執行環境,它與宿主機共享內核,但擁有獨立的用戶空間。通過 Docker,開發者可以在不同的操作系統和環境中一致地部署和運行應用程序,從而解決了“在我的機器上可以運行”的問題。
??既然上面提到環境不同,會導致程序運行結果不同,那么我們首先要做的最重要的事情,就是統一環境。而環境中,最最重要的就是操作系統。比如 centos 還是 ubuntu,我們得選一個,讓所有程序都跑在同一個操作系統上。操作系統分為用戶空間和內核空間,應用程序運行在用戶空間。因此,我們可以閹割操作系統,只需要利用操作系統的用戶空間部分,就能構建出應用所需的環境。
??其次就是統一程序語言依賴,比如要跑 python 應用,你得裝個 python 解釋器,要跑個 java 應用,得裝個 JVM,要跑 go 應用,那就。。什么都不需要裝。選中一個基礎操作系統和語言后,我們將它們對應的文件系統,依賴庫,配置等放一起打包成一個類似壓縮包的文件,這就是所謂的基礎鏡像(Base Image)。
1.3.2 Dockerfile
??Dockerfile 是一個文本文件,它包含了一系列指令,定義了如何構建容器鏡像。
??有了基礎鏡像之后還不夠,我們經常還需要安裝一些依賴,比如yum install gcc
,甚至還要創建一些文件夾。最后才是運行我們的目標應用程序。
??Linux 中,所有工作都可以通過命令行完成,所以我們可以將要做的事情以命令行的形式一行行列出來。就像一份 todo list。意思是要求在基礎鏡像的基礎上按著 todo list 挨個執行命令。這份 todo list 長下面這樣。
# 指定基礎鏡像
FROM python:3.9# 設置工作目錄
WORKDIR /app# 復制依賴文件到容器中
COPY requirements.txt .RUN yum install gcc
# 安裝依賴
RUN pip install --no-cache-dir -r requirements.txt# 將當前目錄下的所有文件復制到容器的 /app 目錄下
COPY . /app# 設置容器啟動時執行的命令
CMD ["python", "app.py"]
具體含義是,基于一個裝了 python3.9 解釋器的操作系統(基礎鏡像),再執行 pip install 等命令安裝其他依賴,從而構建出一個適合程序運行的環境,最后用
python app.py
運行我們的目標應用程序。
??像這樣一份列清楚了,從操作系統到應用服務啟動,需要做哪些事情的清單文件(todo list),就是所謂的 Dockerfile。通過 Dockerfile,開發者可以清晰地描述應用程序的構建過程,確保每次構建的鏡像都是一致的。
1.3.3 容器鏡像(Container Image)
??Dockerfile 只是描述了要做哪些事情,并沒有真正開始做。當我們用命令行執行 docker build 的時候,Docker 軟件就會按著 Dockerfile 的說明,一行行構建環境+應用程序。最終將這個環境+程序,打包成一個類似"壓縮包"的東西,我們叫它容器鏡像(container image)。
??只要將容器鏡像傳到任意一臺服務器上,對這個"壓縮包"執行"解壓縮",我們就能同時運行環境和程序。太完美了!但是現在還有個問題,怎么將容器鏡像傳到那么多服務器上呢?
1.4 Registry
??服務器那么多,挨個將容器鏡像傳過去也不是不行,就是將壓力全給到發送方的網絡帶寬了。有沒有更好的解決方案?有。可以參考 github
代碼倉庫 的做法,我們通常會使用 git push
將代碼傳到 github,有需要的人自己通過 git pull
的方式將代碼從 github 拉到自己的機器上。
??那 Docker 也一樣,弄一個鏡像倉庫,通過 docker push 將鏡像推到倉庫,有需要的時候再通過 docker pull 將鏡像拉到機器上。這個負責管理鏡像倉庫推拉能力的服務,就叫 Docker Registry。
??基于 Docker Registry 的能力,我們可以搭建各種官方或私人鏡像倉庫,比如官方的叫 DockerHub,非官方的有清華大學的 Tuna 等等,一般公司內部也會有自己的鏡像倉庫。
1.5 容器
??現在,我們解決了服務器間傳輸容器鏡像的問題。我們可以跑到目的服務器上,執行 docker pull 拿到容器鏡像。然后執行 docker run 命令,將這個類似"壓縮包"的容器鏡像給"解壓縮",獲得一個獨立的環境和應用程序并運行起來。這樣一個獨立的環境和應用程序,就是所謂的容器(container)。我們可以在一個操作系統上同時跑多個容器。且這些容器之間都是互相獨立,互相隔離的。
- 隔離性 :容器之間相互隔離,每個容器都有自己獨立的文件系統、進程空間和網絡空間,不會互相干擾。這保證了應用程序在容器中運行的穩定性和安全性。
- 輕量化 :容器共享宿主機的內核,不需要像虛擬機那樣虛擬出一整個硬件環境,因此容器的啟動速度非常快,通常只需要幾秒鐘,并且占用的資源也相對較少。
- 可移植性 :由于容器是基于鏡像運行的,而鏡像在不同的環境(如開發、測試、生產環境)中都可以保持一致,因此容器可以在任何安裝了 Docker 的機器上運行,具有很強的可移植性。
1.6 Docker VS 虛擬機
??容器看起來很像我們用 vmware 或 kvm 整出來的傳統虛擬機,但不同的是,傳統虛擬機自帶一個完整操作系統,而容器本身不帶完整操作系統。
??容器的基礎鏡像實際上只包含了操作系統的核心依賴庫和配置文件等必要組件,它利用一個叫 Namespace 的能力讓它看起來就像是一個獨立操作系統一樣,再利用一個叫 Cgroup 的能力限制它能使用的計算資源。所以說,容器本質上只是個自帶獨立運行環境的特殊進程,底層用的其實是宿主機的操作系統內核。
二、Docker 的架構原理
2.1 C/S軟件架構
??現在,我們回到日常使用場景中,聊聊 Docker 的架構原理。它是經典的 Client/Server
架構。Client
對應 Docker-cli
, Server
對應 Docker daemon
。我們在命令行里敲 Docker 命令,使用的就是 Docker-cli.
??Docker-cli
會解析我們輸入的 cmd 命令,然后調用 Docker daemon
守護進程提供的 RESTful API,守護進程收到命令后,會根據指令創建和管理各個容器。再具體點,Docker Daemon
內部分為 Docker Server,Engine
兩層。
Docker Server
:本質上就是個 HTTP 服務,負責對外提供操作容器和鏡像的 api 接口,接收到 API 請求后,會分發任務給Engine
層Engine
層:負責創建Job
,由Job
實際執行各種工作。不同的 Docker 命令會執行不同類型的 Job 任務。
2.2 docker 命令
2.2.1 docker build
??如果你執行的是 docker build
命令,Job 則會根據 Dockerfile 指令,像包洋蔥皮似的一層層構建容器鏡像文件。
2.2.2 docker pull/push
如果你執行的是 docker pull
或 push
之類的鏡像推拉操作,Job 則會跟外部的 Docker Registry
交互,將鏡像上傳或下載。
2.2.3 docker run
??如果你執行的是 docker run
命令,Job 就會基于鏡像文件調用 containerd 組件,驅使 runC 組件創建和運行容器。
??現在我們再回過頭來看這句話,Docker 本質上就是一個將程序和環境打包并運行的工具軟件。具體點來說就是,它通過 Dockerfile 描述環境和應用程序的依賴關系, docker build 構建鏡像, docker pull/push 跟 Docker Registry 交互實現存儲和分發鏡像,docker run 命令基于鏡像啟動容器,基于容器技術運行程序和它對應的環境,從而解決環境依賴導致的各種問題。
好了,到這里,我們就了解了 Docker 的架構和基本運行原理了。接下來,我們再來聊聊跟 Docker 相關的幾個周邊。
三、Docker部署工具
3.1 Docker Compose :多容器部署
??我們現在知道了 Docker 容器 本身只是一個特殊進程,但如果我想要部署多個容器,且對這些容器的順序有一定要求呢?比如一個博客系統,當然是先啟動數據庫,再啟動身份驗證服務,最后才能啟動博客 web 服務。
??按理說挨個執行 docker run 命令當然是沒問題的,但有沒有更優雅的解決方案?有。我們可以通過一個 YAML 文件寫清楚要部署的容器有哪些,部署順序是怎么樣的,以及這些容器占用的 cpu 和內存等信息。
version: "3.8"services:A:image: "some-image-for-a"deploy:resources:limits:cpus: "0.50" # 限制 CPU 使用率為 50%memory: 256M # 限制內存使用量為 256MBB:image: "some-image-for-b"depends_on:- AC:image: "some-image-for-c"depends_on:- B
??然后,通過一行Docker-compose up
命令,開始解析 YAML 文件,將容器們一鍵按順序部署,就完成一整套服務的部署。這其實就是 Docker Compose 干的事情。Docker Compose 使得多容器應用的部署變得簡單高效,特別適合開發和測試環境。
3.2 Docker Swarm :集群部署
Docker
:解決的是一個容器的部署。Docker Compose
:解決的是多個容器組成的一整套服務的部署。Docker Swarm
:解決的是這一整套服務在多臺服務器上的集群部署問題。
??Docker Swarm 是 Docker 官方提供的容器編排工具,用于在多臺主機上管理和部署容器集群。它允許開發者將多個 Docker 主機組成一個虛擬的 Docker 環境,從而實現容器的高可用性、彈性伸縮和負載均衡。
??在 Docker Swarm 中,容器可以自動在不同的主機之間遷移,當某個主機出現故障時,其他主機可以接管其上的容器,確保應用程序的持續運行。此外,Swarm 還支持服務的擴縮容,可以根據業務需求動態調整容器的數量。
3.3 Kubernetes :開源的容器編排平臺
??Kubernetes(通常簡稱為 k8s)是一個開源的容器編排平臺,它與 Docker Swarm 的目標類似,都是用于管理和部署容器集群。
-
Docker 是 Kubernetes 的運行時基礎
在 Kubernetes 中,容器是應用程序的基本運行單元,而 Docker 容器是 Kubernetes 支持的主要容器運行時之一(除了支持 Docker 的容器外,還支持別人家的容器)。Docker 提供了容器的隔離、打包和分發機制,而 Kubernetes 則在此基礎上提供了更高級的編排功能,如服務發現、負載均衡、自動擴縮容等。 -
Pod 與 Docker 容器
Kubernetes 的核心概念是 Pod,Pod 是 Kubernetes 中最小的部署單元,它封裝了一個或多個緊密相關的容器。在 Kubernetes 中,一個 Pod 中的容器共享相同的網絡命名空間、存儲卷等資源,它們可以像一個整體一樣被調度和管理。從某種意義上說,Pod 可以被視為一個“超級容器”,它將多個 Docker 容器組(本質上就是一個服務進程)合在一起,形成一個邏輯單元。Docker 容器是 Pod 的組成部分,而 Pod 是 Kubernetes 編排的基本對象。
k8s會在多臺 Node 服務器上調度 Pod,進行部署和擴縮容。每個 Pod 內部可以含有多個 container -
Kubernetes 的編排功能
Kubernetes 提供了強大的容器編排功能,它通過一系列的控制器(如 Deployment、StatefulSet、DaemonSet 等)來管理 Pod 的生命周期。這些控制器可以根據預定義的策略自動創建、更新、刪除 Pod,并確保應用程序的高可用性和一致性。此外,Kubernetes 還提供了服務發現和負載均衡機制,通過定義 Service 對象,可以將 Pod 暴露為一個網絡服務,客戶端可以通過 Service 的虛擬 IP 地址訪問 Pod 提供的服務。Kubernetes 的自動擴縮容功能可以根據業務負載動態調整 Pod 的數量,從而實現資源的高效利用。 -
對比Docker Compose
Docker Compose 基于多個 container 創建的一整套服務,其實就是 k8s 里的 pod。而 Docker Swarm 做的事情和 k8s 一樣,本質上就是在調度 pod。k8s 的官方定義,叫容器編排引擎,將它理解為,以 API 編程的方式管理安排各個容器的引擎。
??現在,我們再>回過頭來看下 Docker 的圖標,是一個個集裝箱,放在一艘船上,這一個個集裝箱指的就是互相隔離的容器,而 k8s 的圖標,則是一個輪船上的方向盤,意思是 k8s 控制著輪船的航向,其實指的就是調度容器。這波聯想就非常形象了,現在大家通了嗎?
四、總結
-
Docker 本質上就是一個將程序和環境打包并運行的工具軟件,而 Docker 容器本質上只是個自帶獨立運行環境的特殊進程,底層用的其實是宿主機的操作系統內核。
-
Docker 軟件 通過
Dockerfile
描述環境和應用程序的依賴關系,docker build
構建鏡像,docker pull/push
跟Docker Registry
交互實現存儲和分發鏡像,docker run
命令基于鏡像啟動容器,基于容器技術運行程序和它對應的環境,從而解決環境依賴導致的各種問題。 -
Docker 解決的是一個容器的部署問題,
Docker Compose
解決的是多個容器組成的一套服務的部署問題,Docker Swarm
解決的是多個容器組成的一套服務在多臺服務器上的部署問題,k8s
則是Docker Swarm
的競品,在更高維度上兼容了 Docker 容器,實現了容器編排調度。
??在現代的云原生架構中,Docker 和 Kubernetes 已成為不可或缺的技術,它們為開發和運維團隊提供了強大的工具,使得應用程序的開發、部署和管理變得更加高效和可靠。