小鯨魚的前世今生--Docker

2021-12-26 字節前端 ByteFE
Docker 是什麼?圖源百度圖片

Docker 是一個由 go 語言編寫的,開源的應用容器引擎。

開發者可以打包他們的應用以及依賴包到一個可移植的鏡像[1]中,然後發布到任何流行的Linux[2]或Windows[3]機器上,也可以實現虛擬化[4]。

容器是完全使用沙箱[5]機制,相互之間不會有任何接口。

Docker 背後實現原理是什麼?Docker 架構

實現一個完整的容器,需要 Namespace、Cgroups 和聯合文件系統這三項 Linux 技術的支撐。

圖源百度圖片Namespace

Namespace 是 Linux 內核用來隔離內核資源的一種方式。通過 Namespace 可以對某些進程進行限制,使得其只能訪問與自身相關的那部分資源,其他資源不可見。

如此,不同進程之間也是相互無感知的。這種隔離覆蓋面十分廣泛,包括但不限於:隔離進程 ID、主機名、用戶 ID、文件名、網絡訪問和進程間通信等相關資源。在 Docker 的世界中,主要用到以下六種命名空間。

mnt namespace:隔離文件系統掛載點,可在不同進程中看到不同掛載目錄,且不影響主機掛載目錄

ipc namespace:隔離進程間通信(如:信號量,消息隊列和共享內存)

user namespace : 隔離用戶和用戶組,可實現 docker 內擁有 root 權限而在主機上只是普通用戶

正是由於 Docker 使用了 Linux 的這些 Namespace 技術,才實現了 Docker 容器的隔離。

Cgroups

Cgroups 是控制組群(control groups)的簡寫,可用於限制、控制與分離一個進程組的資源(如 CPU、內存、磁碟輸入輸出等)。

在 Docker 的世界中,Cgroups 通常用來限制容器的 CPU 和內存等資源的使用。

資源限制 : 限制資源的使用量(如通過限制某個業務的內存上限,保護主機其他業務的安全運行)。

優先級控制 : 不同的組可以有不同的資源( CPU 、磁碟 IO 等)使用優先級。

圖源掘金小冊-開發者必備的 Docker 實踐指南聯合文件系統

聯合文件系統是一種分層、輕量級並且高性能的文件系統,它支持對文件系統的修改作為一次提交來一層層的疊加,同時可以將不同目錄掛載到同一個虛擬文件系統下。

在 Docker 的世界中,聯合文件系統為容器提供構建層,使得容器可以實現寫時複製以及鏡像的分層構建和存儲。

鏡像本身是只讀的,在運行某個容器的時候,會在鏡像外層附加一個可讀寫層,這也是基於聯合文件系統實現的。

FROM busybox

COPY test /tmp/test

RUN mkdir /tmp/testdir

上述每一行命令都會生成一個鏡像層,當不同的鏡像之間有相同的鏡像層時,便可以實現不同的鏡像之間共享鏡像層的效果。(比如基於 base 鏡像擴展的鏡像)

圖源拉鉤教育

鏡像層共享這個功能十分強大,每一層都可以共享。

圖源百度圖片作業系統層面的虛擬化

以上這種對進程進行封裝隔離的技術,屬於作業系統層面的虛擬化技術[6]。隔離的進程獨立於宿主和其它的隔離的進程,因此也稱其為容器。容器本質是一個受限制的進程,它沒辦法像直接運行在主機上的進程那樣獲取主機上的進程、環境變量、網絡等信息。

該技術最初實現是基於LXC[7](Linux Container),從 0.7 版本以後開始去除 LXC,轉而使用自行開發的libcontainer[8]。從自 1.11 版本開始,進一步演進為使用runC[9]和containerd[10]。

客戶端/服務端模式圖源拉鉤教育docker

如上圖所示:Docker 和 MySQL 一樣,也是客戶端-服務端的模式。Docker 客戶端其實是一種泛稱,用戶可通過 docker 命令或者直接請求 REST API 的方式與 Docker 服務端交互。

dockerd

Docker 服務端是 Docker 所有後臺服務的統稱。其中 dockerd 是一個非常重要的後臺管理進程,它負責響應和處理來自 Docker 客戶端的請求,然後將客戶端的請求轉化為 Docker 的具體操作。這個過程中 dockerd 會通過 grpc(一個 rpc 框架)與 containerd 通信,containerd 作為 dockerd 的下層服務

runC

runC 是一個根據 OCI(開放容器標準)規範生成和運行容器的 CLI 工具,可通過命令行的形式控制容器的銷毀與創建。

contained

containerd 是 dockerd 和 runC 之間的一個中間交流組件,docker 對容器的管理和操作基本都是通過 containerd 完成的。例如:容器生命周期管理、鏡像管理。

containerd-shim

containerd 通過 containerd-shim 啟動並管理 runC,containerd-shim 主要作用是可以在不中斷容器運行的情況下升級或重啟 dockerd。

Docker 與虛擬化技術

虛擬化技術指的是通過隱藏特定計算平臺的實際物理特性,為用戶提供抽象、統一、模擬的計算環境。這種計算環境,也被稱為虛擬機。

Docker 是對 Linux 容器的一種封裝,具有高性能,低開銷,接口簡單易用等特點。真正使其超過其他同類產品,迅速佔領市場,成為目前最流行的 Linux 容器技術解決方案的根本是 Docker 引入了鏡像功能。

與系統級別的虛擬機不同,容器技術的虛擬其實是進程級別的。

圖源極客時間

從上圖中可以看出,虛擬機是通過在宿主機上啟動一個虛擬機監視器 HyperVisor 來管理控制虛擬機的,最經典的 HyperVisor 就是 VirtualBox。與容器相比,虛擬機包含了整個客戶作業系統,這也是二者性能差異的主要成因。

從啟動角度來看,進程級別的容器啟動肯定是比系統級別的虛擬機啟動要快得多。從資源佔用角度來看,容器是按需佔用,虛擬機是全量佔用。從資源利用率角度來看,多容器可以共享資源,而虛擬機是獨享資源。從構建角度來看,容器是按需構建,體積小;虛擬機是全量構建,體積大。圖源掘金小冊-開發者必備的 Docker 實踐指南Docker 解決了什麼問題?

Docker 是容器技術的一種體現,而容器技術的根本是為了抹平軟體運行的環境差異。

如何抹平?Docker 通過 build 命令將應用程式和其依賴構建成鏡像文件,鏡像是只讀的,這意味著構建完成後,鏡像不會再發生任何變化。如此,基於該鏡像啟動的容器環境必然一致。同理,跑在這個容器中的應用程式所處環境也一致。

此外,容器是完全使用沙箱機制,容器相互之間完全隔離,互不影響。

Docker 有哪些適用場景?

作為 Serverless 的底層依賴,動態擴縮容

搭建微服務架構,可通過多容器運行多服務的形式對複雜項目進行拆解

核心概念鏡像

Docker 鏡像是一個特殊的文件系統,它包含了容器運行時所需要的所有基礎文件和配置信息,是容器啟動的基礎。這就意味著,必須先有鏡像才能啟動容器。

鏡像可以自己構建也可以從鏡像倉庫[11]拉取。

容器

鏡像和容器的關係就好像類和實例的關係。一個類可以有很多實例,一個鏡像也可以有很多容器。

容器不可以脫離鏡像存在。事實上,可以理解為容器=容器層(可寫)+鏡像(只讀)。

圖源拉鉤教育

寫時複製

這部分涉及到一個寫時複製(copy-on-write)的技術,能夠有效的提高磁碟的利用率。尤其是對讀操作,十分的友好。

寫時複製會將要修改的內容從鏡像拷貝到容器的可讀寫層,並不會直接修改鏡像的源文件。

這意味著即便是寫的時候有其他容器對同一鏡像資源進行讀取,也不會發生資源不一致的情況。

多容器操作同一個文件也是各自在自己的容器空間創建讀寫層並完成修改,相互隔離,互不影響。

生命周期

每一個容器完整生命周期都具有創建,運行,停止,暫停,刪除這五個狀態。

圖源百度圖片創建:容器被創建,所需資源已就緒,容器中的應用程式尚未運行。

暫停:容器中的所有應用程式都處於暫停 ( 非停止 ) 狀態。

停止:容器中的應用程式均已停止,但所佔用資源不會釋放。

值得注意的是:如果要刪除一個鏡像,必須保證沒有容器佔用,停止狀態的容器也不行。

倉庫

Docker 的鏡像倉庫(public/private)類似於代碼倉庫,可以用來存儲和分發 Docker 鏡像。

鏡像,容器,代碼倉庫三者關係如下:

安裝官方安裝方式 Docker Desktop

Docker Desktop 其本質是藉助 windows 和 macOS 的平臺特性,搭建了一個 Linux 環境,進而運行 docker。

圖源掘金小冊-開發者必備的 Docker 實踐指南鏡像加速

為使得在國內從 Docker Hub 拉取鏡像更快,可以配置鏡像加速器。

阿里雲加速器\(控制臺 -> 登錄帳號-> 應用搜索容器鏡像服務 -> 側邊欄選擇鏡像加速器 -> 複製地址\)[14]

網易雲加速器https://hub-mirror.c.163.com[15]

百度雲加速器https://mirror.baidubce.com[16]

由於鏡像服務可能出現宕機,建議同時配置多個鏡像。

配置方式

下載安裝官方提供的 Docker Desktop 後,點擊 docker 圖標,選擇 setting(windows)或者 preferences(macOS)面板,切換到 docker engine ,編輯 json 文件,加入鏡像源地址後點擊右下角的 Apply&Restart。

安裝檢測

命令行輸入 docker info 後關注 Registry Mirrors

Hello world

本示例將展示一個簡單的 koa server 如何在 docker 中跑起來。

1. 創建項目 koa-server

# 新建文件夾
mkdir koa-server
# 進入
cd koa-server
# 項目初始化,生成package.json
npm init -y
# 安裝koa
npm i koa
# 新建app.js
touch app.js
# 在app.js中寫入如下代碼
const Koa=require('koa')
const app=new Koa()
app.use(ctx=>{
    ctx.body='hello koa'
})
app.listen(3000,()=>{
    console.log('run server__')
})

2. 編寫 Dockerfile 文件,根據其描述構建鏡像

# 新建Dockerfile文件
touch Dockerfile
# 寫入如下內容
FROM node:12.20.1
COPY . /app
WORKDIR /app
RUN npm i
EXPOSE 3000

命令解釋

指定基礎鏡像為 node,冒號表示標籤,此處指的是 12.20.1 版本的 node

將當前目錄下的所有(非.dockerignore 排除)文件,都拷貝進入鏡像文件的/app 目錄。

安裝依賴(安裝後所有的依賴,都將打包進入鏡像文件)。

將容器 3000 埠暴露出來, 允許外部連接這個埠。

其他常用命令

圖源拉鉤教育

3. 編寫.dockerignore 排除文件

# 新建.dockerignore排除文件
touch .dockerignore
# 寫入如下內容
node_modules

4. 構建鏡像

koa-server 根目錄下執行如下命令構建鏡像:

docker image build -t koa-server-image .

-t 用於指定構建的鏡像名,後面可用冒號指定標籤名,默認 latest

最後的那個點表示 Dockerfile 文件所在的路徑,因為是進入 koa-server 後執行的構建命令,所以是當前目錄,可以看成是./

鏡像構建完成後可用 docker image ls 命令查看鏡像列表:

5. 啟動容器

Docker 內部環境與主機資源都是隔離的,因此需要定義容器與物理機的埠映射來進行訪問。

此外,容器是在鏡像基礎上啟動,所以要先保證有這個鏡像。如果本地沒有,默認會去公開鏡像倉庫中查找同名鏡像,找到後拉取到本地再執行 docker run 命令。

鏡像,容器,應用程式三者關係是:鏡像是容器啟動的先決條件,容器中運行著真正的應用程式。

docker container run -p 3000:3000 -it koa-server-image /bin/bash

-p 參數就是用於指定埠映射,格式為主機埠:容器埠

/bin/bash 相當於在-it 參數返回的交互終端中執行/bin/bash

因為是 node 環境,不加/bin/bash 效果就相當於終端輸入 node 後回車的效果

對於上述-p 參數做一個補充說明,這裡涉及到了 docker 中用於處理埠映射的 docker-proxy 組件。當我們使用帶有-p 參數的 docker run 命令,該組件就會把容器內相應的埠映射到主機上來,這樣主機就可以訪問容器內資源了。

6. 效果驗證

上述命令執行後會返回一個交互終端,此時已經進入容器內部,通過執行 node app.js 啟動 koa-server

瀏覽器訪問地址http://localhost:3000/,頁面顯示 hello koa

如果想退出容器,可以先 ctrl+c 打斷應用程式,然後 ctrl+d 退出。如果安裝了 Docker Desktop,可用圖形化界面形式去管理鏡像和容器,十分方便。更多:Docker run 命令[17]。

容器遷移

通過 docker 提供的 export 和 import 命令可以十分方便的實現容器的導入導出,從而完成遷移工作。

導出

docker export 容器名 > xxx.zip
#demo
docker export busybox > busybox.zip

執行完後會生成一個壓縮包,可發送到另一臺機子上再導入使用。

導入

導出的容器在被導入後實際會成為一個鏡像,可使用 docker run 命令基於該鏡像啟動容器。

docker import xxx.zip xxx
# demo
docker import busybox.zip busybox:test
docker run -it busybox:test sh

加入我們

我們是字節跳動互娛前端安全團隊,是抖音、剪映、輕顏、激萌等現象級產品的守護者。

我們年輕、思維活躍、不拘一格,是一群持續學習和探索的技術極客,每天與Web安全攻防、全棧技術、跨端技術、微前端、微服務、Serverless等各種技術打交道。我們以技術為武裝,為用戶數據安全保駕護航。

點擊閱讀原文,投遞簡歷,來互娛前端一起做優秀事情吧!


關注我們,持續了解最新技術!

參考資料

[1]

鏡像: https://baike.baidu.com/item/%E9%95%9C%E5%83%8F/1574

[2]

Linux: https://baike.baidu.com/item/Linux

[3]

Windows: https://baike.baidu.com/item/Windows/165458

[4]

虛擬化: https://baike.baidu.com/item/%E8%99%9A%E6%8B%9F%E5%8C%96/547949

[5]

沙箱: https://baike.baidu.com/item/%E6%B2%99%E7%AE%B1/393318

[6]

作業系統層面的虛擬化技術: https://zh.wikipedia.org/wiki/%E4%BD%9C%E6%A5%AD%E7%B3%BB%E7%B5%B1%E5%B1%A4%E8%99%9B%E6%93%AC%E5%8C%96

[7]

LXC: https://linuxcontainers.org/lxc/introduction/

[8]

libcontainer: https://github.com/docker/libcontainer

[9]

runC: https://github.com/opencontainers/runc

[10]

containerd: https://github.com/containerd/containerd

[11]

鏡像倉庫: https://hub.docker.com/

[12]

mac: https://hub.docker.com/editions/community/docker-ce-desktop-mac/

[13]

windows: https://hub.docker.com/editions/community/docker-ce-desktop-windows/

[14]

阿里雲加速器(控制臺 -> 登錄帳號-> 應用搜索容器鏡像服務 -> 側邊欄選擇鏡像加速器 -> 複製地址): https://www.aliyun.com/product/acr?source=5176.11533457&userCode=8lx5zmtu

[15]

https://hub-mirror.c.163.com: https://www.163yun.com/help/documents/56918246390157312

[16]

https://mirror.baidubce.com: https://cloud.baidu.com/doc/CCE/s/Yjxppt74z#%E4%BD%BF%E7%94%A8dockerhub%E5%8A%A0%E9%80%9F%E5%99%A8

[17]

Docker run 命令: https://www.runoob.com/docker/docker-run-command.html

[18]

Docker —— 從入門到實踐:https://yeasy.gitbook.io/docker_practice/: https://yeasy.gitbook.io/docker_practice/

[19]

Docker 入門教程:http://www.ruanyifeng.com/blog/2018/02/docker-tutorial.html: http://www.ruanyifeng.com/blog/2018/02/docker-tutorial.html

[20]

開發者必備的 Docker 實踐指南:https://juejin.cn/book/6844733746462064654: https://juejin.cn/book/6844733746462064654

[21]

由淺入深吃透 Docker:https://kaiwu.lagou.com/course/courseInfo.htm?courseId=455#/content: https://kaiwu.lagou.com/course/courseInfo.htm?courseId=455#/content

[22]

Serverless 入門課:https://time.geekbang.org/column/intro/305: https://time.geekbang.org/column/intro/305

[23]

Docker 學習筆記之運行和管理容器:https://www.cnblogs.com/JetpropelledSnake/p/10330674.html: https://www.cnblogs.com/JetpropelledSnake/p/10330674.html

[24]

Docker 架構中的幾個核心概念:https://www.jianshu.com/p/de3184ad0800: https://www.jianshu.com/p/de3184ad0800

[25]

作業系統層面的虛擬化技術:https://zh.wikipedia.org/wiki/%E4%BD%9C%E6%A5%AD%E7%B3%BB%E7%B5%B1%E5%B1%A4%E8%99%9B%E6%93%AC%E5%8C%96: https://zh.wikipedia.org/wiki/%E4%BD%9C%E6%A5%AD%E7%B3%BB%E7%B5%B1%E5%B1%A4%E8%99%9B%E6%93%AC%E5%8C%96

[26]

runC:https://github.com/opencontainers/runc: https://github.com/opencontainers/runc

[27]

containerd:https://github.com/containerd/containerd: https://github.com/containerd/containerd

相關焦點

  • 海豹突擊隊的今生前世
    下面就讓我們一起來看看海豹突擊隊在現實裡的前世與在遊戲中的今生吧!一、前世海豹突擊隊起源於第二次世界大戰時, 1942年由美國陸軍和美國海軍設立兩棲偵察兵與突襲兵學校。正式成立於1962年,到1988年時已經擴大到兩個戰鬥群,共有7個中隊,人數約1600人。海豹突擊隊現已成為美國實施局部戰爭、應付突發事件的殺手鐧。
  • 這個連隊的前世今生超乎你的想像
    / 戰火硝煙中走來的曲折「前世」「朱德號」功勳坦克所在連前身是華東野戰軍坦克隊。/ 寒霜鑄劍初露鋒芒,傳承基因決勝強軍「小葉,你的水壺水裝滿沒有?」小編來到訓練現場看到,武裝五公裡考核前,以高標準嚴要求著稱的「鐵面教頭」的士官長徐騰榮正對裝具一人不漏的進行點驗,一聲令下,全連官兵都如離弦之箭一般向前衝去,因為他們知道,作為「朱德號」的一員,只有前進,沒有退路,在戰場上支援速度決定了戰場的勝負定論,所以,他們不敢大意。
  • 重慶記憶 | 防空洞的前世今生
    夏天裡它是重慶人熟知的「純天然空調」;嘴饞了可以去洞子吃火鍋;手癢了可以去洞子改建的步行街購物;你走過的地下通道,也可能是一個煥發新生的防空洞……重慶人對防空洞已經見怪不怪,可防空洞的前世今生,你真的了解嗎?
  • 《白宮舊主》了解美利堅的前世今生:這到底是怎麼樣一個國家?
    隨著中國的發展,人們越來越有必要了解美國的前世今生和治國外交策略。
  • 槍械百科:M14EBR的前世今生
    在文章開頭前,小編想問大家一個問題,在CF當中,有沒有這樣一款步槍?它擁有AK般的威力,也擁有M4般的準度,與此同時,它與AK相比更具現代性,與M4相比它更具穩定性。如果真的有這樣一款步槍,那麼小編認為它非M14EBR莫屬了!今天,小編就跟大家聊一聊這款步槍神器的前世今生。
  • 伊拉克-黎凡特伊斯蘭國的前世今生
    這就是伊拉克武裝組織ISIS的前世今生。了解這一切之後,美國政府又該如何應對?美國的軍事力量,特別是軍火優勢,並不能抹去伊拉克血腥的歷史,也不能重劃記中東地區的邊境。只有在伊拉克領導人自己證明政府能夠代表伊拉克各個團體的利益之後,而不是之前,歐巴馬政府才能予以支持。歐巴馬政府應該銘記於心一條準則:只能看他們做了什麼,而不能看他們承諾要做什麼。
  • 海商法的「前世今生」
    現在,就與小編一起來認識一下海商法的「前世今生」吧!海商法一詞包括了兩層含義,一是指作為法律的海商法,如《中華人民共和國海商法》,《英國海上貨物運輸法》等等;二是指海商法學科,即以海商法為主要研究對象的古老的法律學科,一般又稱為海商法學。 海商法是調整海上運輸關係和船舶關係的法律規範的總稱。
  • Docker,救你於「深度學習環境配置」的苦海
    這個就相當於一個虛擬機,我們可以在Windows系統裡安裝一個linux的虛擬機,但是docker相比虛擬機來說佔用內存更小,轉移起來更加方便。寫下上面這些話時,我使用docker也有幾周了,剛開始對docker的各種操作很懵逼,所以決定記錄下來經常使用的各種操作和對應的說明,方便日後的使用。後來發現記錄的還挺不錯,所以決定整理成體系分享給大家。
  • 俄羅斯光頭黨的前世今生
    前天我發了一組照片《俄羅斯光頭黨
  • 5部電影帶你了解塔利班的「前世今生」
    通過網民們的發言,小編發現,目前國內外還有許多華人朋友沒有搞清楚阿富汗究竟發生了什麼,今天就讓我們一起了解一下阿富汗的「前世今生」。據意媒報導,8月16日,塔利班以驚人的速度完成了接管阿富汗政權的行動,他們佔領了首都喀布爾的總統府,數以萬計的平民湧入喀布爾機場,為了儘快逃離這個再度被塔利班統治的國度。
  • 《幻影突擊》最受歡迎槍械的前世今生
  • 從領花、領章看武警的「前世今生」
    今天,請跟著蜀黍一起,通過領花、領章了解中國武警的「前世今生」
  • 解析中國南海九段線的前世今生
    中國南海九段線的「前世今生」抗日戰爭勝利後,中國政府根據1943年12月籤署的《開羅宣言》和1945年7月籤署的《
  • 「出雲號」的前世今生
    「出雲號」的前世今生  很多媒體都報導過「出雲」,上一艘「出雲」是日本侵華艦隊的旗艦。但其實我們再翻一翻近代海軍史的話,那出雲和我們中國的淵源遠遠不只是一艘旗艦的名字那麼簡單。  怎麼說呢?其實上一艘出雲號軍艦和中國的關係,在出雲號還沒有誕生的時候就存在。
  • Docker 安裝
    sudo apt-get -y updatesudo apt-get -y install docker-ce安裝指定版本# 安裝指定版本的Docker-CE:# Step 1: 查找Docker-CE的版本:# apt-cache madison docker-ce
  • 橡樹 | 搭錯車——老司機的前世今生
    薦文:  以兵家四勢,淺析國共內戰成敗  北洋艦隊徹底覆滅123年散記《少女之心》,老司機的前世今生《張自忠上將殉國記》上集 1979,再看中越諒山戰役(橡樹中越戰爭系列)《水仙花》,老司機的前世今生鄧麗君,走過四十年的記憶——老司機曾經的時代
  • 維內託級戰列艦的前世今生(三)
    前篇:維內託級戰列艦的前世今生(一)維內託級戰列艦的前世今生(二)1939年9月,德國入侵波蘭
  • KAGA「加賀號」的前世今生(一)
    本文就帶著大家探訪「加賀」的前世今生。一、「加賀」名稱的由來「加賀」是日本古代「國」名,這個「國」並非現代意義上的國家,而是類似於「藩鎮」,省一級行政單位。「加賀」的發音是」卡噶「,本義據說是「高地上的草地」(筆者不通日語,無法求證)。弘仁十四年(公元823年),越前國的加賀郡和江沼郡分離出來成立了加賀國。
  • 【艦娘的前世今生】峰風級驅逐艦——島風號
    本作品由kcwiki原創中心作者速吸醬執筆,由kcwiki原創中心畫師ANKER繪製立繪畫師寄語:本期《艦娘的前世今生
  • 重思「印太」概念的前世今生
    近年,歐美學者也掀起了研究「印太」理論的一股小熱潮,但多不得其法,時代誤植問題屢見不鮮。起初,「地緣政治學家」們堅稱「印太」源於安倍晉三在2016年8月發表的「自由開放的印度太平洋」演說。「印太」的前世又如何啟迪了它的今生?▲筆者收藏的豪斯霍弗著作初版:左1924年《太平洋地政學》、右1939年《印度太平洋空間中的德國文化政治》