看完這篇,Docker 你就入門了

在計算機技術日新月異的今天, Docker 在國內發展的如火如荼,特別是在一線互聯網公司,Docker 的使用是十分普遍的,在理解 docker 之前,我們先熟悉兩個概念,容器和虛擬機。

一、容器與虛擬機

傳統的虛擬機有 VMware, VirtualBox ,它們需要模擬整臺機器包括硬件,每臺虛擬機都需要有自己的操作系統,虛擬機一旦開啓,預分配給它們的資源將全部被佔用。每一臺虛擬機包括應用,必要的二進制和庫,以及一個完整的用戶操作系統。

而容器技術是和我們的宿主機共享硬件資源及操作系統,可以實現資源的動態分配。容器包含應用和其所有的依賴包,但是與其他容器共享內核。容器在宿主機操作系統中,在用戶控件以分離的進程運行。

容器技術是實現操作系統虛擬化的一種途徑,可以讓您在資源受到隔離的進程中運行應用程序及其依賴關係。通過使用容器,我們可以輕鬆打包應用程序的代碼、配置和依賴關係,將其編程容易使用的構建塊,從而實現環境一致性、運營效率、開發人員生產力和版本控制等諸多目標。容器幫助保證應用程序快速、可靠、一致性部署,其間不受部署環境的影響。容器還賦予我們對資源更多的精細化控制能力,讓我們的基礎設施效率更高、通過下面這張圖我們可以很直觀的反映出二者的區別。

Docker 屬於 Linux 容器的一種封裝,提供簡單易用的容器使用接口。它是目前最流行的 Linux 容器解決方案。

Linux 容器不是模擬一個完整的操作系統,而是對進程進行隔離,相當於在正常進程的外面套了一個保護層。對於容器裏面的進程來說,它接觸到的各種資源都是虛擬的,從而實現與底層系統的隔離。

Docker 將應用程序與該程序的依賴,打包在一個文件裏。運行這個文件,就會生成一個虛擬容器,程序在這個虛擬容器裏運行,就好像在真實的物理機上運行一樣,有了 Docker,就不用擔心環境問題。

總體來說,Docker 的接口相當簡單,用戶可以方便的創建和使用容器,把自己的應用放入容器,容器還可以進行版本管理,複製,分享,修改,就像管理代碼一樣。

二、Docker 的優勢

1、Docker 啓動快速,屬於秒級別。虛擬機通常需要幾分鐘去啓動。

2、Docker 需要的資源更少,Docker 在操作系統級別進行虛擬化,Docker 容器和內核交互,幾乎沒有性能損耗,性能優於通過 Hypervisor 層與內核層的虛擬化

3、Docker 更輕量,Docker 的架構可以共用一個內核與共享應用程序庫,所佔內存極小。同樣的硬件環境,Docker 運行的鏡像數遠低於虛擬機數量,對系統的利用率非常高

4、安全性, Docker 的安全性也更弱。Docker 的租戶 root 和宿主機 root 等同,一旦容器內的用戶從普通用戶權限提升爲 root 權限,它就直接具備了宿主機的 root 權限,進而可進行無限制的操作。虛擬機租戶 root 權限和宿主機的 root 虛擬機權限是分離的,並且虛擬機利用如 intel 的 vt-d 和 vt-x 的 ring-1 硬件隔離技術,這種隔離技術可以防止虛擬機突破和彼此交互,而容器至今還沒有任何形式的硬件隔離,這使得容器容易受到攻擊

5、可管理性:Docker 的集中化管理工具還不算成熟。各種虛擬化技術都有成熟的管理工具,例如 VMware Vcentor 提供完備的虛擬機管理能力

6、高可用和可恢復性:Docker 對業務的高可用支持是通過快速重新部署實現的。虛擬化具備負載均衡,高可用,容錯,遷移和數據保護等經過生產實踐檢驗的成熟保障機制,VMware 可承諾虛擬機 99.9999% 高可用,保證業務連續性

7、 交付、部署:虛擬機可以通過鏡像實現環境交付的一致性,但鏡像分發無法體系化。 Docker 在 Dockerfile 中記錄了容器構建過程,可在集羣中實現快速分發和快速部署

三、Docker 的三個基本概念

從上圖我們可以看到,Docker 中包括三個基本的概念:

1、鏡像是 Docker 運行容器的前提,倉庫是存放鏡像的場所,可見鏡像是 Docker 的核心。

那麼鏡像到底是什麼呢?

Docker 鏡像可以看作是一個特殊的文件系統,除了提供容器運行時所需的程序、庫、資源、配置等文件外,還包含了一些爲運行時準備的一些配置參數。鏡像不包含任何動態數據,其內容在構建之後也不會被改變。

2、Container (容器)

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

由於容器的定義並沒有提及是否要運行容器,所以實際上,容器 = 鏡像 + 讀寫層。

3、Repository(倉庫)

Docker 倉庫是集中存放鏡像文件的場所,鏡像構建完成後,可以很容易在當前宿主上運行,但是,如果需要在其他服務器上使用這個鏡像,我們需要一個集中的存儲、分發鏡像的服務,Docker Registry(倉庫註冊服務器) 就是這樣的服務。 有時候會把倉庫(Repository)和倉庫註冊服務器(Registry)混爲一談,並不嚴格區分。 實際上,一個 Docker Registry 中可以包含多個倉庫(Repository),每個倉庫可以包含多個標籤 ,每個標籤對應着一個鏡像。所以說,鏡像倉庫是 Docker 用來集中存放鏡像文件的地方類似於我們之前常用的代碼倉庫。

倉庫又可以分爲兩種形式:

(1)public(共有倉庫)

Docker Registry 公有倉庫是開放給用戶使用、允許用戶管理鏡像的 Registry 服務。一般這類公開服務允許用戶免費上傳、下載公開的鏡像,並可能提供收費服務供用戶管理私有鏡像。

(2)private(私有倉庫)

Docker 官方提供了 Docker Registry 鏡像,可以直接使用做爲私有 Registry 服務。當用戶創建了自己的鏡像之後就可以使用 push 命令將它上傳到公有或者私有倉庫,這樣下次在另外一臺機器上使用這個鏡像時候,只需要從倉庫上 pull 下來就可以了。

四、Docker 的架構

Docker 使用 C/S 架構,即客戶端 / 服務器體系結構。Docker 客戶端與 Docker 服務器進行交互,Docker 服務端負責構建、運行和分發 Docker 鏡像。Docker 客戶端與服務端可以運行在一臺機器上,也可以通過 RESTful、stock 或網絡接口與遠程 Docker 服務端進行通信。

這張圖展示了 Docker 客戶端、服務端和 Docker 倉庫(即 Docker Hub 和 Docker Cloud ),默認情況下 Docker 會在 Docker 中央倉庫尋找鏡像文件,這種利用倉庫管理鏡像的設計理念類似於 Git,當然這個倉庫是可以通過修改配置來指定的,甚至我們可以創建我們自己的私有倉庫。

Docker 採用的是 C/S 架構,客戶端向服務器發送請求,服務器負責構建、運行和分發容器。客戶端和服務器可以運行在同一個 Host 上,客戶端也可以通過 socket 或 REST API 與遠程的服務器通信。

1、Docker Client

Docker 客戶端其實就是 Docker 提供命令行界面工具,是許多 Docker 用戶與 Docker 進行交互的主要方式。客戶端可以構建、運行和停止應用程序,還可以遠程與 Docker_HOST 進行交互。 最常用的 Docker 客戶端就是 Docker 命令,我們可以通過 Docker 命令很方便地在 host 上構建和運行 Docker 容器。

2、Docker Daemon

Docker Daemon 是服務器組件,以 Linux 後臺服務的方式運行,是 Docker 最核心的後臺進程,我們也把它稱爲守護進程。它負責相應來自 Docker Client 的請求,然後將這些請求翻譯成系統調用完成容器管理操作。該進程會在後臺啓動一個 API Server,負責接收由 Docker Client 發送的請求,接收到的請求將通過 Docker Daemon 內部的一個路由分發調用,由具體的函數來執行請求。

Docker Daemon 的架構如下所示:

Docker Daemon 可以認爲是通過 Docker Server 模塊接受 Docker Client 的請求,並在 Engine 中處理請求,然後根據請求類型,創建出指定的 Job 並運行。Docker Daemon 運行在 Docker Host 上,負責創建、運行、監控容器,構建、存儲鏡像。

運行過程的作用有以下幾種可能:

由於 Docker Daemon 和 Docker Client 的啓動都是通過可執行文件 Docker 來完成的,因此兩者的啓動流程非常相似。Docker 可執行文件運行時,運行代碼通過不同的命令行 flag 參數,區分兩者,並最終運行兩者各自相應的部分。

啓動 Docker Daemon 時,一般可以使用一下命令來完成

1docker --daemon = truedocker –ddocker –d = true
2

再由 docker 的 main 函數來解析以上命令的相應的 flag 參數,並最終完成 Docker Daemon 的啓動。

Docker Daemon 的啓動流程:

默認配置下,  Docker Daemon 只能相應來自本地 host 的客戶端請求。如果要允許遠程客戶端請求,需要在配置文件中打開 TCP 監聽。我們可以照着如下步驟進行配置:

(1)編輯配置文件 /etc/systemd/system/multi-user.target.wants/docker.service ,在環境變量 ExecStart後面添加 -H tcp://0.0.0.0,允許來自任意 IP 的客戶端連接。

(2)重啓 Docker Daemon

1systemctl daemon-reloadsystemctl restart docker.service
2

(3)我們通過以下命令即可實現與遠程服務器通信

1docker -H 服務器IP地址 info
2

-H 是用來指定服務器主機,info 子命令用於查看 docker 服務器的信息

3、Docker Image

Docker 鏡像可以看作是一個特殊的文件系統,除了提供容器運行時所需的程序、庫、資源、配置等文件外,還包含了一些爲運行時準備的一些配置參數(如匿名卷、環境變量、用戶等)。鏡像不包含任何動態數據,其內容在構建之後也不會被改變。我們可將 Docker 鏡像看成只讀模板,通過它可以創建 Docker 容器。

鏡像有多種生成方法:

我們可以將鏡像的內容和創建步驟描述在一個文本文件中,這個文本文件稱作 Dockerfile,通過執行 docker build 命令可以構建出 docker 鏡像。

4、Docker Registry

Docker Registry 是存儲 Docker Image 的倉庫,它在 Docker 生態環境中的位置如下圖所示:

運行 Docker Push、Docker pull、Docker search 時,實際上是通過 Docker Daemon 與 Docker registry 通信。

5、Docker Container

Docker 容器就是 Docker 鏡像的運行實例,是真正運行項目程序、消耗系統資源、提供服務的地方。Docker  Container 提供了系統硬件環境,我們可以使用 Docker Image 這些製作好的系統盤,再加上我們編寫好的項目代碼,run 一下就可以提供服務了。

五、Docker 組件如何協作運行容器

容器啓動過程如下:

具體過程可以看如下這幅演示圖:

我們可以通過 Docker Image 可以查看到 hello-world 已經下載到本地

六、Docker 常用命令

我們可以通過 docker -h 去查看命令的詳細的幫助文檔。在這裏我只會講一些平常日常比賽或者生活中我們可能會用的比較多的一些命令。

例如,我們需要拉取一個 docker 鏡像,我們可以用如下命令:

1docker pull image_name
2

image_name 爲鏡像的名稱,而如果我們想從 Docker Hub 上去下載某個鏡像,我們可以使用以下命令:

1docker pull centos:latest
2

centos:lastest 是鏡像的名稱,Docker daemon 發現本地沒有我們需要的鏡像,會自動去 Docker Hub 上去下載鏡像,下載完成後,該鏡像被默認保存到 / var/lib/docker 目錄下。

接着我們如果想查看下主機下存在多少鏡像,我們可以用如下命令:

1docker images
2

我們要想知道當前有哪些容器在運行,我們可以用如下命令:

1docker ps -a
2

-a 是查看當前所有的容器,包括未運行的

我們該如何去對一個容器進行啓動,重啓和停止呢?我們可以用如下命令:

1docker start container_name/container_iddocker restart container_name/container_iddocker stop container_name/container_id
2

這個時候我們如果想進入到這個容器中,我們可以使用 attach 命令:

1docker attach container_name/container_id
2

那如果我們想運行這個容器中的鏡像的話,並且調用鏡像裏面的 bash,我們可以使用如下命令:

1docker run -t -i container_name/container_id /bin/bash
2

那如果這個時候,我們想刪除指定鏡像的話,由於 image 被某個 container 引用(拿來運行),如果不將這個引用的 container 銷燬(刪除),那 image 肯定是不能被刪除。我們首先得先去停止這個容器:

然後我們用如下命令去刪除這個容器:

1docker psdocker stop container_name/container_id
2

然後這個時候我們再去刪除這個鏡像:

1docker rmi image_name
2

此時,常用的 Docker 相關的命令就講到這裏爲止了,我們在後續的文章中還會反覆地提到這些命令。

七、Dockerfile

Dockerfile 是自動構建 docker 鏡像的配置文件,用戶可以使用 Dockerfile 快速創建自定義的鏡像,Dockerfile 中的命令非常類似於 Linux 下的 shell 命令。

我們可以通過下面這幅圖來直觀地感受下 Docker 鏡像、容器和 Dockerfile 三者之間的關係。

我們從上圖中可以看到,Dockerfile 可以自定義鏡像,通過 Docker 命令去運行鏡像,從而達到啓動容器的目的。

Dockerfile 是由一行行命令語句組成,並且支持已 #開頭的註釋行。

一般來說,我們可以將 Dockerfile 分爲四個部分:

下面是一段簡單的 Dockerfile 的例子:

1、從 Docker Hub 上 pull 下 python 2.7 的基礎鏡像

2、顯示維護者的信息

3、copy 當前目錄到容器中的 / app 目錄下 複製本地主機的 (Dockerfile 所在目錄的相對路徑) 到容器裏

4、指定工作路徑爲 / app

5、安裝依賴包

6、暴露 5000 端口

7、啓動 app

這個例子是啓動一個 Python flask app 的 Dockerfile(flask 是 Python 的一個輕量級的 web 框架),相信大家從這個例子中能夠稍微理解了 Dockerfile 的組成以及指令的編寫過程。

八、構建 Dockerfile 代碼實例

 1mkdir static_web
 2cd static_web
 3touch Dockerfile
 4然後 vi Dockerfile  開始編輯該文件
 5輸入 i 開始編輯
 6 
 7以下是我們構建的Dockerfile內容``````````FROM nginx
 8MAINTAINER Angel_Kitty <angelkitty6698@gmail.com>
 9RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html``````````
10 編輯完後 按 esc 退出編輯
11然後  :wq    寫入 退出
12

我們在 Dockerfile 文件所在目錄執行:

1docker build -t angelkitty/nginx_web:v1 .
2

我們解釋一下,-t 是爲新鏡像設置倉庫和名稱,其中 angelkitty 爲倉庫名,nginx_web 爲鏡像名,:v1 爲標籤(不添加爲默認 latest)

我們構建完成之後,使用 docker images 命令查看所有鏡像,如果存在 REPOSTORY 爲 nginx 和 TAG 是 v1 的信息,就表示構建成功。

接下來使用 docker run 命令來啓動容器

1docker run --name nginx_web -d -p 8080:80   angelkitty/nginx_web:v1
2

這條命令會用 nginx 鏡像啓動一個容器,命名爲 nginx_web,並且映射了 8080 端口,這樣我們可以用瀏覽器去訪問這個 nginx 服務器:http:localhost:8080 或者 http:// 本機的 IP 地址: 8080/,頁面返回信息:

這樣一個簡單使用 Dockerfile 構建鏡像,運行容器的示例就完成了!

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/_iqXyaFNIcEpmVDfw4Kxzw