Docker 容器概念

容器技術的火熱, 必將爲線上服務運維方式帶來變革。中間件集羣管理的目標是使中間件運維更輕、更快、更穩定、更簡易, docker 容器技術即是咱們實現這一目標的有力工具。這一節咱們先來介紹 docker 容器概念及其優點。linux

不玩虛的, 固然更暢快

docker 與虛擬機(vm)對比:docker

lark_01_vm_vs_dockerlark_01_vm_vs_dockershell

  1. 虛擬機運行在虛擬硬件上, 應用運行在虛擬機內核上。而 docker daemon 是宿主機上的一個進程, 應用只是 docker daemon 的一個子進程, 換句話說, 應用直接運行在宿主機內核上。ubuntu

  2. 虛擬機須要特殊硬件虛擬化技術支持, 於是只能運行在物理機上。docker 沒有硬件虛擬化, 於是能夠運行在物理機、虛擬機, 甚至 docker 容器內(嵌套運行)。bash

  3. 由於沒有硬件虛擬化及多運行一個 Linux 內核的開銷, 應用運行在 docker 上比虛擬機上更輕、更快。網絡

那麼, 使用 docker 和直接在宿主機上運行一個程序有什麼區別呢?答案是 docker 容器使用 cgroup 名字空間實現了 CPU, 內存, 網絡, 文件系統等資源隔離。瞭解 chroot 的同窗能夠認爲 docker 就是一個更優雅的 chroot。app

說到隔離, docker 容器的文件系統在哪裏呢? 答案就是鏡像。運維

docker 鏡像

鏡像描述了 docker 容器運行的初始文件系統, 包含運行應用所需的全部依賴。便可以是一個完整的操做系統, 也能夠僅包含應用所需的最小 bin/lib 文件集合。ide

一個問題: 假設一個 docker 容器文件系統大小爲 10GiB, 建立 10 個容器須要多少磁盤空間?
100 GiB?錯,仍是隻要 10 GiB!由於 docker 鏡像和容器採用分層文件系統結構, 每一個容器包含一層薄薄的可寫層, 只讀部分是共享的。微服務

docker 鏡像存儲引擎有 aufs, devicemapper, overlay 等多種實現, 請看 devicemapper 實現示意圖以下:

lark_01_dm_containerlark_01_dm_container

鏡像是隻讀的, 建立容器時只是在鏡像上面新建一個可寫層, 不須要複製整個文件系統, 於是能夠實現毫秒級建立。

鏡像存儲在鏡像 hub。每一個鏡像有一個 tag, 如 registry.hub.docker.com/library/ubuntu:14.04。鏡像完整 tag 不只包含鏡像名字, 還指明瞭鏡像從哪裏來, 要到哪裏去, 就像一個 URL。沒錯, registry.hub.docker.com 就是官方 docker 鏡像 hub 的地址。使用官方 library 鏡像時, 可省略前綴, 如以上鏡像 tag 可簡寫爲 ubuntu:14.04

docker 爲運行應用而生

有了鏡像,如何建立容器?docker 不加載 kernel (不一樣於 vm), 也不執行 init (不一樣於 vm 和 lxc)。「你不執行應用, 空跑一個 kernel 或者 init 有什麼意義?」,docker 說。docker 容器爲運行應用而生, 要建立 docker 容器, 必須指定鏡像 tag 和啓動應用的命令行 (或者鏡像設置了默認命令行)。

so, 建立一個 docker 容器的命令行以下:

sudo docker create -ti --name test ubuntu:14.04 bash

這只是建立了容器, 尚未運行, 要運行容器, 執行:

sudo docker start test

一般咱們把這兩條命令合併成一條, 即 docker run:

sudo docker run -dti --name test ubuntu:14.04 bash

在宿主機上看一下咱們剛剛運行的 bash 命令的進程樹:

$pstree -sa 21811
systemd --switched-root --system --deserialize 21
  └─docker daemon ... ...
      └─bash

沒錯, 它只是 docker daemon 的一個子進程.

應用即 docker 主進程

attach 到容器內的應用, 本例中即爲 bash 命令行:

sudo docker attach test

ps -ef 看一下:

$sudo docker attach test

root@47c90c3dcbfa:/# ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 17:05 ?        00:00:00 bash
root        18     1  0 17:11 ?        00:00:00 ps -ef

加上 ps 本身, 容器中只有兩個進程。 bash 在容器內 PID 爲 1, 便是容器主進程。主進程退出後, 容器即自動退出。仍是那句話, 容器爲運行應用而生, 應用都退出了, 容器留着還有什麼用。

手動中止容器:

sudo docker stop test

刪除容器:

sudo docker rm test

注意: 刪除容器後在鏡像上建立的可寫層文件系統也將被刪除, 因此日誌、配置、數據等須要持久保存的文件須要掛接到外部儲存。

docker 有多輕

俗話說前人栽樹, 後人乘涼, 咱們一般是基於一個已有的鏡像建立應用鏡像。爲了演示鏡像有多輕,咱們能夠從 0 開始建立一個鏡像。

建立一個文件夾 hello-lark, 進入文件夾, 添加一個 Dockerfile 內容以下:

FROM scratch
COPY Dockerfile hello.c hello /

Dockerfile 描述如何建立鏡像:

  • FROM scratch 表示從 0 開始, 即從一個空白文件系統開始建立鏡像。
  • COPY Dockerfile hello.c hello / 表示將本地 Dockerfilehello.chello 3 個文件複製到鏡像內根目錄下。

hello.c 和 hello 是咱們的應用源碼及編譯後的二進制文件。
添加 hello.c 文件內容以下:

#include <stdio.h>

int main(int argc, char* argv[]) {
  printf("Hello, Lark!\n");
  return 0;
}

靜態編譯之:

gcc -static hello.c -o hello

執行 docker build 建立鏡像:

$sudo docker build -t hello-lark:1.0 .
Sending build context to Docker daemon 881.2 kB
Step 1 : FROM scratch
 ---> 
Step 2 : COPY Dockerfile hello.c hello /
 ---> b52b3bd2799c
Removing intermediate container bc5dcd332026
Successfully built b52b3bd2799c

鏡像在本地倉庫打包和存儲, 不能直接看到實體文件。可是能夠導出爲一個 tar 包:

sudo docker save -o ../hello-lark.tar hello-lark:1.0

看看有多大:

$ll -h ../hello-lark.tar 
-rw-r--r-- 1 root root 870K Apr 12 13:41 ../hello-lark.tar

僅有 870K, 差很少就是 hello 這個二進制文件的大小。

docker 有多快

這個鏡像能跑嗎?咱們立刻運行看看:

$time sudo docker run --name hello --rm hello-lark:1.0 /hello
Hello, Lark!

real  0m0.486s
user  0m0.078s
sys 0m0.016s

可看到, 這條命令一共經歷了容器建立、運行、中止、銷燬 4 個過程,共耗時不到 0.5 秒。--rm 表示容器結束後自動刪除容器。

若是隻是建立:

$time sudo docker create --name hello hello-lark:1.0 /hello
16449a07a0f1377336a879f8136ec7369e07520da1f4a7516128b8d3ba314008

real  0m0.075s
user  0m0.064s
sys 0m0.017s

不到 0.1 秒。毫秒級建立絕非虛言。

固然, 只是 hello world 並無什麼用, 咱們打一個 busybox 進去, 鏡像大小隻有 2MB, 然而已經具有一個基本的 linux shell 環境.

sudo docker run -ti --rm lark-box:1.0 sh

docker 的好處

簡單說: 標準化交付,微服務編排,提高資源利用率

  1. 校準化交付

    docker 將應用及其全部依賴打包到鏡像內, 包括二進制文件(包括底層基礎庫), 靜態配置文件, 環境變量等。剝離了應用對操做系統和環境的依賴, 鬆耦合 。只須要拉取鏡像, 啓動容器便可完成應用部署, 方便 。毫秒級建立銷燬容器,從而能夠實現 快速部署、快速遷移、快速擴容縮容,一鍵快速回滾 (只依賴應用啓動時間)。docker 鏡像制定了應用交付標準, 開發人員對應用及其運行環境徹底可控,並 有效避免各類環境問題踩坑

  2. 微服務編排

    單機部署多應用時,應用之間徹底解耦,能夠任意部署編排, 完美支持微服務編排的需求。多個 C 應用混布時, docker 化實現 C 依賴隔離, 避免依賴衝突。

  3. 提高資源利用率

    docker 是輕量級的解決方案, 不作虛擬化, 不運行多餘的 kernel 和 init 進程, 能有效提高資源利用率。

相關文章
相關標籤/搜索