Docker從入門到實戰(一)

一步一步走,寫小白都能看懂的文章,將持續更新中,敬請期待!linux

Docker從入門到實戰(一)

一:容器技術與Docker概念

1 什麼是容器

容器技術並非一個全新的概念,它又稱爲容器虛擬化。虛擬化技術目前主要有硬件虛擬化、半虛擬化、操做系統虛擬化等。
1.1關於虛擬化
虛擬化技術的分類與定義在不一樣領域有不一樣的理解。對於計算機領域,虛擬化技術主要分爲兩大類:一類基於硬件虛擬化,另外一類基於軟件虛擬化。硬件虛擬化並很少見,大都是半虛擬化與軟件結合,應用較爲普遍的則是基於軟件的虛擬化技術。
基於軟件虛擬化又可分爲應用虛擬化(如Wine)和平臺虛擬化(如虛擬機),容器技術屬於操做系統虛擬化,屬於平臺虛擬化的一種。
Docker從入門到實戰(一)
1.2容器的定義
所謂容器,顧名思義就是來放東西的道具。在剛進入國內時,還有一段時間在討論Container這個單詞翻譯爲「容器合適」,仍是翻譯爲「集裝箱」合適。大可把容器理解爲一個沙盒,每一個容器是獨立的,容器間能夠相互通訊。docker

2 容器的前世此生

若是說工業上的集裝箱是從一個箱子開始的,那麼軟件行業的容器則是從文件系統隔離開始的。
2015年微軟公司也在Windows Server上爲其基於Windows的應用添加了容器支持,稱之爲Windows Containers,與Windows Server 2016一同發佈,經過該實現,Docker能夠原生的在Windows上運行Docker容器,而不須要再啓動一個虛擬機來運行Docker(Windows上早期運行Docker須要使用Linux虛擬機)。同年,MacOS也原生支持運行Docker容器。centos

3 容器的原理

容器本質上是宿主機上的進程。容器技術經過namespace實現資源隔離,經過Cgroups(Google公司的Control Groups技術,2007年被合併到Linux2.6.24內核中)實現資源控制,經過rootfs實現文件系統隔離,再加上容器搜索引擎自身的特性來管理容器的生命週期。
3.1認識namespace
在分佈式的環境下,容器必需要有獨立的IP、端口和路由等,天然就有了網絡隔離。同時,進程通訊隔離、權限隔離等也要考慮到,所以基本上一個容器須要作到6項基本隔離。
Docker從入門到實戰(一)
對namespace的操做主要經過clone(),setns(),unshare()這三個系統調用來完成的。
3.1.1查看當前的namespance
root用戶:ls -l /proc/$$/ns
Docker從入門到實戰(一)
這裏$$指的是當前進程ID號,能夠看到4026531839這樣的數字,表示當前進程指向的namespace.當兩個進程指向同一串數字時,表示他們處於同一個namespace下。
3.1.2使用clone()建立新的namespace
建立一個namespace的方法是使用clone()系統調用,它會建立一個新的進程。爲了說明建立的過程,給出clone()的原型以下:
int clone (int(child_func) (void ) , void child_stack, int flags , voidarg) ;
若是調用clone()時設置了一個CLONE_NEW的標誌,一個與之對應的新的命名空間將被建立,新的進程屬於該命名空間,可使用多個CLONE_NEW標誌的組合。
3.1.3使用一個sents()關聯一個已經存在namespace
當一個namespace沒有進程時還保持打開,這麼作是爲了後續添加進程到該namesapce.而添加這個功能就是使用sents()系統調用來完成,這使得調用的進程可以和namespace關聯,docker exec 就須要用到這個方法:
int setns (int fd, int nstyps);
fd參數指明瞭關聯的namespace,其指向了\proc\PID\ns目錄系一個符號鏈接的文件描述符。能夠經過發開這些符號連接指向的文件或者打開一個綁定到符號連接的文件來得到文件描述符。
nstype參數運行調用者檢查fd指向的命名空間的類型,若是這個參數等於數,將不會檢查,當調用者已經知道namespace的類型時這會頗有用。當nstype被賦值爲CLONE_NEW*的常量時,內核會檢查fd指向的namespace的類型。
要把namespace利用起來,還要使用execve()函數(或者其餘的exec()函數),使得咱們可以構建一個簡單可是有用的工具,該函數能夠執行用戶命令。
3.1.4使用unshare()在已有進程上進行namespace隔離
unshare()和clone()有些像,不一樣的地方是前者運行在原有進程上,至關於跳出原來namespace操做,Linux自帶的unshare()就是經過調用unshare()這個API來實現。
[root@VM_110_98_centos ~]# unshare --help
Usage:
unshare [options] <program> [<argument>...]bash

Run a program with some namespaces unshared from the parent.markdown

Options:
-m, --mount unshare mounts namespace
-u, --uts unshare UTS namespace (hostname etc)
-i, --ipc unshare System V IPC namespace
-n, --net unshare network namespace
-p, --pid unshare pid namespace
-U, --user unshare user namespace
-f, --fork fork before launching <program>
--mount-proc[=<dir>] mount proc filesystem first (implies --mount)
-r, --map-root-user map current user to root (implies --user)
--propagation <slave|shared|private|unchanged>
modify mount propagation in mount namespace
-s, --setgroups allow|deny control the setgroups syscall in user namespaces網絡

-h, --help display this help and exit
-V, --version output version information and exit分佈式

For more details see unshare(1).
因爲docker沒有使用這個系統調用,因此不展開。
3.2 認識Cgroups
Cgroups是linux內核提供的一種能夠限制、記錄、隔離進程組(process groups)所使用的物理資源(如CPU,內存,I/O等)的機制。最初由Google公司的工程師提出看,後來被整合經linux內核。
這麼說理解起來有點吃力,咱們經過命令來掛載cgroupfs
提示已經掛載,這個動做通常狀況下已經在linux啓動的時候作了。
Docker從入門到實戰(一)
在主流linux發行版下,均可以經過/etc/cgconfig.conf或者cgroup-bin的相關指令來配置Cgroups。
mount {
cpuset = /sys/fs/cgroup/cpuset;
momory = /sys/fs/cgroup/momory;
}
group cnsworder/test {
perm {
task {
uid = root;
gid = root;
}
admin {
uid = root;
gid = root;
}
}
cpu {
cpu.shares = 1000;
}
}
而後經過命令行把一個進程移動到這個Cgroups之中。
#mount -t group -o cpu cpu /sys/fs/cgroup/cpuset
#cgcreate -g cpu,momory:/cnsworder
#chown root:root /sys/fs/cgroup/cpuset/cnsworder/test/*
#chown root:root /sys/fs/cgroup/cpuset/cnsworder/test/task
#cgrun -g cpu,momory:/cnsworder/test bash
3.3容器的建立
3.3.1系統調用clone()建立新進程,擁有本身的namespace
該進程擁有本身的pid,mount,user,net,ipc和uts namespace。
#pid =clone(fun,stack,flags,clone_arg);
3.3.2將pid寫入Cgroup子系統這樣就受到Cgroups子系統控制
#echo$pid >/sys/fs/cgroup/cpu/tasks
#echo$pid >/sys/fs/cgroup/cpuset/tasks
#echo$pid >/sys/fs/cgroup/bikio/tasks
#echo$pid >/sys/fs/cgroup/memory/tasks
#echo$pid >/sys/fs/cgroup/devices/tasks
#echo$pid >/sys/fs/cgroup/feezer/tasks
3.3.3經過pivot_root系統調用,使進程進入一個新的rootfs,以後經過exec()系統調用,在新的namespace,Cgroups,rootfs中執行/bin/bash.
fun () {
pivot_root ("path_of_rootfs/", path);
exec ("/bin/bash");
}
經過上面的操做,成功的在一個容器中運行了/bin/bash。
3.4 容器雲
雖然Docker提供了較爲便捷的操做方式,可是在開發、生產環境中網路、存儲、集羣和高可用等問題層出不窮。僅憑Docker是沒法作到面面俱到,因而就從容器到容器雲就成了容器技術的 必然發展途徑。
完整來講,容器雲是以容器爲資源分割和調度的基本單位,經過容器封裝軟件運行環境,爲用戶提供一個集構建,發佈和運行於一體的分佈式應用平臺。它與IaaS(Platform as a Service,也就是平臺即服務)、PaaS等不一樣,容器雲能夠共享與隔離資源、編排與部署容器。在這點上容器雲與IaaS類似。可是容器雲也能夠***到應用支撐與運行時環境,在這一點上與PaaS 相似。ide

文中全部內容皆爲手動敲出來的,不免有疏忽之處,歡迎評論指正!
後續文檔Docker從入門到實戰(二)連接 https://blog.51cto.com/12943999/2072592
函數

相關文章
相關標籤/搜索