Docker學習之工作原理

2021-12-29 白砂

    想學習好一點技術,最好的方法就是學習這項技術的工作原理。一直很好奇docker是如何實現互不影響的,很是神奇。

    通過學習查閱一些資料,慢慢的了解了底層是如何實現的,特此記錄一下。

    從本質上說,docker容器其實就是一個沙盒技術。就好像把一個應用隔離在一個盒子內,讓其運行。因為盒子有邊界的存在,應用於應用之間不會存在相互幹擾。

實現原理

    實現容器的核心,其實就是要生成限制應用運行時的邊界。編譯後的可執行代碼加上數據,叫做程序。

    而把程序運行起來後,就變成了進程,也就是所謂的應用了。如果在啟動的時候,加上一個邊界,是不是就實現期待的沙盒了?

    在Linux中,實現容器的邊界,主要有兩種技術,Cgroups 和 Namespace。

Namespace

    Namespace是用於分離進程樹、網絡接口、掛載點以及進程間通信等資源的方法。通俗點講,就是將容器隔離起來,實現邊界。

    在日常使用Linux 和 macOS時,並沒有必要運行多個完全分離的伺服器需要。但是如果在伺服器上啟動多個服務,這些服務其實會相互影響的。

    每個服務都能看到其他服務的進程,也可以訪問宿主機上的任意文件,這是很多時候不願意看到的,我們希望他們能做到完全隔離,就像運行在不同機器上一樣。

    在這種情況下,一旦伺服器上一個服務被入侵,其他服務也就被入侵了。

    而Docker就是通過namespace對不同容器實現的隔離。

Cgroups

    通過Namespace技術,我們實現了容器和容器之間,容器和宿主機之間的隔離。

    但這還不夠,想像一下一種場景。宿主機上運行著兩個容器,雖然在容器之間相互隔離,但在宿主機的視角來看,只是兩個特殊的進程。

    而進程之間自然存在著競爭關係,自然可以將系統資源吃光,這是一定要避免的。

    Cgroups就是Linux內核中用來為進程設置資源的一個技術。

Linux Cgroups 全稱是 Linux Control Group,主要作用限制進程組使用的資源上限。例如CPU、磁碟I/O、內存、和網絡帶寬。還可以對進程進行優先級設置,審計,掛起和恢復等操作。

」容器的文件系統:rootfs

    現在知道容器的核心技術就是通過 Namespace 限制了容器看到的視野 , 通過Cgroup限制容器可訪問的資源。

    在容器內,可以看到完全獨立的文件系統,而且不會收到宿主機以及其他容器的影響。

    這個獨立的文件系統,叫做容器鏡像, 專業的名字叫 rootfs, rootfs中包含了一個作業系統所需要的文件,配置和目錄,但不包含系統內核。

    因為在Linux中,文件和內核是分開存放的,作業系統只有在開啟啟動時才會加載指定的內核。這就說明,所有的容器都會共享宿主機上作業系統的內核。

    有了rootfs之後,在鏡像內,打包的不僅僅是應用,還有所需要的依賴,都被封裝在一起。這就解決無論是在哪,應用都可以很好運行的原因。

    不光是這樣,rootfs 還解決了可重用性的問題。

    想像一下,你通過 rootfs 打包一個包含php的centos鏡像,別人需要安裝一個Nginx服務,是否還需要從頭開始搭建php服務呢?

    docker 在解決這個問題的時候,引入一個層(layer)的概念,每次對 rootfs 的更改,都只保留增量的內容,而不是fork一個新鏡像。

    層級的想法,同樣來自於 Linux,一個叫 union file system (聯合文件系統)。

    它最主要的功能就是將不同位置的目錄聯合掛載到同一個目錄下。對應在 Docker 裡面,不同的環境則使用了不同的聯合文件系統。

Image、Container Layer定義Image 定義

    鏡像(Image)就是一堆只讀層的統一視角,也許這個定義有些難以理解,看張圖理解下。

鏡像統一視角

    從左邊看到多個只讀層,他們重疊在一起。除了最下面的一層,其它層都會有一個指向下一層的指針。

    這些層是Docker內部的實現細節,並能在運行Docker機器的文件系統上訪問到。

    統一文件系統(union file system)技術能夠將不同的層整合成一個文件系統,為這些層提供了一個統一的視角,這樣就能隱藏錯層的存在,在用戶的角度看來,只存在一個文件系統。在在右邊的圖上可以看到這種形式

Container 定義

    容器(container)的定義和鏡像(image)幾乎一模一樣,也是一堆層的統一視角,唯一區別在於容器最上面的那一層是可讀可寫的。

容器統一視角

    這裡容器的定義並沒有提及到容器是否運行,運行時的容器是怎麼樣的呢?

Running Container 定義

    一個運行態的容器(running container)被定義為一個可讀寫的統一文件系統加上隔離的進程空間和包含其中的進程。

運行態的容器

    文件系統隔離技術促使了Docker成為了一個前途無量的技術。一個容器中的進程可能會對文件進行修改、刪除、創建,這些改變都將作用於可讀可寫層(read-write layer)。

可讀可寫層修改文件Image Layer 定義

    為了將零星的數據整合起來,提出了鏡像層(image layer)的概念。一個鏡像層不僅僅包含文件系統的改變,他還能包含一些其他重要的信息。

image 層

    元數據(metadata)就是關於這個層的額外信息,他不僅能夠讓Docker獲取運行和構建時的信息,還包括父層的層次信息。需要注意的是,只讀層和讀寫層都包含元數據。

只讀層和讀寫層包含元數據

    除此之外,每一層都有一個指向父級層的指針,這點和mvcc中版本鏈是一樣的。如果沒有這個指針,說明他是最底層。

層次鏈Docker命令詳解docker create <image_id>

    docker create 命令為指定的鏡像(image)添加一個可讀可寫層,構建一個新的容器。

添加可讀可寫層

    這個容器此時並沒有啟動運行。

鏡像 -> 容器docker start <container_id>

    docker start 命令為容器文件系統創建一個進程隔離空間。注意:每一個容器只能夠有一個進程隔離空間。

創建進程隔離空間docker run <image_id>

    看到這個命令的時候我會產生一個疑問:run 和 start 有什麼區別?

docker run 命令解釋圖

    docker run 其實是兩個命令的結合體:docker create 和 docker start。

    首先會使用 docker create 利用鏡像創建一個容器,然後運行這個容器。這個命令雖然很方面,但是也會隱藏一部分細節。

題外話:git pull命令其實就是 git fetch 和 git merge 兩個命令的組合。同樣的,docker run就是docker create和docker start兩個命令的組合。

」docker ps

    這個命令會羅列出所有運行中的容器,隱藏了未運行的容器,如果想看到未運行的,使用 docker ps -a 則可以看到所有的容器。

docker psdocker commit <container_id>

    docker commit 會將可讀可寫層轉換為一個可讀層,這樣就把一個容器轉換為不可變的鏡像。

docker commitdocker build

    docker build 會反覆執行多個命令。

執行過程

    build命令根據Dockerfile文件中的FROM指令獲取到鏡像,然後重複的。1、run(create和start);2、修改;3、commit。在循環中的每一步都會生成一個新的層,因此許多新的層會被創建。

    docker 原理中涉及到很多linux相關的知識,這方面的知識還需要後續的學習補充。

    總結的不對的地方,還請各位大佬多多指點。

    如果我的文章對你有所幫助,還請幫忙點讚、在看、轉發一下,你的支持會激勵我繼續堅持下去,非常感謝!

    你還可以把我的公眾號設為「星標」,這樣當公眾號文章更新時,你會在第一時間收到推送消息,避免錯過我的文章更新。


Namespace[1]

Layer層[2]

參考資料[1]

命名空間:https://draveness.me/docker。

[2]

層級:https://www.yht7.com/news/140896。

相關焦點

  • Docker集群管理之Docker Compose
    前言:在上一篇《Docker集群管理之Docker Machine》中,我們通過源碼分析了解了Docker Machine的工作原理,使用者可以通過Docker Machine的一條命令在任意支持的平臺創建一個Docker主機,並能集中管理這些主機。Docker主機創建好之後,接下來就該考慮Docker容器部署的問題了。
  • 【乾貨】解密監控寶Docker監控實現原理
    2、Docker監控的工作原理  大家都知道,CloudWise在APM領域率先提出了端到端的一體化監控模型,並且在此模型上,發布了技術領先、便於部署和管理的SmartAgent軟體架構。此次Docker監控的實現,也是基於SmartAgent的架構來完成的。  SmartAgent以部署的快捷高效和智能化見長,整個部署過程中,用戶在兩分鐘內便可完成。
  • docker系列學習(二):Docker + Flask 例子
    系列學習(一):整體認識docker系列學習(二):Docker + Flask 例子(當前文章)這是一個簡單的 Docker + Flask 入門教程。在接下來的學習中,你將學習到如何創建,運行,構建,推送,拉取,殺死,修剪和使用 flask 作為 api 在 docker 中如何工作。設置步驟創建一個文件夾來保存項目。我們將在這裡花費大部分時間,首先我們使用 mkdir 命令創建文件夾。mkdir hello_docker_flask之後利用 cd 命令切換到這個目錄。
  • 聽我跟你侃會兒Docker原理
    通常應用程式對安裝的系統環境會有各種嚴格要求,當伺服器很多時部署時系統環境的配置工作是非常繁瑣的。Docker讓應用程式不必再關心主機環境,各個應用安裝在Docker鏡像裡,Docker引擎負責運行包裹了應用程式的docker鏡像。
  • Docker鏡像進階:了解其背後的技術原理
    什麼是 docker 鏡像  docker 鏡像是一個只讀的 docker 容器模板,含有啟動 docker 容器所需的文件系統結構及其內容,因此是啟動一個 docker 容器的基礎。
  • Docker學習筆記(1)
    文章來自零釼實驗室成員南宮十六文章共2694字13圖預計閱讀時間6分鐘點擊原文查看更佳前言最近學習了version容器生命周期管理1.docker run創建一個新的容器並運行一個命令1docker run [options] IMAGE [COMMAND
  • docker下高並發和高可用之docker swarm使用
    ,操作步驟參考Linux下安裝和使用Docker安裝完,使用命令sudo systemctl start docker啟動docker,再通過命令docker version查看docker版本信息利用docker swarm 命令來指定其中一臺虛擬機為docker的Manager管理機docker swarm init --advertise-addr
  • Docker —— 從入門到實踐
    本書最初源於WaitFish的《Docker學習手冊v1.0》內容。後來,yeasy 根據最新Docker版本對內容進行了修訂和重寫,並增加了部分內容;與WaitFish協商,將所有內容開源,採用網際網路合作的方式進行創作和維護。本書既適用於具備基礎Linux知識的Docker初學者,也可供希望理解原理和底層實現的高級用戶參考。
  • Docker CNM 原理分析與實戰
    可是對於自己來說,熟悉Docker網絡無論對於自己的工作、興趣以及自己的執念都有一定的意義。如果對Docker network感興趣可以看下歷史文章。本文是一個Docker CNM原理的簡單的分析以及實現一個類似於bridge的自定義插件。這並不是結束,後面我還會實現基於全局的OVS的網絡插件。實例的代碼見文末。
  • 10張圖帶你深入理解Docker容器和鏡像
    於是,我花了幾周的時間來學習Docker的工作原理,更確切地說,是關於Docker統一文件系統(the union file system)的知識,然後回過頭來再看Docker的命令,一切變得順理成章,簡單極了。題外話:就我個人而言,掌握一門技術併合理使用它的最好辦法就是深入理解這項技術背後的工作原理。
  • 宋寶華:Docker 最初的2小時(Docker從入門到入門)
    最初的2小時,你會愛上Docker,對原理和使用流程有個最基本的理解,避免滿世界無頭蒼蠅式找資料。
  • docker容器dockerfile詳解
    在這種情況下,如果<dest>以斜槓結尾/,它將被視為一個目錄,其內容<src>將被寫入<dest>/base(<src>)。•如果<src>直接指定了多個資源,或者由於使用了通配符,則<dest>必須是目錄,並且必須以斜槓結尾/。
  • 一鍵搭建深度學習平臺,基於Docker/Mesos和NVIDIA GPU詳細教程
    為了解決上述問題,一個更合理的思路是利用 Mesos 將 GPU 資源匯聚成資源池來實現資源共享,並借用 Docker 交付深度學習的 runtime 環境,很好的解決了上述問題。清華大學交叉信息研究院開放計算項目實驗室( OCP 實驗室)基於以上背景,與數人云合作解決深度學習環境部署繁瑣的問題,該平臺從 6 月份開始已經為清華大學的師生提供服務。
  • docker系列:docker安裝
    大家好~我是小方,歡迎大家關注「筍貨測試筆記」體完記得俾個「like」呀聊聊最近最近發生了一些事,整個事情經過有點像"劉邦剷除諸侯王,發配邊疆",好了不說了,咱們繼續學習吧,在"邊疆好好勞改學習",對了,公眾號也改名了,就叫筍貨測試筆記,希望能自己堅持初心,不管有沒有人看,繼續寫下去吧,就當成記錄一下自己~今天我們來學學docker的安裝吧,雙11的騰訊雲,快吃灰了,我的騰訊雲裝的是CentOS 7.6官方腳本自動安裝國內daocloud一鍵安裝
  • docker 門外初體驗——docker 安裝(一)
    二、安裝三、驗證四、總結前言重寫對docker的學習記錄,最主要的原因之一,花了大量的時間進行學習,形成一個從0至1的認識,但是工作中卻沒見有實際應用,導致所學的知識存活率很低,也為了豐富自身的技術體系一、docker是什麼?Docker 是一個開源的應用容器引擎。
  • 通過容器化一個Python Web應用學習Docker容器技術
    程序要想能運行起來,除了有我們自己編寫的業務代碼還要有依賴,還要藉助於作業系統,把代碼、依賴和作業系統打包在一起就是鏡像,鏡像中包含程序運行起來的所有要素,因此鏡像可以「Build Once,Run Anywhere」,能夠保證一致性。這是容器技術帶給我們的非常大的益處。
  • 這10張圖帶你深入理解Docker容器和鏡像
    於是,我花了幾周的時間來學習Docker的工作原理,更確切地說,是關於Docker統一文件系統(the union file system)的知識,然後回過頭來再看Docker的命令,一切變得順理成章,簡單極了。題外話:就我個人而言,掌握一門技術併合理使用它的最好辦法就是深入理解這項技術背後的工作原理。
  • Docker小白到實戰之Dockerfile解析及實戰演示,果然順手
    前言使用第三方鏡像肯定不是學習Docker的最終目的,最想要的還是自己構建鏡像;將自己的程序、文件、環境等構建成自己想要的應用鏡像,方便後續部署、啟動和維護;而Dockerfile就是專門做這個事的,通過類似簡單編碼的形式,最終就可以構建出屬於自己的鏡像,所以必須學起來。正文1.
  • 【長篇博文】Docker學習筆記與深度學習環境的搭建和部署(一)
    歡迎關注我的csdn:原始碼殺手docker學習筆記本文的最終目的是在docker下搭建深度學習環境,之前的所有操作是簡單對docker的一些實現流程進行記錄,不做更細緻的分析。以下是在搭建深度學習環境之前所做操作。
  • 學習Docker就應該掌握的dockerfile語法與指令
    以下是 Dockerfile 中一些常用欄位的含義:todo:下面命令太抽象,而且只是介紹,沒有demo,可以給每個命令引入demo,比如解釋 FROM ubuntu:16.04FROM:基礎鏡像,FROM 命令必須是 Dockerfile 的首個命令。LABEL:為鏡像生成元數據標籤信息。