天天看點

【菜菜的CV進階之路-GPU伺服器使用-Docker環境配置-七】Docker 底層原理初探第07課:Docker 底層原理初探

第07課:Docker 底層原理初探

      • Docker 究竟做了什麼?
      • Docker 的 C/S 模型
      • 網絡
      • 程序和控制組
      • 分層存儲
      • 接下來做什麼?
本文主要簡單講解 Docker 底層原理,包括控制組,命名空間和分層存儲。

Docker 究竟做了什麼?

為了了解 Docker 幫助我們做了什麼,我們先來看看 Linux 核心做了什麼。簡單來說,Linux 核心做了下面幾件事:

  • 對來自硬體的消息作出響應;
  • 啟動和規劃程式的運作;
  • 控制群組織存儲;
  • 在程式之間傳遞消息;
  • 配置設定資源——記憶體,CPU,網絡等;

Docker 做的也是這些事情:

Docker 是一個 Go 語言開發的程式,它利用了 Linux 核心的一些特性,比如控制組,命名空間等技術來為容器提供隔離,讓容器看起來就是一個獨立的系統。這些技術并不是 Docker 的原創,在 Docker 之前這些技術就已經存在了,不過除非你是 Linux 專家,否則很難完美地使用這些特性。Docker 的出現讓這一切變得優雅又簡單,你可以很友善地在自己的電腦使用 Docker 部署容器!

本文接下來的内容會比較詳細地介紹一下這些 Docker 背後的技術,了解一下原理有助于大家對 Docker 有一個更加深刻的認識。讓我們開始吧!

Docker 的 C/S 模型

Docker 采用了 C/S 架構,包括用戶端(Client)和服務端(Server),服務端通過 socket 接受來自用戶端的請求,這些請求可以是建立鏡像,運作容器,終止容器等等。

【菜菜的CV進階之路-GPU伺服器使用-Docker環境配置-七】Docker 底層原理初探第07課:Docker 底層原理初探

服務端既可以運作在本地主機,也可以運作在遠端伺服器或者雲端,隻要你可以通路 Docker 的服務端,你甚至可以在容器裡運作容器。現在,我們來看看在 Docker 容器裡運作 Docker 容器的例子:

【菜菜的CV進階之路-GPU伺服器使用-Docker環境配置-七】Docker 底層原理初探第07課:Docker 底層原理初探

Docker 官方有一個名為“docker”的鏡像,使用這個鏡像運作容器的話,就可以在容器裡運作 Docker 指令。現在,我們讓用戶端運作在這個容器裡面,服務端運作在宿主主機,是以需要把宿主主機的“/var/run/docker.sock”挂載到容器裡的“/var/run/docker.sock”:

sudo docker run --rm -ti -v /var/run/docker.sock:/var/run/docker.sock docker sh
           

然後,我們可以在這個容器裡運作 Docker 指令:

【菜菜的CV進階之路-GPU伺服器使用-Docker環境配置-七】Docker 底層原理初探第07課:Docker 底層原理初探

你可以看到,“net:v1.0” 本是我們自定義的鏡像,存儲在宿主主機裡,之是以我們在容器裡可以從這個鏡像運作容器,是因為我們可以通路宿主主機的 Docker 服務端。是以隻要我們可以通路宿主主機的 Docker 服務端,我們就可以從服務端存在的鏡像運作容器。

總之,隻要了解:Docker是C/S架構就可以了!

網絡

在深入講解 Docker 網絡原理之前,不得不簡單提一下網絡有關的知識:

  • Ethernet(以太網):通過有線或者無線傳遞“幀”(frame)
  • IP Layer:在區域網路内傳遞資料包
  • Routing(路由):在不同網絡之間傳遞資料包
  • Ports(端口):尋址一台主機的特定程式,這裡指的是某些程式監聽某些端口

其實在之前學習 Docker 網絡操作部分的時候,我們已經介紹過 Docker 網絡的一些原理了。Docker 并不是像變魔術一樣直接在容器之間傳遞包,而是運作的時候會自動在宿主主機上建立一個名為 docker0 的虛拟網橋,它就像軟體交換機一樣,在挂載到它的網口之間進行消息轉發。運作一個 Docker 容器時,會建立 veth 對(Virtual Ethernet Pair)接口,這對接口一端在容器内,另一端挂載到 Docker 的網橋(預設 docker0,或者使用-- net 參數指定網絡)。veth 總是成對出現,并且從一端進入的資料會從另一端流出,這樣就可以實作挂載到同一網橋的容器間通信。

【菜菜的CV進階之路-GPU伺服器使用-Docker環境配置-七】Docker 底層原理初探第07課:Docker 底層原理初探

之前在學習 Docker 端口映射的時候,使用 -p 參數将宿主主機的端口映射到容器内部,這個過程用到了 Linux 的防火牆指令 iptable,iptable 會建立映射規則。現在,我們的主機上沒有運作任何容器,讓我們看看目前的端口映射規則:

sudo iptables -n -L -t nat
           
【菜菜的CV進階之路-GPU伺服器使用-Docker環境配置-七】Docker 底層原理初探第07課:Docker 底層原理初探

現在,運作一個容器,映射主控端的8080端口:

sudo docker run --rm -p 8080:8080 -ti net:v1.0 bash
           

現在,再來看看端口映射情況:

【菜菜的CV進階之路-GPU伺服器使用-Docker環境配置-七】Docker 底層原理初探第07課:Docker 底層原理初探

可以從最後一行看到我們的映射規則“tcp dpt:8080 to 172.17.0.2:8080”。

程序和控制組

先來簡單描述一下 Linux 程序有關知識。

Linux 的程序都是來自一個父程序,是以程序之間是父子關系。當一個子程序結束的時候,會傳回一個退出代碼給父程序。在衆多程序中,有一個程序是特殊的,它就是初始化程序(init),程序号為0,這個程序負責啟動所有其它程序。

使用 Docker 運作容器時,容器啟動的時候也有一個初始化程序,當這個程序終止的時候,對應的容器也就終止了。下面以一個具體例子加深了解:

首先,運作一個容器:

sudo docker run --name process --rm -ti ubuntu:16.04 bash
           

然後,檢視容器程序号:

sudo docker inspect --format '{{.State.Pid}}' process
           

在我的電腦上結果是:

【菜菜的CV進階之路-GPU伺服器使用-Docker環境配置-七】Docker 底層原理初探第07課:Docker 底層原理初探

然後使用"kill 23483"指令,發現容器退出。

并且,Docker 使用 Linux 控制組(cgroup, control group) 來對容器程序進行隔離。cgroup 是 Linux 核心的特性之一,它保證所有在一個控制組内的程序組成一個私密的、隔離的空間。控制組内的程序有自己的程序号,并且無法通路所在控制組之外的程序。是以控制組可以把你的系統中的程序劃分為若幹互相隔離的區域,并且控制組内的父程序衍生的子程序依舊在這個控制組内。Docker 正是利用這個特性實作容器間程序隔離。同時,控制組還提供了資源限制,資源審計等功能,這些在 Docker 裡都有所展現。

分層存儲

在學習編寫 Dockerfile 的部分,我們已經詳細介紹過了 Docker 的分層存儲架構,是以如果忘記了,請傳回去複習相關内容。

接下來做什麼?

本文主要簡單介紹了 Docker 的底層原理。下一篇文章将會介紹一下如何使用 Docker 配置一個公用的 GPU 深度學習伺服器。在配置 GPU 深度學習伺服器的過程中,其實我們是把容器當成虛拟機來用了,縱然這樣做有悖于 Docker 哲學,但是對初學者卻是一個很好的系統複習之前學到的知識的例子。