目錄
- 1.docker發展歷史
- 2.docker基礎用法
- 3.docker存盤驅動
1.docker發展歷史
1979年:Unix V7
這個年代,計算資源匱乏,想要通過快速銷毀和重建基礎設施來解決測驗環境污染問題變得幾乎不可能,為隔離出可供軟體進行構建和測驗的環境,chroot(change root)系統呼叫程式橫空出現,
在1979年Unix V7的開發程序中,正式引入chroot系統呼叫,為每個行程提供一個獨立的磁盤空間,將一個行程及其子行程的根目錄改變到檔案系統中的新位置,讓這些行程只能訪問到該目錄,這個被隔離出來的新環境被叫做 Chroot Jail,這標志著行程隔離的開始,隔離每個行程的檔案訪問權限,
2000年:FreeBSD Jails
2000年,FreeBSD作業系統正式發布FreeBSD jails隔離環境,真正意義上實作行程的沙箱化,這為檔案系統、用戶、網路等隔離增加了行程沙盒功能,實作了客戶服務之間的隔離和管理,
據悉,這種沙箱的實作,依靠作業系統級別的隔離與限制能力而非硬體虛擬化技術,FreeBSD Jails允許管理員將FreeBSD計算機系統劃分為幾個獨立的、較小的系統,稱為“ jails”,并能為每個系統和配置分配IP地址,可以對軟體的安裝和配置進行定制,
2001年:LinuxVServer
與FreeBSD Jails一樣,Linux VServer也是采取一種類似的上述Jails機制,它可以對計算機系統上的資源(檔案系統、網路地址、記憶體)進行磁區,每個所劃分的區域叫做一個安全背景關系(security context),其中的虛擬系統叫做虛擬私有服務器(virtual private server,VPS),該作業系統虛擬化于2001年推出,通過修補Linux內核來實作,測驗性補丁目前仍然可用,但最后一個穩定的修補程式是2006年發布,
2004年:Solaris容器
2004年2月,Oracle發布Oracle Solaris Containers,這是一個用于X86和SPARC處理器的Linux-Vserver版本,Solaris Container 是由系統資源控制和通過 zones 提供的邊界分離(boundary separation)所組合而成的,zones 是一個單一作業系統實體中的完全隔離的虛擬服務器,
2005年:Open VZ(Open Virtuzzo)
這是Linux作業系統級虛擬化技術,它通過Linux內核補丁形式進行虛擬化、隔離、資源管理和狀態檢查,
作業系統級虛擬化有一些限制,因為容器共享相同的體系結構和內核版本,當客戶需要不同于主機的內核版本情況下,這種缺點就會顯現出來,該代碼未作為正式Linux內核的一部分發布,每個 OpenVZ 容器都有一套隔離的檔案系統、用戶、用戶組、行程樹、網路、設備和 IPC 物件,
2006年:Process Containers
Process Containers(由Google在2006年推出)旨在用于限制、計算和隔離一系列流程的資源使用(CPU、記憶體、磁盤I / O、網路),
一年后,為了避免和 Linux 內核背景關系中的“容器”一詞混淆而改名為 ControlGroups簡稱Cgroups,并最終合并到Linux內核2.6.24中,
這也可以說明 Google 很早就參與了容器技術的開發,
2008年:LXC
Linux容器(LXC)是第一個、最完整的Linux容器管理器的實作方案,2008年,通過將 Cgroups 的資源管理能力和 Linux Namespace 的視圖隔離能力組合在一起,LXC完整的容器技術出現在Linux 內核中,并且可以在單個Linux內核上運行而無需任何補丁,
LXC 存在于 liblxc 庫中,提供各種編程語言的 API 實作,包括 Python3、Python2、Lua、Go、Ruby 和 Haskell,現在 LXC project 由 Canonical 公司贊助并托管的,
2011年:Warden
Warden由CloudFoundry在2011年成立,這是一個管理隔離、短暫存在和被資源控制的環境的API,在其第一個版本中,Warden使用LXC,之后替換為他們自己的實作方案,
不像 LXC,Warden 并不緊密耦合到 Linux 上,可以為任何系統提供隔離運行環境,Warden以后臺保護程式運行,而且能提供用于容器管理的API,它開發了一個CS(客戶端-服務端)模型來管理跨多個主機的容器集群,并且Warden提供用于管理cgroup、名稱空間和行程生命周期的相關服務,
2013年:LMCTFY
LMCTFY 是2013年Google容器技術的開源版本,它提供Linux應用程式容器,旨在提供性能可保證的、高資源利用率的、資源共享的、可超售的、接近零消耗的容器,
2015年,Google開始向由Docker發起的Libcontainer貢獻LMCTFY核心概念后,LMCTFY在2015年主動停止部署,Libcontainer現在是Open Container Foundation(開放容器基金會)的一部分,
2013年:Docker
2013年,隨著Docker的出現,容器開始迅速普及,
它最初是一個叫做 dotCloud 的 PaaS 服務公司的內部專案,后來該公司改名為 Docker,Docker的迅速普及并非偶然,它引入了一整套管理容器的生態系統,包括高效、分層的容器鏡像模型、全域和本地的容器注冊庫、清晰的REST API、命令列等, 與Warden一樣,Docker最初階段使用的也是LXC,后來用自己的庫libcontainer進行替換,Docker 推動實作了一個叫做 Docker Swarm 的容器集群管理方案
2014年:Rocket
Rocket 是由 CoreOS 所啟動的專案,類似于 Docker,但是其修復了一些 Docker 中發現的問題,
CoreOS的初衷是旨在提供一個比 Docker 更嚴格的安全性和產品需求,更重要的是,它是在一個更加開放的標準 AppContainer 規范上實作的,在 Rocket 之外,CoreOS也開發了其它幾個可用于 Docker 和 Kubernetes容器相關的產品,例如,CoreOS 作業系統、etcd 和flannel,
2016年:Windows Containers
2015 年,微軟在 Windows Server 上為基于 Windows 的應用添加了容器支持,稱之為 Windows Containers,它與 Windows Server 2016 一同發布,Docker 可以原生地在 Windows 上運行 Docker 容器,而不需要啟動一個虛擬機來運行 Docker( Windows 上早期運行 Docker 需要使用 Linux 虛擬機),
2017年:容器工具日趨成熟
在2017年以前,市場上已經有上百種工具用來管理容器,這些型別的工具已存在多年,
但是,2017年許多工具脫穎而出,最知名的是Kubernetes,自從2016年被納入CNCF以來,VMWare、Azure、AWS甚至Docker都宣布在其基礎架構上提供相關支持,
隨著容器市場的發展,一些工具已經開始定義容器的某些功能,Ceph和REX-Ray為容器存盤設定了標準,在CI / CD中,Jenkins完全改變了構建和部署應用程式的方式,
2017年,CoreOS和Docker聯合提議將rkt和containerd作為新專案納入CNCF,這標志著容器生態系統初步形成,容器專案之間協作更加豐富,
從 Docker 最初宣布將剝離其核心運行時到2017年捐贈給CNCF 協會,“containerd”專案在過去兩年經歷顯著增長,Docker捐贈的主要目的是通過提供一個核心容器運行時來促進容器生態系統的進一步創新,容器系統供應商和編排專案(如 Kubernetes、Swarm 等)可以利用這個核心容器運行時,
“containerd”的一個重要設計原則是可以對 Kubernetes 提供一流支持,但又不完全依賴于 Kubernetes,這也為許多容器的用例打開新大門,如 developer desktop、CI/CD、單節點部署、edge 和物聯網等,
2018年:規范化向前發展
容器化成為現代軟體基礎架構的基礎,眾所周知,Kubernetes也被用于大多數企業容器專案,
2018年,GitHub上的Kubernetes專案有27000多個Star,1500多個貢獻者,成為最重要的開源社區之一,
Kubernetes的廣泛采用推動了諸如AWS云供應商提供托管的Kubernetes服務,
此外,VMWare、RedHat和Rancher等領先的軟體供應商也開始提供基于Kubernetes的管理平臺,
2019年:歷史變革
2019年是容器發生歷史性變革的一年,
這一年發生許多歷史性變革事件,包括容器生態變化、產業資本并購和出現新技術解決方案等,
在2019年,新的運行時引擎開始替代docker運行引擎,其最具代表性的新引擎就是CNCF的Containerd和CRI-O(一個用于Kubernetes的輕量級運行時),CRI-O能讓用戶直接從 Kubernetes 運行容器,而無需任何不必要的代碼或工具,只要容器符合 OCI 標準,CRI-O 就可以運行它,
在2019年,產業方面也發送巨大變化,DockerEnterprise賣給Mirantis(一家專注于OpenStack、Kubernetes的云計算公司),可以預見的是Docker Swarm將逐步被淘汰,
同時,雖然rkt已經正式成為CNCF一部分,但是其普及率正在、逐步下降,此外,VMware先后收購Heptio和Pivotal Software(包括PAS和PKS),此舉可以幫助企業客戶更好建立并運行基于Kubernetes的容器化架構,其中,Heptio公司是由兩位曾在2014年幫助谷歌聯合建立Kubernetes專案的主力(當時的專案負責人共有三名)共同建立,創始人及其團隊都將一同加盟VMware公司,如此清晰的創始人背景,可能意味著VMware有意在Kubernetes領域發動全面沖擊,甚至預示VMware已經把Kubernetes視為企業業務運營的根本性基石之一,
2019年,容器技術領域也出現新變革,函式即服務(‘函式’或者‘無服務器’)已經成為一種新的抽象趨勢,其允許開發人員更輕松地運行并部署代碼片段,且這些代碼片段將能快速實作規模伸縮以回應事件需求,
例如,企業只要使用由Google與Pivotal、IBM、紅帽和SAP等企業共同開發的跨云Serverless管理平臺Knative,就能在支持Kubernetes的云平臺上自由的遷移作業負載,無論是跨私有云或是公有云及各種混合云架構都沒問題,
2019年也出現了基于Kubernetes -混合云解決方案,如IBM CloudPaks、谷歌Anthos,AWS Outposts、和Azure Arc,這些云平臺模糊了云環境與本地環境之間的傳統界限,可以更方便管理本地和供應商云服務,
Kubernetes已經成為構建容器化平臺體系的默認抽象方案,上訴這些新功能的出現也代表著Kubernetes的下一步演進方向,諸如Anthos、Arc和Outposts之類超抽象,在超抽象中,計算資源從管理層解耦,類似于Kubernetes的作業方式,它將作業負載從管理層解耦,
2020:容器安全成為新挑戰
作為一種輕量級的虛擬化技術,容器使用方便、操作便捷,大大提高開發人員的作業效率,并得到業內的廣泛使用,但與此同時,容器安全事故頻發,包括不安全的鏡像源、容器入侵事件、運行環境的安全問題等等,
1.不安全的鏡像源
開發者通常會在Docker 官方的Docker Hub倉庫下載鏡像,這些鏡像一部分來源于開發鏡像內相應軟體的官方組織,還有大量鏡像來自第三方組織甚至個人,從這些鏡像倉庫中獲取鏡像的同時,也帶來潛在的安全風險,例如,下載鏡像內軟體本身是否就包含漏洞,下載的鏡像是否被惡意植入后門,鏡像在傳輸程序中是否被篡改,
2.容器入侵事件
由docker本身的架構與機制可能產生的問題,這一攻擊場景主要產生在黑客已經控制了宿主機上的一些容器(或者通過在公有云上建立容器的方式獲得這個條件),然后對宿主機或其他容器發起攻擊來產生影響,
3.運行環境的安全
除docker 本身存在的問題外,docker運行環境存在的問題同樣給docker的使用帶來風險,
由于容器是介于基礎設施和平臺之間的虛擬化技術,因此面向基礎設施虛擬化的傳統云安全解決方案無法完全解決前述安全問題,如以容器為支撐技術構建DevOps環境,就需要設計涵蓋從容器鏡像的創建到投產上線的整個生命周期的容器安全方案,
2.docker基礎用法
什么是docker
Docker 是一個開源的應用容器引擎,基于 Go 語言 并遵從Apache2.0協議開源,Docker 可以讓開發者打包他們的應用以及依賴包到一個輕量級、可移植的容器中,然后發布到任何流行的 Linux 機器上,也可以實作虛擬化,容器是完全使用沙箱機制,相互之間不會有任何介面(類似 iPhone 的 app),更重要的是容器性能開銷極低, Docker 和傳統虛擬化方式的不同之處,可見容器是在作業系統層面上實作虛擬化,直接復用本地主機的作業系統,而傳統方式則是在硬體層面實作,
docker中的容器:
- lxc --> libcontainer --> runC
OCI&OCF
OCI
Open Container-initiative(一個容器的開放協議)
- 由Linux基金會主導于2015年6月創立
- 旨在圍繞容器格式和運行時制定一個開放的工業化標準
- contains two specifications(包含兩個規格)
- the Runtime Specification(runtime-spec) 運行時的規范
- the Image Specification(image-spec) 鏡像的規范
OCF
Open Container Format(一個開放的容器格式)
runC is a CLI tool for spawning and running containers according to the OCI specification(runC是一個CLI工具,用于根據OCI規范生成和運行容器)
- Containers are started as a child process of runC and can be embedded into various other systems without having to run a daemon(容器作為runC的子行程啟動,可以嵌入到其他各種系統中,而不需要運行守護行程)
- runC is built on libcontainer, the same container technology powering millions of Docker Engine installations(runC構建在libcontainer之上,同樣的容器技術支撐著數以百萬計的Docker引擎安裝)
docker提供了一個專門容納容器鏡像的站點:https://hub.docker.com
docker架構

docker鏡像與鏡像倉庫
-
registry:鏡像的倉庫
-
Repository:本身是一個倉庫,這個倉庫里面可以放具體的鏡像,是指具體的某個鏡像的倉庫
-
按照Docker的logo來看,Repository是集裝箱,Registry是鯨魚,
鏡像是靜態的,而容器是動態的,容器有其生命周期,鏡像與容器的關系類似于程式與行程的關系,鏡像類似于檔案系統中的程式檔案,而容器則類似于將一個程式運行起來的狀態,也即行程,所以容器是可以洗掉的,容器被洗掉后其鏡像是不會被洗掉的,
docker物件
When you use docker, you are creating and using images, containers, networks, volumes, pluginns, and other objects.(當你使用docker時,你是在創建和使用影像、容器、網路、卷、插件和其他物件,)
- IMAGES(鏡像)
- An image is a read-only template with instructions for creating a docker container.(鏡像是一個只讀的模板用于創建dorker容器)
- Often, an image is based on another image, with some additional customization.(通常,一個鏡像基于另一個鏡像,并帶有一些額外的定制,)
- You might create your own images or you might only use those created by others and published in a registry.(你可以創建自己的鏡像,也可以只使用其他人創建并在鏡像倉庫中發布的影像,)
- CONTAINERS(容器)
- A conntainer is a runnable instance of an image.(容器是鏡像的可運行實體,)
- You can create, run, stop, move, or delete a container using the docker API or CLI.(你可以使用docker API或CLI創建、運行、停止、移動或洗掉容器,)
- You can connect a container to one or more networks, attach storage to it, or even create a new image based on its current state.(你可以將一個容器連接到一個或多個網路,將存盤附加到它,甚至根據它的當前狀態創建一個新鏡像)
安裝docker
[root@localhost ~]# cd /etc/yum.repos.d/
[root@localhost yum.repos.d]# wget https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/docker-ce.repo
[root@localhost yum.repos.d]# sed -i 's@https://download.docker.com@https://mirrors.tuna.tsinghua.edu.cn/docker-ce@g' docker-ce.repo
[root@localhost yum.repos.d]# dnf -y install docker-ce
配置鏡像加速
docker-ce的組態檔是/etc/docker/daemon.json,此檔案默認不存在,需要我們手動創建并進行配置,而docker的加速就是通過配置此檔案來實作的,
docker的加速有多種方式:
- docker cn
- 中國科技大學加速器
- 阿里云加速器(需要通過阿里云開發者平臺注冊帳號,免費使用個人私有的加速器)
[root@localhost ~]# sudo mkdir -p /etc/docker
[root@localhost ~]# sudo tee /etc/docker/daemon.json <<-'EOF'
> {
> "registry-mirrors": ["https://w673ojdv.mirror.aliyuncs.com"]
> }
> EOF
{
"registry-mirrors": ["https://w673ojdv.mirror.aliyuncs.com"]
}
[root@localhost ~]# sudo systemctl daemon-reload
[root@localhost ~]# sudo systemctl restart docker
[root@localhost ~]# systemctl enable docker
Created symlink /etc/systemd/system/multi-user.target.wants/docker.service → /usr/lib/systemd/system/docker.service.
[root@localhost ~]# docker version //顯示Docker版本資訊
Client: Docker Engine - Community
Version: 20.10.17
API version: 1.41
Go version: go1.17.11
Git commit: 100c701
Built: Mon Jun 6 23:03:11 2022
OS/Arch: linux/amd64
Context: default
Experimental: true
Server: Docker Engine - Community
Engine:
Version: 20.10.17
API version: 1.41 (minimum version 1.12)
Go version: go1.17.11
Git commit: a89b842
Built: Mon Jun 6 23:01:29 2022
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: 1.6.6
GitCommit: 10c12954828e7c7c9b6e0ea9b0c02b01407d3ae1
runc:
Version: 1.1.2
GitCommit: v1.1.2-0-ga916309
docker-init:
Version: 0.19.0
GitCommit: de40ad0
[root@localhost ~]# docker info //顯示整個系統的資訊
Client:
Context: default
Debug Mode: false
Plugins:
app: Docker App (Docker Inc., v0.9.1-beta3)
buildx: Docker Buildx (Docker Inc., v0.8.2-docker)
scan: Docker Scan (Docker Inc., v0.17.0)
Server:
Containers: 0
Running: 0
Paused: 0
Stopped: 0
Images: 0
Server Version: 20.10.17
Storage Driver: overlay2
Backing Filesystem: xfs
Supports d_type: true
Native Overlay Diff: true
userxattr: false
Logging Driver: json-file
Cgroup Driver: cgroupfs
Cgroup Version: 1
Plugins:
Volume: local
Network: bridge host ipvlan macvlan null overlay
Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
Swarm: inactive
Runtimes: io.containerd.runc.v2 io.containerd.runtime.v1.linux runc
Default Runtime: runc
Init Binary: docker-init
containerd version: 10c12954828e7c7c9b6e0ea9b0c02b01407d3ae1
runc version: v1.1.2-0-ga916309
init version: de40ad0
Security Options:
seccomp
Profile: default
Kernel Version: 4.18.0-365.el8.x86_64
Operating System: CentOS Stream 8
OSType: linux
Architecture: x86_64
CPUs: 4
Total Memory: 3.618GiB
Name: localhost.localdomain
ID: ZHWC:G7Y5:BYBD:PHYP:6Z4P:RCXN:NMVB:N3OJ:KLGH:JRRP:7FM3:5MUI
Docker Root Dir: /var/lib/docker
Debug Mode: false
Registry: https://index.docker.io/v1/
Labels:
Experimental: false
Insecure Registries:
127.0.0.0/8
Registry Mirrors:
https://w673ojdv.mirror.aliyuncs.com/
Live Restore Enabled: false
docker常用操作
| 命令 | 功能 |
|---|---|
| docker search | 在Docker Hub上查找鏡像 |
| docker pull | 從鏡像倉庫中拉取或者更新指定鏡像 |
| docker images | 列出本地鏡像 |
| docker create | 創建一個新的容器但不啟動它 |
| docker start | 啟動容器 |
| docker run | 創建一個新的容器并運行一個命令 |
| docker attach | 連接到運行的容器 |
| docker ps | 列出容器 |
| docker logs | 查看容器日志 |
| docker restart | 重啟容器 |
| docker stop | 停止容器 |
| docker kill | 干掉一個或多個運行中的容器 |
| docker rm | 洗掉一個或多個容器 |
| docker exec | 在運行的容器中運行命令 |
| docker info | 顯示整個系統的資訊 |
| docker inspect | 回傳Docker物件的低級資訊 |
//在Docker Hub上查找鏡像
[root@localhost ~]# docker search httpd
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
httpd The Apache HTTP Server Project 4108 [OK]
centos/httpd-24-centos7 Platform for running Apache httpd 2.4 or bui… 44
centos/httpd 35 [OK]
clearlinux/httpd httpd HyperText Transfer Protocol (HTTP) ser… 2
//從鏡像倉庫中拉取或者更新指定鏡像
[root@localhost ~]# docker pull httpd //拉取httpd鏡像 可指定版本號,未指定為最新版
Using default tag: latest
latest: Pulling from library/httpd
a2abf6c4d29d: Pull complete
dcc4698797c8: Pull complete
41c22baa66ec: Pull complete
67283bbdd4a0: Pull complete
d982c879c57e: Pull complete
Digest: sha256:0954cc1af252d824860b2c5dc0a10720af2b7a3d3435581ca788dff8480c7b32
Status: Downloaded newer image for httpd:latest
docker.io/library/httpd:latest
//列出本地鏡像
[root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
httpd latest dabbfbe0c57b 7 months ago 144MB
//創建一個新的容器但不啟動它
[root@localhost ~]# docker create --name web -p 80:80 httpd
9fdaf3c409dac424fababe2f40d16f3ffd4059dc61a0e2a2b92262e947876a9b
//列出容器
[root@localhost ~]# docker ps //列出容器不包括未啟動的
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@localhost ~]# docker ps -a //列出所有容器包括未啟動的
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9fdaf3c409da httpd "httpd-foreground" 21 seconds ago Created web
//啟動容器
[root@localhost ~]# docker start web //可以用ID或者名字
web
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9fdaf3c409da httpd "httpd-foreground" 2 minutes ago Up 9 seconds 0.0.0.0:80->80/tcp, :::80->80/tcp web //查看是否啟動
//關閉容器
[root@localhost ~]# docker stop web //可以用ID或者名字
web
[root@localhost ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9fdaf3c409da httpd "httpd-foreground" 3 minutes ago Exited (0) 3 seconds ago web
//重啟容器
[root@localhost ~]# docker restart web //可以用ID或者名字
web
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9fdaf3c409da httpd "httpd-foreground" 4 minutes ago Up 5 seconds 0.0.0.0:80->80/tcp, :::80->80/tcp web
//干掉運行中的容器 //stop正常退出 kill強制關閉
[root@localhost ~]# docker kill web
web
[root@localhost ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9fdaf3c409da httpd "httpd-foreground" 6 minutes ago Exited (137) 4 seconds ago web
//查看容器日志
[root@localhost ~]# docker logs web
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.2. Set the 'ServerName' directive globally to suppress this message
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.2. Set the 'ServerName' directive globally to suppress this message
[Fri Aug 05 15:17:38.444681 2022] [mpm_event:notice] [pid 1:tid 139833106722112] AH00489: Apache/2.4.52 (Unix) configured -- resuming normal operations
//洗掉一個或多個容器 運行時不可以洗掉
[root@localhost ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9fdaf3c409da httpd "httpd-foreground" 13 minutes ago Up 2 minutes 0.0.0.0:80->80/tcp, :::80->80/tcp web
[root@localhost ~]# docker stop web //先停止
web
[root@localhost ~]# docker rm web //在進出洗掉
web
[root@localhost ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
//-f 在運行時可以強制洗掉
[root@localhost ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
662e0fdfb4ca httpd "/bin/sh" 25 seconds ago Exited (0) 3 seconds ago test
[root@localhost ~]# docker rm -f test
test
[root@localhost ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
//創建一個新的容器并運行一個命令
[root@localhost ~]# docker run -it --name test httpd /bin/sh
#
[root@localhost ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8592a0cf0a8a httpd "/bin/sh" 8 seconds ago Up 8 seconds 80/tcp test
[root@localhost ~]# docker run -it --name test httpd /bin/sh
# exit //互動模式內 如果退出 就會停止容器
[root@localhost ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8592a0cf0a8a httpd "/bin/sh" 37 seconds ago Exited (0) 4 seconds ago test
//連接到正在運行中的容器
[root@localhost ~]# docker start test
test
[root@localhost ~]# docker start test
test
# exit //此方式 進入退出后也會自動關閉容器
[root@localhost ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8592a0cf0a8a httpd "/bin/sh" 3 minutes ago Exited (130) 4 seconds ago test
//在運行的容器中執行命令
[root@localhost ~]# docker start test
test
[root@localhost ~]# docker exec -it test /bin/sh
# exit //使用exec進入后退出后容器不會停止運行
[root@localhost ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8592a0cf0a8a httpd "/bin/sh" 5 minutes ago Up 55 seconds 80/tcp test
//回傳Docker物件的低級資訊
[root@localhost ~]# docker inspect
"docker inspect" requires at least 1 argument.
See 'docker inspect --help'.
Usage: docker inspect [OPTIONS] NAME|ID [NAME|ID...]
Return low-level information on Docker objects
[root@localhost ~]# docker inspect test
[
{
"Id": "8592a0cf0a8a981579b57a156c4807a706be1279bf1336c20208679aa7c81472",
"Created": "2022-08-05T15:34:30.163877907Z",
"Path": "/bin/sh",
"Args": [],
"State": {
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 176575,
"ExitCode": 0,
"Error": "",
"StartedAt": "2022-08-05T15:39:10.071223772Z",
"FinishedAt": "2022-08-05T15:38:06.009220384Z"
......省略
"Networks": {
"bridge": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"NetworkID": "93f3fbf6b5b9952e23ebd8e3799b996cc8bd4161977b51038af852c505c9a4dc",
"EndpointID": "3f49e68f641af9bc93eff3aa01d065f6650db6543e2ecd453ab5d8cd15cb3518",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:11:00:02",
"DriverOpts": null
}
}
}
}
]
3.docker存盤驅動
docker提供了多種存盤驅動來實作不同的方式存盤鏡像,下面是常用的幾種存盤驅動:
- AUFS
- OverlayFS
- Devicemapper
- Btrfs
- VFS
- zfs
AUFS
AUFS(AnotherUnionFS)是一種Union FS,是檔案級的存盤驅動,AUFS是一個能透明覆寫一個或多個現有檔案系統的層狀檔案系統,把多層合并成檔案系統的單層表示,簡單來說就是支持將不同目錄掛載到同一個虛擬檔案系統下的檔案系統,這種檔案系統可以一層一層地疊加修改檔案,無論底下有多少層都是只讀的,只有最上層的檔案系統是可寫的,當需要修改一個檔案時,AUFS創建該檔案的一個副本,使用CoW將檔案從只讀層復制到可寫層進行修改,結果也保存在可寫層,在Docker中,底下的只讀層就是image,可寫層就是Container,
AUFS檔案系統據說有3W行代碼,而ext4檔案系統卻只有4000-5000行左右代碼,這些代碼是要被整合進內核的,后來AUFS申請要被合并進內核代碼的時候,linuz覺得它這代碼太過臃腫,于是拒絕了,因此AUFS這個檔案系統一直以來就不是linux內核中自有的檔案系統,想用AUFS這個檔案系統的話,必須自己向內核打補丁并去編譯使用它,但redhat系列的作業系統一向以穩定著稱,不會干這種出格的事,所以在redhat系列作業系統中使用AUFS并無可能,而ubuntu上的docker默認使用的就是AUFS,
OverlayFS
Overlay是Linux內核3.18后支持的,也是一種Union FS,和AUFS的多層不同的是Overlay只有兩層:一個upper檔案系統和一個lower檔案系統,分別代表Docker的鏡像層和容器層,當需要修改一個檔案時,使用CoW將檔案從只讀的lower復制到可寫的upper進行修改,結果也保存在upper層,在Docker中,底下的只讀層就是image,可寫層就是Container,目前最新的OverlayFS為Overlay2,
AUFS和Overlay都是聯合檔案系統,但AUFS有多層,而Overlay只有兩層,所以在做寫時復制操作時,如果檔案比較大且存在比較低的層,則AUSF會慢一些,而且Overlay并入了linux kernel mainline,AUFS沒有,目前AUFS已基本被淘汰,
DeviceMapper
Device mapper是Linux內核2.6.9后支持的,提供的一種從邏輯設備到物理設備的映射框架機制,在該機制下,用戶可以很方便的根據自己的需要制定實作存盤資源的管理策略,AUFS和OverlayFS都是檔案級存盤,而Device mapper是塊級存盤,所有的操作都是直接對塊進行操作,而不是檔案,Device mapper驅動會先在塊設備上創建一個資源池,然后在資源池上創建一個帶有檔案系統的基本設備,所有鏡像都是這個基本設備的快照,而容器則是鏡像的快照,所以在容器里看到檔案系統是資源池上基本設備的檔案系統的快照,并沒有為容器分配空間,當要寫入一個新檔案時,在容器的鏡像內為其分配新的塊并寫入資料,這個叫用時分配,當要修改已有檔案時,再使用CoW為容器快照分配塊空間,將要修改的資料復制到在容器快照中新的塊里再進行修改,
OverlayFS是檔案級存盤,Device mapper是塊級存盤,當檔案特別大而修改的內容很小,Overlay不管修改的內容大小都會復制整個檔案,對大檔案進行修改顯然要比小檔案要消耗更多的時間,而塊級無論是大檔案還是小檔案都只復制需要修改的塊,并不是整個檔案,在這種場景下,顯然device mapper要快一些,因為塊級的是直接訪問邏輯盤,適合IO密集的場景,而對于程式內部復雜,大并發但少IO的場景,Overlay的性能相對要強一些,
Btrfs
Btrfs被稱為下一代寫時復制檔案系統,并入Linux內核,也是檔案級級存盤,但可以像Device mapper一直接操作底層設備,Btrfs把檔案系統的一部分配置為一個完整的子檔案系統,稱之為subvolume ,那么采用 subvolume,一個大的檔案系統可以被劃分為多個子檔案系統,這些子檔案系統共享底層的設備空間,在需要磁盤空間時便從底層設備中分配,類似應用程式呼叫 malloc()分配記憶體一樣,為了靈活利用設備空間,Btrfs 將磁盤空間劃分為多個chunk ,每個chunk可以使用不同的磁盤空間分配策略,比如某些chunk只存放metadata,某些chunk只存放資料,這種模型有很多優點,比如Btrfs支持動態添加設備,用戶在系統中增加新的磁盤之后,可以使用Btrfs的命令將該設備添加到檔案系統中,Btrfs把一個大的檔案系統當成一個資源池,配置成多個完整的子檔案系統,還可以往資源池里加新的子檔案系統,而基礎鏡像則是子檔案系統的快照,每個子鏡像和容器都有自己的快照,這些快照則都是subvolume的快照
當寫入一個新檔案時,為在容器的快照里為其分配一個新的資料塊,檔案寫在這個空間里,這個叫用時分配,而當要修改已有檔案時,使用CoW復制分配一個新的原始資料和快照,在這個新分配的空間變更資料,變結束再更新相關的資料結構指向新子檔案系統和快照,原來的原始資料和快照沒有指標指向,被覆寫
ZFS
ZFS 檔案系統是一個革命性的全新的檔案系統,它從根本上改變了檔案系統的管理方式,ZFS 完全拋棄了“卷管理”,不再創建虛擬的卷,而是把所有設備集中到一個存盤池中來進行管理,用“存盤池”的概念來管理物理存盤空間,過去,檔案系統都是構建在物理設備之上的,為了管理這些物理設備,并為資料提供冗余,“卷管理”的概念提供了一個單設備的映像,而ZFS創建在虛擬的,被稱為“zpools”的存盤池之上,每個存盤池由若干虛擬設備(virtual devices,vdevs)組成,這些虛擬設備可以是原始磁盤,也可能是一個RAID1鏡像設備,或是非標準RAID等級的多磁盤組,于是zpool上的檔案系統可以使用這些虛擬設備的總存盤容量
在Docker里ZFS的使用,首先從zpool里分配一個ZFS檔案系統給鏡像的基礎層,而其他鏡像層則是這個ZFS檔案系統快照的克隆,快照是只讀的,而克隆是可寫的,當容器啟動時則在鏡像的最頂層生成一個可寫層,
當要寫一個新檔案時,使用按需分配,一個新的資料快從zpool里生成,新的資料寫入這個塊,而這個新空間存于容器(ZFS的克隆)里
當要修改一個已存在的檔案時,使用寫時復制,分配一個新空間并把原始資料復制到新空間完成修改
| 存盤驅動 | 特點 | 優點 | 缺點 | 使用場景 |
|---|---|---|---|---|
| AUFS | 聯合檔案系統、未并入內核主線、檔案級存盤 | 作為docker的第一個存盤驅動,已經有很長的歷史,比較穩定,且在大量的生產中實踐過,有較強的社區支持 | 有多層,在做寫時復制操作時,如果檔案比較大且存在比較低的層,可能會慢一些 | 大并發但少IO的場景 |
| overlayFS | 聯合檔案系統、并入內核主線、檔案級存盤 | 只有兩層 | 不管修改的內容大小都會復制整個檔案,對大檔案進行修改顯示要比小檔案消耗更多的時間 | 大并發但少IO的場景 |
| Devicemapper | 并入內核主線、塊級存盤 | 塊級無論是大檔案還是小檔案都只復制需要修改的塊,并不是整個檔案 | 不支持共享存盤,當有多個容器讀同一個檔案時,需要生成多個復本,在很多容器啟停的情況下可能會導致磁盤溢位 | 適合io密集的場景 |
| Btrfs | 并入linux內核、檔案級存盤 | 可以像devicemapper一樣直接操作底層設備,支持動態添加設備 | 不支持共享存盤,當有多個容器讀同一個檔案時,需要生成多個復本 | 不適合在高密度容器的paas平臺上使用 |
| ZFS | 把所有設備集中到一個存盤池中來進行管理 | 支持多個容器共享一個快取塊,適合記憶體大的環境 | COW使用碎片化問題更加嚴重,檔案在硬碟上的物理地址會變的不再連續,順序讀會變的性能比較差 | 適合paas和高密度的場景 |
**1、AUFS VS Overlay** AUFS和Overlay都是聯合檔案系統,但AUFS有多層,而Overlay只有兩層,所以在做寫時復制操作時,如果檔案比較大且存在比較低的層,則AUSF可能會慢一些,而且Overlay并入了linux kernel mainline,AUFS沒有,所以可能會比AUFS快,但Overlay還太年輕,要謹慎在生產使用,而AUFS做為docker的第一個存盤驅動,已經有很長的歷史,比較的穩定,且在大量的生產中實踐過,有較強的社區支持,目前開源的DC/OS指定使用Overlay
2、Overlay VS Device mapper
Overlay是檔案級存盤,Device mapper是塊級存盤,當檔案特別大而修改的內容很小,Overlay不管修改的內容大小都會復制整個檔案,對大檔案進行修改顯示要比小檔案要消耗更多的時間,而塊級無論是大檔案還是小檔案都只復制需要修改的塊,并不是整個檔案,在這種場景下,顯然device mapper要快一些,因為塊級的是直接訪問邏輯盤,適合IO密集的場景,而對于程式內部復雜,大并發但少IO的場景,Overlay的性能相對要強一些,
3、Device mapper VS Btrfs Driver VS ZFS
Device mapper和Btrfs都是直接對塊操作,都不支持共享存盤,表示當有多個容器讀同一個檔案時,需要生活多個復本,所以這種存盤驅動不適合在高密度容器的PaaS平臺上使用,而且在很多容器啟停的情況下可能會導致磁盤溢位,造成主機不能作業,Device mapper不建議在生產使用,Btrfs在docker build可以很高效,
ZFS最初是為擁有大量記憶體的Salaris服務器設計的,所在在使用時對記憶體會有影響,適合記憶體大的環境,ZFS的COW使碎片化問題更加嚴重,對于順序寫生成的大檔案,如果以后隨機的對其中的一部分進行了更改,那么這個檔案在硬碟上的物理地址就變得不再連續,未來的順序讀會變得性能比較差,ZFS支持多個容器共享一個快取塊,適合PaaS和高密度的用戶場景
4、在IO性能上
AUFS在讀的方面性能相比Overlay要差一些,但在寫的方面性能比Overlay要好
device mapper在512M以上檔案的讀寫性能都非常的差,但在512M以下的檔案讀寫性能都比較好
btrfs在512M以上的檔案讀寫性能都非常好,但在512M以下的檔案讀寫性能相比其他的存盤驅動都比較差
ZFS整體的讀寫性能相比其他的存盤驅動都要差一些
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/501137.html
標籤:Linux
上一篇:docker
