部分内容參考連結:
- Docker實戰總結(非常全面,建議收藏)
一、 Docker概述
Docker是一個開源的應用容器引擎(基于Go語言開發),讓開發者可以打包他們的應用以及依賴包到一個可移植的容器中,然後釋出到任何流行的Linux機器上,也可以實作虛拟化,容器是完全使用沙箱機制,互相之間不會有任何接口。簡言之,就是可以在Linux上鏡像使用的這麼一個容器。
Docker可以在容器内部快速自動化部署應用,并可以通過核心虛拟化技術(namespaces及cgroups等)來提供容器的資源隔離與安全保障等。
Docker的思想來自于集裝箱,集裝箱解決了什麼問題?在一艘大船上,可以把貨物規整的擺放起來。并且各種各樣的貨物被集裝箱标準化了,集裝箱和集裝箱之間不會互相影響。那麼我就不需要專門運送水果的船和專門運送化學品的船了。隻要這些貨物在集裝箱裡封裝的好好的,那我就可以用一艘大船把他們都運走。
簡單的了解,docker就是一個軟體集裝箱化平台,就像船隻、火車、卡車運輸集裝箱而不論其内部的貨物一樣,軟體容器充當軟體部署的标準單元,其中可以包含不同的代碼和依賴項。
按照這種方式容器化軟體,開發人員和 IT 專業人員隻需進行極少修改或不修改,即可将其部署到不同的環境,如果出現的故障,也可以通過鏡像,快速恢複服務。
1.1 Docker的優勢
二、從容器化技術說起
2.1 背景
在虛拟機和雲計算較為成熟的時候,各家公司想在雲伺服器上部署應用,通常都是像部署實體機那樣使用腳本或手動部署,但由于本地環境和雲環境不一緻,往往會出現各種小問題。
這時候有個叫Paas的項目,就是專注于解決本地環境與雲端環境不一緻的問題,并且提供了應用托管的功能。簡單得說,就是在雲伺服器上部署Paas對應的服務端,然後本機就能一鍵push,将本地應用部署到雲端機器。然後由于雲伺服器上,一個Paas服務端,會接收多個使用者送出的應用,是以其底層提供了一套隔離機制,為每個送出的應用建立一個沙盒,每個沙盒之間彼此隔離,互不幹涉。
看看,這個沙盒是不是和docker很類似呢?實際上,容器技術并不是docker的專屬,docker隻是衆多實作容器技術中的一個而已。
2.2 docker實作原理
說起docker,很多人都會将它與虛拟機進行比較,
其中左邊是虛拟機的結構,右邊是docker容器的結構。
在虛拟機中,通過Hypervisor對硬體資源進行虛拟化,在這部分硬體資源上安裝作業系統,進而可以讓上層的虛拟機和底層的主控端互相隔離。
但docker是沒有這種功能的,我們在docker容器中看到的與主控端互相隔離的沙盒環境(檔案系統,資源,程序環境等),本質上是通過Linux的Namespace機制,CGroups(Control Groups)和Chroot等功能實作的。實際上Docker依舊是運作在主控端上的一個程序(程序組),隻是通過一些障眼法讓docker以為自己是一個獨立環境。
是以,容器=Cgroup+Namespace+rootfs+容器引擎(使用者态工具)
- Cgroup:資源控制。
- Namespace:通路隔離。
- rootfs:檔案系統隔離。
- 容器引擎:生命周期控制。
2.3 Cgroup
Cgroup是control group的簡寫,屬于Linux核心提供的一個特性,用于限制和隔離一組程序對系統資源的使用,也就是做資源QoS,這些資源主要包括CPU、記憶體、block I/O和網絡帶寬。
- devices:裝置權限控制。
- cpuset:配置設定指定的CPU和記憶體節點。
- cpu:控制CPU占用率。
- cpuacct:統計CPU使用情況。
- memory:限制記憶體的使用上限。
- freezer:當機(暫停)Cgroup中的程序。
- net_cls:配合tc(traffic controller)限制網絡帶寬。
- net_prio:設定程序的網絡流量優先級。
- huge_tlb:限制HugeTLB的使用。
- perf_event:允許Perf工具基于Cgroup分組做性能監測。
2.4 NameSpace
Namespace又稱為命名空間(也稱為名字空間),它是将核心的全局資源做封裝,使得每個Namespace都有一份獨立的資源,是以不同的程序在各自的Namespace内對同一種資源的使用不會互相幹擾。
- IPC:隔離System V IPC和POSIX消息隊列。
- Network:隔離網絡資源。
- Mount:隔離檔案系統挂載點。
- PID:隔離程序ID。
- UTS:隔離主機名和域名。
- User:隔離使用者ID群組ID。
2.5 徹底了解docker隔離機制
如果在一個docker容器裡面,使用ps指令檢視程序,可能隻會看到如下的輸出:
/ # ps
PID USER TIME COMMAND
1 root 0:00 /bin/bash
10 root 0:00 ps
在容器中執行ps,隻會看到1号程序/bin/bash和10号程序ps。前面有說到,docker容器本身隻是Linux中的一個程序(組),也就是說在主控端上,這個/bin/bash的pid可能是100或1000,那為什麼在docker裡面看到的這個/bin/bash程序的pid是1呢?答案是linux提供的Namespace機制,将/bin/bash這個程序的程序空間隔離開了。
具體的做法呢,就是在建立程序的時候添加一個可選的參數,比如下面這樣:
int pid = clone(main_function, stack_size, CLONE_NEWPID | SIGCHLD, NULL);
那樣後,建立的線程就會有一個新的命名空間,在這個命名空間中,它的pid就是1,當然在主控端的真實環境中,它的pid還是原來的值。
上面的這個例子,其實隻是pid Namespace(程序命名空間),除此之外,還有network Namespace(網絡命名空間),mount Namespace(檔案命名空間,就是将整個容器的根目錄root挂載到一個新的目錄中,然後在其中放入核心檔案看起來就像一個新的系統了)等,用以将整個容器和實際主控端隔離開來。而這其實也就是容器基礎的基礎實作了。
但是,上述各種Namespace其實還不夠,還有一個比較大的問題,那就是系統資源的隔離,比如要控制一個容器的CPU資源使用率,記憶體占用等,否則一個容器就吃盡系統資源,其他容器怎麼辦。
而Linux實作資源隔離的方法就是Cgroups。Cgroups主要是提供檔案接口,即通過修改 /sys/fs/cgroup/下面的檔案資訊,比如給出pid,CPU使用時間限制等就能限制一個容器所使用的資源。
是以,docker本身隻是linux中的一個程序,通過Namespace和cgroup将它隔離成一個個單獨的沙盒。明白這點,就會明白docker的一些特性,比如說太過依賴核心的程式在docker上可能執行會出問題,比如無法在低版本的主控端上安裝高本版的docker等,因為本質上還是執行在主控端的核心上。
三、Docker的核心:鏡像、容器、倉庫
3.1 鏡像
鏡像是一個可執行包,包含運作應用程式所需的所有内容——代碼、運作時、庫、環境變量和配置檔案。
3.2 容器
容器:
- 容器是通過運作鏡像啟動容器,是鏡像的運作時執行個體。鏡像實際上就是一個容器的模闆,通過這個模闆可以建立很多相同的容器。
- 容器就是一個認為隻有其本身在運作狀态的linux程式,隻服從使用者指定的指令。(容器程式有自己的IP位址;一個可通路網絡的獨立裝置)
通過Java去類比了解Docker的一些概念:
- Class檔案 - 相當于Docker鏡像,定義了類的一些所需要的資訊
- 對象 - 相當于容器,通過Class檔案建立出來的執行個體
- JVM - 相當于Docker引擎,可以讓Docker容器屏蔽底層複雜邏輯,實作跨平台操作
3.3 倉庫
存放鏡像的地方,和git倉庫類似。
四、Docker的安裝方式
4.1 方式一:yum方式安裝
# 更新yum源
yum update
# 安裝所需環境
yum install -y yum-utils device-mapper-persistent-data lvm2
# 配置yum倉庫
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
# 安裝Docker
yum install docker-ce
# 啟動Docker
systemctl start docker
systemctl enable docker
4.2 方式二:curl
curl -sSL https://get.daocloud.io/docker | sh
4.3 離線安裝
- 下載下傳docker的安裝檔案:https://download.docker.com/linux/static/stable/x86_64/
- 将下載下傳後的tgz檔案傳至伺服器,通過FTP工具上傳即可
- 解壓
tar -zxvf docker-19.03.8-ce.tgz
- 将解壓出來的docker檔案複制到 /usr/bin/ 目錄下:
cp docker/* /usr/bin/
- 進入/etc/systemd/system/目錄,并建立docker.service檔案
[root@localhost java]# cd /etc/systemd/system/
[root@localhost system]# touch docker.service
- 打開docker.service檔案,将以下内容複制
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service
Wants=network-online.target
[Service]
Type=notify
# the default is not to use systemd for cgroups because the delegate issues still
# exists and systemd currently does not support the cgroup feature set required
# for containers run by docker
ExecStart=/usr/bin/dockerd --selinux-enabled=false --insecure-registry=192.168.200.128
ExecReload=/bin/kill -s HUP $MAINPID
# Having non-zero Limit*s causes performance problems due to accounting overhead
# in the kernel. We recommend using cgroups to do container-local accounting.
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
# Uncomment TasksMax if your systemd version supports it.
# Only systemd 226 and above support this version.
#TasksMax=infinity
TimeoutStartSec=0
# set delegate yes so that systemd does not reset the cgroups of docker containers
Delegate=yes
# kill only the docker process, not all processes in the cgroup
KillMode=process
# restart the docker process if it exits prematurely
Restart=on-failure
StartLimitBurst=3
StartLimitInterval=60s
[Install]
WantedBy=multi-user.target
- 給docker.service檔案添加執行權限:
chmod 777 /etc/systemd/system/docker.service
- 重新加載配置檔案:
systemctl daemon-reload
- 啟動Docker
systemctl start docker
- 設定開機啟動:
systemctl enable docker.service
- 檢視Docker狀态:
systemctl status docker
如出現如圖界面,則表示安裝成功!
五、Docker思維導圖總結
思維導圖下載下傳連結:
Docker思維導圖下載下傳