概念
虛擬化
虛擬化技術(shù)是一種將計(jì)算機(jī)物理資源進(jìn)行抽象外恕、轉(zhuǎn)化為虛擬的計(jì)算機(jī)資源提供給程序使用的技術(shù)
計(jì)算機(jī)資源:CPU提供的運(yùn)算控制資源,硬盤提供的數(shù)據(jù)存儲(chǔ)資源以现,網(wǎng)卡提供的網(wǎng)絡(luò)傳輸資源等匀归。
硬件虛擬化,指的是物理硬件本身就提供虛擬化的支持
軟件虛擬化运敢。指的是通過軟件的方式來實(shí)現(xiàn)虛擬化中關(guān)鍵的指令轉(zhuǎn)換部分校仑。
虛擬機(jī)
通過一個(gè)虛擬機(jī)監(jiān)視器的設(shè)施來隔離操作系統(tǒng)與硬件或者應(yīng)用程序和操作系統(tǒng),以次來達(dá)到虛擬化的目的传惠。 通過隔離程序和操作系統(tǒng)迄沫,將程序的指令轉(zhuǎn)換為當(dāng)前所在操作系統(tǒng)平臺(tái)所能執(zhí)行的指令,達(dá)到了不用對(duì)程序進(jìn)行任何修改即可執(zhí)行的目的卦方。
容器
容器技術(shù)是一種全新意義上的虛擬化技術(shù)羊瘩,屬于操作系統(tǒng)虛擬化的范疇, 可以理解為操作系統(tǒng)本身支持一些接口,能夠讓應(yīng)用程序間可以互不干擾的獨(dú)立運(yùn)行困后,并且能夠?qū)ζ湓谶\(yùn)行中所使用的資源進(jìn)行干預(yù)乐纸。 容器技術(shù)沒有做指令轉(zhuǎn)換,運(yùn)行在容器中的應(yīng)用程序自身必須支持在真實(shí)操作系統(tǒng)上運(yùn)行摇予。
數(shù)據(jù)卷
Docker采用掛載真實(shí)數(shù)據(jù)源的方式進(jìn)行應(yīng)用數(shù)據(jù)文件存儲(chǔ)汽绢,通過UnionFS(聯(lián)合文件系統(tǒng)),除了能夠從宿主機(jī)操作系統(tǒng)中掛載目錄外侧戴,還能夠建立獨(dú)立的目錄持久存放數(shù)據(jù)宁昭,或者在容器間共享。
Docker常用命令:
鏡像命令
docker images
docker images 查看所有本地的主機(jī)上的鏡像
可選項(xiàng)
-a, --all # 列出所有鏡像
-q, --quiet # 只顯示鏡像的id
docker search
docker search 搜索鏡像
docker search mysql
可選項(xiàng):通過收藏來過濾
--filter=START=3000 # 搜索出來的鏡像就是START大于3000的
docker search mysql --filter=START=3000
docker pull
# docker pull 鏡像名[:tag] 下載鏡像
docker pull mysql
# 如果不寫tag 默認(rèn)就是latest
# 分層下載酗宋,docker image的核心 聯(lián)合文件系統(tǒng)
# Digest: 簽名
# dokcer.io/librarymysql:latest 真實(shí)地址
docker rmi
使用該鏡像創(chuàng)建的容器在運(yùn)行中积仗,此鏡像不可刪除 不過可以 加-f 參數(shù) 強(qiáng)制刪除。
docker rmi -f 鏡像id # 強(qiáng)制刪除指定的鏡像
docker rmi -f 鏡像id0蜕猫, 鏡像id1寂曹, 鏡像id # 強(qiáng)制刪除指定的多個(gè)鏡像
docker rmi -f $(dcoker imaages -aq) # 強(qiáng)制批量刪除 查詢出來所有的鏡像
docker commit
創(chuàng)建鏡像: 通過容器創(chuàng)建
docker commit [-a 作者 -c 執(zhí)行某些Dockerfile執(zhí)行 -m 說明文字 -p 是否暫停容器] 容器id 鏡像:標(biāo)簽
docker commit -a meiko -m "一段描述" container_id image_name:version1
[]中選項(xiàng)可以省略
docker build
創(chuàng)建鏡像:通過Dockerfile創(chuàng)建
docker build ./demo
選項(xiàng):--no-cache 創(chuàng)建過程不使用緩存
-f 指定要使用的Dockerfile文件的路徑,指向路徑+文件名
-t 鏡像的名字及標(biāo)簽
docker build --no-cache -t image_name:tag -f Dockerfile_local .
docker save/load 鏡像遷移 (只想備份images時(shí)使用)
# 將nginx:latest導(dǎo)出到/demo/nginx.tar中
docker save -o /demo/nginx.tar nginx:latet
#或
docker save > /demo/nginx.tar nginx:latest
# 注意save下來的是每一層的數(shù)據(jù)
# 將/demo/nginx.tar導(dǎo)入
docker load -i /demo/nginx.tar
# 或
docker load < /demo/nginx.tar
注意: 導(dǎo)入的鏡像沒有repo和tag 可以使用docker tag 鏡像id repo:tag任意指定自己想要的tag
docker export/import 將一個(gè)容器導(dǎo)出為文件(容器啟動(dòng)后回右,內(nèi)容有變化隆圆,想備份容器時(shí)使用)
# 導(dǎo)出容器為文件
docker export -o "my_nginx.tar" 容器id
# 導(dǎo)入文件成鏡像
選項(xiàng): --change 使用coker指令創(chuàng)建鏡像
--message 在導(dǎo)入鏡像時(shí)設(shè)置提交信息
docker import --message "commit my mginx" my_nginx.tar my_nginx:version1
容器命令
說明: 有了鏡像才可以創(chuàng)建容器
容器的生命周期分為五種狀態(tài)
● Created:容器已經(jīng)被創(chuàng)建,容器所需的相關(guān)資源已經(jīng)準(zhǔn)備就緒翔烁,但容器中的程序還未處于運(yùn)行狀態(tài)渺氧。
● Running:容器正在運(yùn)行,也就是容器中的應(yīng)用已經(jīng)在運(yùn)行中了蹬屹。
● Paused:容器已暫停侣背,表示容器中的所有程序都處于暫停(不是停止)狀態(tài)。
● Stopped:容器處于停止?fàn)顟B(tài)慨默,占用的資源和沙盒環(huán)境都依然存在贩耐,只是容器中的應(yīng)用程序均已停止。
● Deleted:容器已刪除厦取,占用的資源及存儲(chǔ)的Docker中的管理信息都已釋放和移除憔杨。
docker run
docker run [可選參數(shù)] image # 新建容器并啟動(dòng)
#參數(shù)說明
--name="容器名字" # 容器名字,區(qū)分容器
-d # 后臺(tái)方式運(yùn)行
-it # 使用交互方式運(yùn)行蒜胖,進(jìn)入容器查看內(nèi)容
-p # 指定容器的端口 -p 8080:8080
-p ip:主機(jī)端口:容器端口
-p 主機(jī)端口:容器端口 (常用)
-p 容器端口
容器端口
-P # 隨機(jī)指定端口
--rm 在容器退出時(shí)能夠自動(dòng)i清理容器內(nèi)部的文件系統(tǒng), 不能與-d同時(shí)使用抛蚤。 作用等價(jià)于台谢,在容器退出后,執(zhí)行docker rm -v
docker run -it centos /bin/bash # 啟動(dòng)并進(jìn)入容器
exit # 從容器中退回主機(jī)
docker ps
docker ps # 列出運(yùn)行中的容器
可選參數(shù)
-a --all # 列出所有容器岁经。包括停止的
-n=? # 列出最近n個(gè)創(chuàng)建的容器
-q # 只顯示容器的編號(hào)
docker create 創(chuàng)建容器
docker create --name demo 鏡像id或repo:tag
docker start 啟動(dòng)容器
docker start 容器id或容器名稱
# 此時(shí) 容器處于啟動(dòng)狀態(tài)
docker exec 進(jìn)入容器
docker exec -it 容器id或容器名稱 /bin/bash
選項(xiàng): -it 以交互命令行方式進(jìn)入其中
exit 退出容器
exit # 直接容器停止并退出
Ctrl+P+Q #容器不停止退出
docker rm
docker rm 容器id # 刪除容器朋沮,不能刪除正在運(yùn)行的容器
docker rm $(docker ps -aq) # 強(qiáng)制刪除全部容器
docker rm -f 容器id # 強(qiáng)制刪除容器
docker ps -aq | xrags docker rm # 管道符刪除篩選出來的容器
啟動(dòng)和停止容器
docker start 容器id # 啟動(dòng)容器
docker restart 容器id # 重啟容器
docker stop 容器id # 停止當(dāng)前正在運(yùn)行的容器
docker kill 容器id # 強(qiáng)制停止當(dāng)前容器
其他命令:
后臺(tái)啟動(dòng)容器
docker run -d 容器id # 啟動(dòng)容器
問題: 發(fā)現(xiàn)容器同是停止的
原因:docker 容器使用后臺(tái)運(yùn)行,就必須要有喲一個(gè)前臺(tái)進(jìn)程, docker發(fā)現(xiàn)沒有應(yīng)用樊拓, 就會(huì)自動(dòng)停止
# nginx, 容器啟動(dòng)纠亚,發(fā)現(xiàn)自己沒有通過服務(wù), 就會(huì)立即停止
查看日志
docker logs [可選參數(shù)] 容器id
# 可選參數(shù)
-f : 跟蹤日志輸出
--since :顯示某個(gè)開始時(shí)間的所有日志
-t : 顯示時(shí)間戳
--tail :僅列出最新N條容器日志
docker logs -ft --tail 10 容器id # 顯示該容器最近10條日志
查看容器中進(jìn)程信息
docker top 容器id
UID PID PPID
用戶ID 進(jìn)程ID 父進(jìn)程ID
docker inspect
docker inspect 容器id # 查看容器的元數(shù)據(jù)
#docker inspect 6e1d2ce15c2e
[
{
"Id": "6e1d2ce15c2e7c27f2c6ac524f3a17132e06bd324492f233f1e9a1b4b2acc330",
"Created": "2021-05-27T13:52:03.994785605+08:00",
"Path": "/alicvdata/cv_engine_app/start.sh",
"Args": [],
"State": {
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 129119,
"ExitCode": 0,
"Error": "",
"StartedAt": "2021-07-22T21:04:43.263598079+08:00",
"FinishedAt": "2021-07-22T20:51:58.196842719+08:00"
},
"Image": "sha256:7f47f511e9d7e20a5f8b9af45e20795695ac79ed312a6ddfeaa03f04cd4d442c",
"ResolvConfPath": "/apsarapangu/disk1/docker/containers/6e1d2ce15c2e7c27f2c6ac524f3a17132e06bd324492f233f1e9a1b4b2acc330/resolv.conf",
"HostnamePath": "/apsarapangu/disk1/docker/containers/6e1d2ce15c2e7c27f2c6ac524f3a17132e06bd324492f233f1e9a1b4b2acc330/hostname",
"HostsPath": "/apsarapangu/disk1/docker/containers/6e1d2ce15c2e7c27f2c6ac524f3a17132e06bd324492f233f1e9a1b4b2acc330/hosts",
"LogPath": "/apsarapangu/disk1/docker/containers/6e1d2ce15c2e7c27f2c6ac524f3a17132e06bd324492f233f1e9a1b4b2acc330/6e1d2ce15c2e7c27f2c6ac524f3a17132e06bd324492f233f1e9a1b4b2acc330-json.log",
"Name": "/thanos_x86",
"RestartCount": 0,
"Driver": "overlay",
"MountLabel": "",
"ProcessLabel": "",
"AppArmorProfile": "",
"ExecIDs": null,
"HostConfig": {
"Binds": null,
"ContainerIDFile": "",
"LogConfig": {
"Type": "json-file",
"Config": {
"max-file": "4",
"max-size": "25m"
}
},
"NetworkMode": "host",
"PortBindings": {},
"RestartPolicy": {
"Name": "no",
"MaximumRetryCount": 0
},
"AutoRemove": false,
"VolumeDriver": "",
"VolumesFrom": null,
"CapAdd": null,
"CapDrop": null,
"Dns": [],
"DnsOptions": [],
"DnsSearch": [],
"ExtraHosts": null,
"GroupAdd": null,
"IpcMode": "",
"Cgroup": "",
"Links": null,
"OomScoreAdj": 0,
"PidMode": "",
"Privileged": false,
"PublishAllPorts": false,
"ReadonlyRootfs": false,
"SecurityOpt": null,
"UTSMode": "",
"UsernsMode": "",
"ShmSize": 67108864,
"Runtime": "runc",
"ConsoleSize": [
0,
0
],
"Isolation": "",
"CpuShares": 0,
"Memory": 67474893824,
"CgroupParent": "",
"BlkioWeight": 0,
"BlkioWeightDevice": null,
"BlkioDeviceReadBps": [],
"BlkioDeviceWriteBps": [],
"BlkioDeviceReadIOps": [],
"BlkioDeviceWriteIOps": [],
"CpuPeriod": 0,
"CpuQuota": 0,
"CpusetCpus": "35,36,37,38",
"CpusetMems": "",
"ScheLatSwitch": 0,
"Devices": [],
"DiskQuota": null,
"KernelMemory": 0,
"MemoryReservation": 0,
"MemorySwap": 134949787648,
"MemorySwappiness": -1,
"MemoryWmarkRatio": 0,
"MemoryExtra": 0,
"MemoryForceEmptyCtl": -1,
"MemoryPriority": null,
"MemoryUsePriorityOOM": null,
"MemoryKillAll": null,
"OomKillDisable": false,
"PidsLimit": 0,
"Ulimits": null,
"CpuCount": 0,
"CpuPercent": 0,
"IOMaximumIOps": 0,
"IOMaximumBandwidth": 0,
"CPUBvtWarpNs": -2,
"IntelRdtL3Cbm": "",
"IntelRdtGroup": "",
"IntelRdtMba": "",
"BlkFileLevelSwitch": 0,
"BlkBufferWriteBps": 0,
"BlkMetaWriteTps": 0,
"BlkFileThrottlePath": null,
"BlkBufferWriteSwitch": 0,
"BlkDeviceBufferWriteBps": null,
"BlkDeviceIdleTime": null,
"BlkDeviceLatencyTarget": null,
"BlkioDeviceReadLowBps": null,
"BlkioDeviceReadLowIOps": null,
"BlkioDeviceWriteLowBps": null,
"BlkioDeviceWriteLowIOps": null
},
"GraphDriver": {
"Name": "overlay",
"Data": {
"LowerDir": "/apsarapangu/disk1/docker/overlay/55c3d22360047965b1c9776fe11163d06c5a989a2b50085d2fcc2a23d307420b/root",
"MergedDir": "/apsarapangu/disk1/docker/overlay/fff2e5913071f40797f163aeeef850ded288ef740c062e69b7d620215b365cfb/merged",
"UpperDir": "/apsarapangu/disk1/docker/overlay/fff2e5913071f40797f163aeeef850ded288ef740c062e69b7d620215b365cfb/upper",
"WorkDir": "/apsarapangu/disk1/docker/overlay/fff2e5913071f40797f163aeeef850ded288ef740c062e69b7d620215b365cfb/work"
}
},
"HostRootPath": "/apsarapangu/disk1/docker/overlay/fff2e5913071f40797f163aeeef850ded288ef740c062e69b7d620215b365cfb/merged",
"Mounts": [],
"Config": {
"Hostname": "e21a02001.cloud.a02.amtest8",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"ExposedPorts": {
"3306/tcp": {},
"5000/tcp": {},
"8080/tcp": {}
},
"Tty": true,
"OpenStdin": true,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
],
"Cmd": null,
"Image": "reg.docker.alibaba-inc.com/stonecloud/cv_common_engine:thanos_x86",
"Volumes": null,
"WorkingDir": "/alicvdata/cv_engine_app",
"Entrypoint": [
"/alicvdata/cv_engine_app/start.sh"
],
"OnBuild": null,
"Labels": {
"build-date": "20180107",
"desktop.docker.io/binds/0/Source": "/etc/resolv.conf",
"desktop.docker.io/binds/0/SourceKind": "hostFile",
"desktop.docker.io/binds/0/Target": "/etc/resolv.conf",
"license": "GPLv2",
"name": "CentOS Base Image",
"vendor": "CentOS"
},
"FromCmdCreate": true,
"NetPriority": 0
},
"NetworkSettings": {
"Bridge": "",
"SandboxID": "ef1c85f46e8dd1509fd03c3be8e8af3bf26e9f09522e5419c1b910e64f86aed3",
"HairpinMode": false,
"LinkLocalIPv6Address": "",
"LinkLocalIPv6PrefixLen": 0,
"Ports": {},
"SandboxKey": "/var/run/docker/netns/default",
"SecondaryIPAddresses": null,
"SecondaryIPv6Addresses": null,
"EndpointID": "",
"Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"IPAddress": "",
"IPPrefixLen": 0,
"IPv6Gateway": "",
"MacAddress": "",
"Networks": {
"host": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"NetworkID": "8a8874fe423fc34f361b7faa8e617643895a1691473505d5bf202acf7b1a7c28",
"EndpointID": "10a025a35207e34f90c129bb58458865ef4fd1516a5fec3aa1725bb8271eb8b2",
"Gateway": "",
"IPAddress": "",
"IPPrefixLen": 0,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "",
"Time": 0,
"SkipResolver": false
}
}
}
}
]
進(jìn)入當(dāng)前正在運(yùn)行的容器
容器退出使用后臺(tái)方式運(yùn)行的筋夏,需要進(jìn)入容器蒂胞, 修改一些配置。
# 方式一:
docker exec -it 容器id /bin/bash # 進(jìn)入容器后 開啟一個(gè)新的終端条篷,可以在里面操作
# 方式二:
docker attach 容器id # 進(jìn)入容器正在執(zhí)行的終端骗随。 不會(huì)啟動(dòng)新的進(jìn)程。
從容器內(nèi)拷貝文件到主機(jī)上
docker cp 容器id:容器內(nèi)文件路徑 本機(jī)目錄
#步驟1,進(jìn)入容器
# docker attach 容器id
#步驟2,拷貝
# docker cp hye868923768:/home/meiko.js /home
# 說明: 拷貝是手動(dòng)操作 使用 -v 卷技術(shù)赴叹,可以實(shí)現(xiàn)自動(dòng)同步
小結(jié)
attach # 當(dāng)前shell下attach鏈接指定運(yùn)行鏡像
build # 通過Dockerfile 定制鏡像
commit # 提交當(dāng)前容器為新的鏡像
cp # 從容器中拷貝指定文件或目錄到宿主機(jī)中
create # 創(chuàng)建一個(gè)新的容器鸿染,同 run, 但不啟動(dòng)容器
diff # 查看docker容器變化
events # 從docker服務(wù)獲取容器實(shí)時(shí)事件
exec # 在已存在的容器上運(yùn)行命令
export # 導(dǎo)出容器內(nèi)的內(nèi)容流作為一個(gè)tar 歸檔文件【對(duì)應(yīng)import】
import # 從tar包中的內(nèi)容創(chuàng)建一個(gè)新的文件系統(tǒng)映像【對(duì)應(yīng)export】
history # 展示一個(gè)鏡像形成歷史
images # 列出系統(tǒng)當(dāng)前鏡像
info # 顯示系統(tǒng)相關(guān)信息
inspect # 查看容器詳細(xì)信息
kill # kill 指定容器
load # 從一個(gè)tar包中加載一個(gè)鏡像[對(duì)用save]
save # 保存一個(gè)鏡像為tar包[對(duì)應(yīng)load]
login # 注冊(cè)或者登錄一個(gè)docker源服務(wù)器
logout # 從當(dāng)前Docker registry退出
logs # 輸出當(dāng)前容器日志信息
port # 查看映射端口對(duì)應(yīng)的容器內(nèi)部源端口
start # 啟動(dòng)容器
stop # 停止容器
pause # 暫停容器
unpause # 取消暫停容器
restart # 重啟容器
ps # 列出容器列表
pull # 從docker鏡像源服務(wù)器拉取指定鏡像或者庫(kù)鏡像
push # 推送指定鏡像或者庫(kù)鏡像到docker源服務(wù)器
rm # 移除一個(gè)或多個(gè)容器
rmi # 移除一個(gè)或多個(gè)鏡像
run # 創(chuàng)建一個(gè)新的容器并運(yùn)行
search # 在docker hub中搜索鏡像
tag # 給源中鏡像打tag
top # 查看容器中運(yùn)行的進(jìn)程信息
version #查看docker版本
wait # 截取容器停止時(shí)的退出狀態(tài)值
Docker 鏡像
鏡像定義
鏡像是一種輕量級(jí),可執(zhí)行的獨(dú)立軟件包,用來打包軟件運(yùn)行環(huán)境和基于運(yùn)行環(huán)境開發(fā)的軟件,它包含運(yùn)行某個(gè)軟件所需的所有內(nèi)容,包括代碼,運(yùn)行時(shí),庫(kù),環(huán)境變量和配置文件.
Docker鏡像加載原理
UnionFS(聯(lián)合文件系統(tǒng))
下載鏡像時(shí)看到的一層層的.
UFS是一種分層,輕量級(jí)并且高性能的文件系統(tǒng),它支持對(duì)文件系統(tǒng)的修改作為一次提交來一層層的疊加, 同時(shí)可以將不同目錄掛載到同一虛擬文件系統(tǒng). Union文件系統(tǒng)是Docker鏡像的基礎(chǔ),鏡像可以通過分層來繼續(xù)繼承,基于基礎(chǔ)鏡像,可以制作各種具體的應(yīng)用鏡像.
特性:一次同時(shí)加載多個(gè)文件系統(tǒng),但從外面看起來,只能看到一個(gè)文件系統(tǒng), 聯(lián)合加載會(huì)把各層文件系統(tǒng)疊加起來,這樣最終的文件系統(tǒng)會(huì)包含所有底層的文件和目錄.
Docker鏡像加載原理
docker的鏡像實(shí)際上由一層一層的文件系統(tǒng)組成, 這種層級(jí)就是聯(lián)合文件系統(tǒng)(unionFS)
bootfs(boot file system- 系統(tǒng)啟動(dòng)需要引導(dǎo)加載),主要包含bootloader(加載器)和kernel,加載器主要是引導(dǎo)加載kernel.Linux剛啟動(dòng)時(shí)會(huì)加載bootfs文件系統(tǒng),在Docker鏡像的最底層bootfs. 這一層與典型的Linux/Unix系統(tǒng)是一樣的, 包含boot加載器和內(nèi)核, 當(dāng)boot加載完成之后,整合內(nèi)核就在內(nèi)存中了, 此時(shí)內(nèi)存的使用全已由bootfs轉(zhuǎn)交給內(nèi)核,此時(shí)系統(tǒng)也會(huì)卸載bootfs.
rootfs(root file system) 在bootfs之上, 包含的就是典型Linux系統(tǒng)中的/dev /proc /bin /etc等標(biāo)準(zhǔn)目錄和文件, rootfs就是各種不同的操作系統(tǒng)發(fā)行版,如Ubuntu, Centos等
docker images inspect redis:latest 查看redis的鏡像詳情.
分層下載, 6個(gè)layer, 表示有6層.
通俗解釋:
黑屏->加載>開機(jī)運(yùn)行操作系統(tǒng) 中間加載過程就是bootfs工作過程,通過加載器加載內(nèi)核, 完成后卸載bootfs, 這個(gè)過程比較耗時(shí),
對(duì)于一個(gè)精簡(jiǎn)的OS, rootfs可以很小,只需要包含最基本的命令, 工具和程序庫(kù)就可以了, 因?yàn)榈讓又苯佑肏ost的kernel,自己只需要提供rootfs就可以了. 因此對(duì)于不同的Linux發(fā)行版, bootfs基本是一致的, rootfs會(huì)有差別,不同的發(fā)行版可以公用bootfs
虛擬機(jī)分鐘級(jí)別,容器秒級(jí).
分層理解
分層的鏡像
鏡像構(gòu)建時(shí),會(huì)一層層構(gòu)建乞巧,前一層是后一層的基礎(chǔ)涨椒。每一層構(gòu)建完就不會(huì)再發(fā)生
改變,后一層上的任何改變只發(fā)生在自己這一層绽媒。比如蚕冬,刪除前一層文件的操作,
實(shí)際不是真的刪除前一層的文件些椒,而是僅在當(dāng)前層標(biāo)記為該文件已刪除播瞳。在最終容
器運(yùn)行的時(shí)候,雖然不會(huì)看到這個(gè)文件免糕,但是實(shí)際上該文件會(huì)一直跟隨鏡像赢乓。
Docker通過存儲(chǔ)引擎(新版本采用快照機(jī)制)的方式來實(shí)現(xiàn)鏡像層堆棧, 并保證多鏡像層對(duì)外展示為統(tǒng)一的文件系統(tǒng).
Docker鏡像都是只讀的,當(dāng)容器啟動(dòng)時(shí),一個(gè)新的可寫層被加載到鏡像的頂部!
這一層就是我們通常說的容器層, 容器直線的都叫鏡像層.
tomcat 作為基礎(chǔ)鏡像pull下來, 需要操作時(shí), 通過run啟動(dòng),新增一個(gè)容器層. 發(fā)布時(shí),將所有打包為一個(gè)鏡像發(fā)布.
定制鏡像
docker commit定制鏡像
啟動(dòng)容器:
docker run --name webserver -d -p 80:80 nginx
這條命令會(huì)用nginx鏡像啟動(dòng)一個(gè)容器,命名為webserver石窑,并且映射了80端口牌芋,這樣我們可以用瀏覽器去訪問這個(gè)nginx服務(wù)器
進(jìn)入容器:
$docker exec -it webserver bash
修改歡迎界面內(nèi)容:即修改了容器的存儲(chǔ)層:
root@3729b97e8226:/#echo'<h1>Hello,Docker!</h1>'>/usr/share/nginx/html/index.html
root@3729b97e8226:/#exit
docker diff 查看容器的具體改動(dòng):實(shí)際上可以看到很多文件被改動(dòng)過。要是安裝部署或其他修改 會(huì)使修改的文件很多松逊,長(zhǎng)此以往使用commit定制的鏡像會(huì)變得非常臃腫躺屁。所以推薦使用
$docker diff webserver
C/root
A/root/.bash
_
history
C/run
C/usr
C/usr/share
C/usr/share/nginx
C/usr/share/nginx/html
C/usr/share/nginx/html/index.html
C/var
C/var/cache
C/var/cache/nginx
A/var/cache/nginx/client_temp
A/var/cache/nginx/fastcgi_temp
A/var/cache/nginx/proxy_temp
A/var/cache/nginx/scgi_temp
A/var/cache/nginx/uwsgi_temp
將容器保存為鏡像:docker commit [選項(xiàng)] <容器ID或容器名> [<倉(cāng)庫(kù)名>[:<標(biāo)簽>]]
$ docker commit\
--author "張三"\
--message "修改了默認(rèn)網(wǎng)頁(yè)"\
webserver\
nginx:v2
sha256:07e33465974800ce65751acc279adc6ed2dc5ed4e0838f8b86f0c87aa1795214
Docker網(wǎng)絡(luò)
容器網(wǎng)絡(luò)是docker為應(yīng)用程序所創(chuàng)造的虛擬環(huán)境的一部分,獨(dú)立于宿主機(jī)操作系統(tǒng)的網(wǎng)絡(luò)環(huán)境经宏,形成容器自有的網(wǎng)絡(luò)設(shè)備犀暑, IP協(xié)議棧, 端口套接字烁兰, IP路由表耐亏, 防火墻等等與網(wǎng)絡(luò)相關(guān)的模塊。
默認(rèn)網(wǎng)絡(luò)
安裝Docker后沪斟,會(huì)默認(rèn)創(chuàng)建三種網(wǎng)絡(luò)广辰, 可以通過docker network ls查看
[root@localhost ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
688d1970f72e bridge bridge local
885da101da7d host host local
f4f1b3cf1b7f none null local
Table
網(wǎng)絡(luò)模式
bridge 為每一個(gè)容器分配,設(shè)置IP等,并將容器連接到一個(gè)docker0虛擬網(wǎng)橋择吊,默認(rèn)為該模式
host 容器將不會(huì)虛擬出自己的網(wǎng)卡李根,配置自己的IP等,而是使用宿主機(jī)的IP和端口
none 容器有獨(dú)立的Network namespace几睛,但并沒有對(duì)其進(jìn)行任何網(wǎng)絡(luò)配置房轿。
container 新創(chuàng)建的容器不會(huì)創(chuàng)建自己的網(wǎng)卡,配置自己的IP枉长,而是和一個(gè)指定的容器共享IP,端口范圍等
bridge模式
在該模式中冀续,Docker守護(hù)進(jìn)程創(chuàng)建了一個(gè)虛擬以太網(wǎng)橋docker0, 新建的容器會(huì)自動(dòng)橋接到這個(gè)接口,附加在其上的任何網(wǎng)卡之間都能自動(dòng)轉(zhuǎn)發(fā)數(shù)據(jù)包必峰。
默認(rèn)情況下洪唐,守護(hù)進(jìn)程會(huì)創(chuàng)建一對(duì)對(duì)等虛擬設(shè)備接口veth pair,將其中一個(gè)接口設(shè)置為容器的etho接口(容器的網(wǎng)卡)吼蚁, 另一個(gè)接口放置在宿主機(jī)的命名空間中凭需, 以類似veth***這樣的名字命名, 從而將宿主機(jī)上的所有容器都連接到這個(gè)內(nèi)部網(wǎng)絡(luò)上肝匆。
使用bridge模式
# 創(chuàng)建容器時(shí)通過參數(shù) --net bridge或--network bridge指定即可(默認(rèn)bridge模式粒蜈,所有也就無需指定)
docker run -it --name bbox01 --network bridge busybox
容器內(nèi)查看ip addr:
宿主機(jī)內(nèi)查看ip addr:
查看容器的IP地址和Gateway信息:
查看所有bridge網(wǎng)絡(luò)模式下的容器:
docker network inspect bridge # 查看所有bridge網(wǎng)絡(luò)模式下的容器
# 在 Containers 節(jié)點(diǎn)中可以看到容器名稱
bridge橋接模式的實(shí)現(xiàn)步驟主要如下:
● Docker Daemon利用veth pair技術(shù), 在宿主機(jī)上創(chuàng)建一對(duì)對(duì)等虛擬設(shè)備接口旗国, 假設(shè)為veth0和veth1枯怖。而veth pair的技術(shù)特性可以保證無論哪一個(gè)veth接受到網(wǎng)絡(luò)報(bào)文,都會(huì)將報(bào)文傳輸給另一方能曾;
● Docker Daemon將veth0附加到Docker Daemon創(chuàng)建的docker0網(wǎng)橋上度硝。 保證宿主機(jī)的網(wǎng)絡(luò)報(bào)文可以發(fā)往veth0;
● Docker Daemon將veth1添加到Docker Container所屬的namespace下寿冕,并被改名為eth0蕊程。
如此一來,宿主機(jī)的網(wǎng)絡(luò)報(bào)文若發(fā)往veth0驼唱,則立即會(huì)被Container的eth0接收藻茂,實(shí)現(xiàn)宿主機(jī)到Docker Container網(wǎng)絡(luò)的聯(lián)通性;同時(shí)玫恳,也保證Docker Container單獨(dú)使用eth0辨赐,實(shí)現(xiàn)容器網(wǎng)絡(luò)環(huán)境的隔離性。
host網(wǎng)絡(luò)模式
● 采用host網(wǎng)絡(luò)模式的Docker Container京办,可以直接使用宿主機(jī)的IP地址與外界進(jìn)行通信掀序,若宿主機(jī)的eth0是一個(gè)公有IP,那么容器也擁有這個(gè)公有IP臂港。同時(shí)容器內(nèi)服務(wù)的端口也可以使用宿主機(jī)的端口,無需額外進(jìn)行NAT轉(zhuǎn)換;
● host網(wǎng)絡(luò)模式可以讓容器共享宿主機(jī)網(wǎng)絡(luò)棧审孽, 這樣的好處時(shí)外部主機(jī)與容器直接通信县袱,但是容器的網(wǎng)絡(luò)缺少隔離性。
使用host網(wǎng)絡(luò)模式
# 在創(chuàng)建容器時(shí)通過參數(shù) --net host 或者 --network host指定
docker run -it --name bbox02 --network host busybox
通過 ip addr查看宿主機(jī)和容器佑力。發(fā)現(xiàn)網(wǎng)卡信息完全一致式散。
容器內(nèi)查看ip addr:
宿主機(jī)查看ip addr:
查看host網(wǎng)絡(luò)模式下的容器
docker network inspect host
# 在Container節(jié)點(diǎn)中可以看到容器名稱。
none網(wǎng)絡(luò)模式
none網(wǎng)絡(luò)模式打颤,即不為Docker Container創(chuàng)建任何的網(wǎng)絡(luò)環(huán)境暴拄,同期內(nèi)部就只能使用loopback網(wǎng)絡(luò)設(shè)備,不會(huì)再有其他的網(wǎng)絡(luò)資源编饺」耘瘢可以說none網(wǎng)絡(luò)模式為Docker Container做了極少的網(wǎng)絡(luò)設(shè)定, 在沒有網(wǎng)絡(luò)配置的情況下透且,作為Docker開發(fā)者撕蔼, 才能在這基礎(chǔ)上做其他無限可能的網(wǎng)絡(luò)定制開發(fā)。
使用none網(wǎng)絡(luò)模式
none網(wǎng)絡(luò)模式是指禁用網(wǎng)絡(luò)功能秽誊, 只有IO接口(local的簡(jiǎn)寫)鲸沮,代表127.0.0.1,即localhost本地回環(huán)地址锅论。
# 在創(chuàng)建容器時(shí)通過參數(shù)--net none或 --network none指定
docker run -it --name bbox03 --network none busybox
查看ip addr:
查看所有none網(wǎng)絡(luò)模式下的容器
docker network inspect none
# 在Container節(jié)點(diǎn)可以看到容器名稱
Container網(wǎng)絡(luò)模式
● Container網(wǎng)絡(luò)模式讼溺,即新創(chuàng)建的容器不會(huì)創(chuàng)建自己的網(wǎng)卡,配置自己的IP最易,而是和指定的容器共享IP怒坯,端口范圍等。同樣兩個(gè)容器除了網(wǎng)絡(luò)方面相同之外耘纱,其他的如文件系統(tǒng)敬肚,進(jìn)程列表等都是隔離的。
● 處于這個(gè)模式下的Docker容器會(huì)共享一個(gè)網(wǎng)絡(luò)棧束析,這樣兩個(gè)容器之間就可以使用localhost高效快速通信艳馒。
使用Container網(wǎng)絡(luò)模式
# 在創(chuàng)建容器時(shí)通過參數(shù)--net container或 --network container指定
# 基于容器bbox01創(chuàng)建了網(wǎng)絡(luò)模式為container的容器bbox04
docker run -it --name bbox04 --network container:bbox01 busybox
查看ip addr:
查看容器bbox01的ip addr信息如下:
宿主機(jī)的ip addr信息如下:
如上:Docker守護(hù)進(jìn)程之創(chuàng)建了一對(duì)對(duì)等虛擬網(wǎng)絡(luò)設(shè)備接口,用于連接bbox1容器和宿主機(jī)员寇,而bbox04容器則直接使用了bbox1容器的網(wǎng)卡信息弄慰。
如果將bbox01容器停止,會(huì)發(fā)現(xiàn)bbox04容器只剩下IO接口了蝶锋。
容器bbox01重啟后陆爽,bbox04容器也重啟一下,就可以獲取到網(wǎng)卡信息了扳缕。
自定義網(wǎng)絡(luò)
● Docker提供的默認(rèn)網(wǎng)絡(luò)模式比較簡(jiǎn)單慌闭,為了保證各容器中應(yīng)用的安全性别威,在實(shí)際開發(fā)中更推薦使用自定義的網(wǎng)絡(luò)進(jìn)行容器管理,以及啟用容器名稱到IP地址的自動(dòng)DNS解析驴剔。
從Docker 1.10版本開始省古, docker daemon實(shí)現(xiàn)了一個(gè)內(nèi)嵌的DNS server,使容器可以直接通過容器名稱通信丧失。方法就是在創(chuàng)建容器時(shí)使用 --name 為容器命名即可豺妓。
但是在使用Docker DNS有個(gè)限制:只能在user-defined網(wǎng)絡(luò)中使用。也就是說布讹,默認(rèn)的bridge網(wǎng)絡(luò)是無法使用DNS的琳拭,所以需要自定義網(wǎng)絡(luò)。
創(chuàng)建網(wǎng)絡(luò)
# 創(chuàng)建一個(gè)基于bridge網(wǎng)絡(luò)模式的自定義網(wǎng)絡(luò)模式custom_network
docker network create custom_network
選項(xiàng): --driver -d 指定網(wǎng)絡(luò)模式 默認(rèn):bridge網(wǎng)絡(luò)模式
docker network create -d bridge my-net
查看網(wǎng)絡(luò)模型:docker network ls
[root@localhost ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
b3634bbd8943 bridge bridge local
062082493d3a custom_network bridge local
885da101da7d host host local
f4f1b3cf1b7f none null local
通過自定義網(wǎng)絡(luò)模式custom_network創(chuàng)建容器
docker run -it --name bbox05 --network custom_network busybox
查看容器的網(wǎng)絡(luò)信息:
docker inspect bbox05
# 在NetworkSettings節(jié)點(diǎn)中可以看到詳細(xì)信息描验。
連接網(wǎng)絡(luò):
通過docker network connect 網(wǎng)絡(luò)名稱 容器名稱 為容器連接新的網(wǎng)絡(luò)模式白嘁。
docker network connect bridge bbox05
通過docker inspect 容器名稱|ID 查看網(wǎng)絡(luò)信息,多增加了默認(rèn)的bridge網(wǎng)絡(luò)模式:
斷開網(wǎng)絡(luò)
通過docker network disconnect 網(wǎng)絡(luò)名稱 容器名稱 命令斷開網(wǎng)絡(luò)挠乳。
移除網(wǎng)絡(luò)
通過docker network rm 網(wǎng)絡(luò)名稱 命令移除自定義網(wǎng)絡(luò)模式权薯,返回網(wǎng)絡(luò)模式名稱。
docker network rm custom_network
注意: 如果通過某個(gè)自定義網(wǎng)絡(luò)模式創(chuàng)建了容器睡扬,則該網(wǎng)絡(luò)模式無法刪除盟蚣。
容器間網(wǎng)絡(luò)通信
容器之間要相互通信,必須要有屬于同一網(wǎng)絡(luò)的網(wǎng)卡卖怜。
步驟:
- 先創(chuàng)建兩個(gè)基于默認(rèn)的bridge網(wǎng)絡(luò)模式的容器
docker run -di --name default_bbox01 busybox
docker run -di --name default_bbox02 busybox
- 通過docker network inspect bridge 查看兩個(gè)容器的具體IP信息屎开。
default_bbox01容器ip: 172.17.0.2
default_bbox02容器ip: 172.17.0.3
-
測(cè)試兩個(gè)容器間是否可以進(jìn)行網(wǎng)絡(luò)通信
這倆個(gè)屬于同一個(gè)網(wǎng)絡(luò)的容器是可以進(jìn)行網(wǎng)絡(luò)通信的,但是IP地址可能是不固定的马靠,又被更改的情況奄抽,那容器內(nèi)所有通信的IP地址也需要進(jìn)行更改,能否使用容器名稱進(jìn)行網(wǎng)絡(luò)通信甩鳄?
-
使用容器名稱進(jìn)行網(wǎng)絡(luò)通信逞度。網(wǎng)絡(luò)不通
docker daemon實(shí)現(xiàn)了一個(gè)內(nèi)嵌的DNS server,使容器可以直接通過容器名稱通信妙啃,只要在創(chuàng)建容器時(shí)使用--name為容器名稱即可档泽。
但是使用Docker DNS有個(gè)限制:只能在user-defined網(wǎng)絡(luò)中使用,也就是說默認(rèn)的bridge網(wǎng)絡(luò)是無法使用DNS的揖赴,所以需要自定義網(wǎng)絡(luò)
- 先基于bridge網(wǎng)絡(luò)模式創(chuàng)建自定義網(wǎng)絡(luò)custom_network馆匿,然后創(chuàng)建兩個(gè)基于自定義網(wǎng)絡(luò)模式的容器
docker network create custom_network # 創(chuàng)建自定義網(wǎng)絡(luò)custom_metwork
docker run -di --name custom_bbox01 --net custom_network busybox # 創(chuàng)建容器custom_bbox01
docker run -di --name custom_bbox02 --network custom_network busybox # 創(chuàng)建容器custom_bbox02
通過docker network inspect custom_network查看兩個(gè)容器的具體IP信息
-
測(cè)試兩個(gè)容器間是否可以進(jìn)行網(wǎng)絡(luò)通信,分別使用具體IP和容器名稱進(jìn)行網(wǎng)絡(luò)通信
結(jié)論:兩個(gè)屬于同一個(gè)自定義網(wǎng)絡(luò)的容器時(shí)可以進(jìn)行網(wǎng)絡(luò)通信的燥滑,并且可以使用容器名稱進(jìn)行網(wǎng)絡(luò)通信渐北。
7.bridge網(wǎng)絡(luò)下的容器和custom_network網(wǎng)絡(luò)下的容器進(jìn)行網(wǎng)絡(luò)通信。
# 讓bridge網(wǎng)絡(luò)下的容器連接至新的custom_network網(wǎng)絡(luò)即可铭拧。
docker network connect custom_network default_bbox01
網(wǎng)絡(luò)互聯(lián) --link
要讓一個(gè)容器連接到另外一個(gè)容器的配置赃蛛,一種方式是在docker create或docker run創(chuàng)建時(shí)通過--link選項(xiàng)配置恃锉。
# 創(chuàng)建了一個(gè)mysql容器, 并命名為mysql呕臂,之后淡喜,另一個(gè)應(yīng)用容器需要鏈接過來。
docker create --link mysql --name webapp -it webapp:latest /bin/bash
注意:必須保證link的容器(mysql)處于start狀態(tài)
dockerfile結(jié)構(gòu)
dockerfile中的內(nèi)容主要是兩種形式诵闭, 以#開頭的注釋行, 和以指定命令字符串開頭的命令行澎嚣。
dockerfile可以理解為自上而下執(zhí)行的腳本文件疏尿, 其中的指令可以分為五大類
基礎(chǔ)指令:用于定義新鏡像的基礎(chǔ)和性質(zhì)
控制指令:是指導(dǎo)鏡像構(gòu)建的核心部分, 用于描述鏡像在構(gòu)建過程中需要執(zhí)行的命令易桃。
引入指令:用于將外部文件直接引用到構(gòu)建鏡像內(nèi)部褥琐。
執(zhí)行指令:能夠?yàn)榛阽R像所創(chuàng)建的容器,指定在啟動(dòng)時(shí)需要執(zhí)行的腳本或命令晤郑。
配置指令:對(duì)鏡像以及基于鏡像所創(chuàng)建的容器敌呈,可以通過配置指令對(duì)其網(wǎng)絡(luò),用戶等內(nèi)容進(jìn)行配置造寝。
官方文檔:https://docs.docker.com/engine/reference/builder/
Docker總架構(gòu)圖:
Docker三個(gè)基本組件:
Docker Client 是用戶界面磕洪,它支持用戶與Docker Daemon之間通信。
Docker Daemon運(yùn)行于主機(jī)上诫龙,處理服務(wù)請(qǐng)求析显。
Docker Index是中央registry,支持擁有公有與私有訪問權(quán)限的Docker容器鏡像的備份
Docker三個(gè)基本元素:
Docker Containers負(fù)責(zé)應(yīng)用程序的運(yùn)行签赃,包括操作系統(tǒng)谷异、用戶添加的文件以及元數(shù)據(jù)。
Docker Images是一個(gè)只讀模板锦聊,用來運(yùn)行Docker容器歹嘹。
DockerFile是文件指令集,用來說明如何自動(dòng)創(chuàng)建Docker鏡像孔庭。
Docker實(shí)現(xiàn)原理
使用Namespaces實(shí)現(xiàn)了系統(tǒng)環(huán)境的隔離尺上,Namespaces允許一個(gè)進(jìn)程以及他的子進(jìn)程從共享的宿主機(jī)內(nèi)核資源(網(wǎng)路棧,進(jìn)程列表史飞,掛載點(diǎn)等)中獲得一個(gè)僅自己可見的隔離區(qū)域尖昏,讓同一個(gè)Namespace下的所有進(jìn)程感知彼此變化,對(duì)外界進(jìn)程一無所知构资,仿佛運(yùn)行在一個(gè)獨(dú)立的操作系統(tǒng)中抽诉;--資源隔離
使用CGroups限制這個(gè)環(huán)境的資源使用情況, 比如一臺(tái)16核32G的機(jī)器上只讓容器使用2核4GB吐绵。使用CGroups還可以為資源設(shè)置權(quán)重迹淌,計(jì)算使用量河绽,操作任務(wù)(進(jìn)程或線程)啟停等;--資源控制
使用鏡像管理功能唉窃,利用Docker的鏡像分層耙饰、寫時(shí)復(fù)制、聯(lián)合掛載技術(shù)實(shí)現(xiàn)了一套完整的容器文件系統(tǒng)即運(yùn)行環(huán)境纹份,在結(jié)合鏡像倉(cāng)庫(kù)苟跪,鏡像可以快速的下載和共享,方便再多環(huán)境部署蔓涧。
Docker的核心模塊功能與實(shí)現(xiàn)分析
Docker系統(tǒng)如下功能來提高容器技術(shù)效率:
○ Namespaces 充當(dāng)隔離的第一級(jí)件已。確保一個(gè)容器中運(yùn)行一個(gè)進(jìn)程而且不能看到或影響容器外的其它進(jìn)程。
○ Control Groups是LXC的重要組成部分元暴,具有資源核算與限制的關(guān)鍵功能篷扩。
○ UnionFS(聯(lián)合文件系統(tǒng))作為容器的構(gòu)建塊。為了支持Docker的輕量級(jí)以及速度快的
● 特性茉盏,它創(chuàng)建層與用戶鉴未。
cgroups(以一組進(jìn)程為目標(biāo)進(jìn)行系統(tǒng)資源分配和控制)
controller group,可以為系統(tǒng)中所運(yùn)行任務(wù)(進(jìn)程)的用戶定義組群分配資源鸠姨,比如CPU時(shí)間铜秆,系統(tǒng)內(nèi)存,網(wǎng)絡(luò)帶寬或這些資源的組合讶迁∮鸱澹可以監(jiān)控配置的cgroup,拒絕cgroup訪問某些資源添瓷,甚至在運(yùn)行的系統(tǒng)中動(dòng)態(tài)配置cgroup梅屉。
提供如下功能:
● Resource limitation:限制資源使用,比如內(nèi)存使用上線以及文件系統(tǒng)的緩存限制鳞贷。
● Prioritization:優(yōu)先級(jí)控制坯汤,比如:CPU利用和磁盤IO吞吐。
● Accounting:一些審計(jì)或一些統(tǒng)計(jì)搀愧,主要目的時(shí)為了計(jì)費(fèi)惰聂。
● Control:掛起進(jìn)程,恢復(fù)執(zhí)行進(jìn)程咱筛。
可以用來完成如下事情:
● 隔離一個(gè)進(jìn)程集合(比如nginx的所有進(jìn)程)搓幌,并限制他們所消費(fèi)的資源,比如綁定CPU的核迅箩。
● 為這組進(jìn)程分配足夠其使用的內(nèi)存
● 為這組進(jìn)程分配相應(yīng)的網(wǎng)絡(luò)帶寬和磁盤存儲(chǔ)限制
● 限制訪問某些設(shè)備(通過設(shè)置設(shè)備的白名單)
cgroups中的重要概念是“子系統(tǒng)”溉愁,也就是資源控制器,每個(gè)子系統(tǒng)就是一個(gè)資源的分配器饲趋,比如CPU子系統(tǒng)就是控制CPU時(shí)間分配的拐揭。 首先掛載子系統(tǒng)撤蟆,然后才有control group的。 比如先掛在memory子系統(tǒng)堂污,然后再menory子系統(tǒng)中創(chuàng)建一個(gè)cgroup節(jié)點(diǎn)家肯,在這個(gè)節(jié)點(diǎn)中, 將需要的控制的進(jìn)程id寫入盟猖,并且將控制的屬性寫入讨衣,這就完成了內(nèi)存的資源限制。
查看linux內(nèi)核中是否啟用的cgroup:("y" 表示已啟用)
內(nèi)存限制
相關(guān)參數(shù):
選項(xiàng) 描述
-m,--memory 內(nèi)存限制式镐,格式是數(shù)字加單位值依,單位可以為 b,k,m,g。最小為 4M
--memory-swap 內(nèi)存+交換分區(qū)大小總限制碟案。格式同上。必須必-m設(shè)置的大
--memory-reservation 內(nèi)存的軟性限制颇蜡。格式同上
--oom-kill-disable 是否阻止 OOM killer 殺死容器价说,默認(rèn)沒設(shè)置
--oom-score-adj 容器被 OOM killer 殺死的優(yōu)先級(jí),范圍是[-1000, 1000]风秤,默認(rèn)為 0
--memory-swappiness 用于設(shè)置容器的虛擬內(nèi)存控制行為鳖目。值為 0~100 之間的整數(shù)
--kernel-memory 核心內(nèi)存限制。格式同上缤弦,最小為 4M
用戶內(nèi)存限制(-memory 和 --memory-swap)
容器能使用的內(nèi)存和交換分區(qū)大小
-m, --memory 內(nèi)存限制领迈,格式是數(shù)字加單位别智,單位可以是b,k,m,g勤众,最小為4M
--memory-swap 內(nèi)存+交換分區(qū)大小總限制肺孵,必須比-m設(shè)置的大.
四種設(shè)置方式:
1. 不設(shè)置
不設(shè)置 --memory和 --memory-swap买窟,容器默認(rèn)可以使用完宿主機(jī)的所有內(nèi)存和swap分區(qū)补箍。不過注意皱碘,如果容器占用宿主機(jī)的所有內(nèi)存和swap分區(qū)超過一段時(shí)間后压昼,會(huì)被宿主機(jī)系統(tǒng)殺死(如果沒有設(shè)置 --oom-likk-disable=true的話)
2. 設(shè)置 --memory送滞,不設(shè)置 --memory-swap
給--memory設(shè)置一個(gè)不小于4M的值斋陪,不設(shè)置--menory-swap朽褪,或者將--memory-swap設(shè)置為0。容器能使用的內(nèi)存大小為a无虚,能使用的交換分區(qū)大小也是a缔赠。因?yàn)镈ocker默認(rèn)容器交換分區(qū)的大小和內(nèi)存相同。
$ docker run -m 1G nginx /bin/bash 該容器能使用的內(nèi)存大小為1G友题,能使用的swap分區(qū)大小也是1G嗤堰,容器內(nèi)的進(jìn)程能申請(qǐng)到的總內(nèi)存大小為2G.
3. 設(shè)置 --memory=a, memory-swap=b, 且b>a
a是能使用的內(nèi)存大小, b是能使用的內(nèi)存+swwp分區(qū)大小度宦。
$ docker run --memory 1G --memory-swap 3G nginx:1.0 /bin/bash
4. 設(shè)置 --memory=a, --memory-swap=1
給--memory設(shè)置為正常值梁棠,給--memory-swap設(shè)置成-1置森。這種情況表示限制容器能使用的內(nèi)存大小為a, 而不限制容器額能使用的swap分區(qū)大小。 這時(shí)候符糊,容器內(nèi)進(jìn)程能申請(qǐng)到的內(nèi)存大小為a+宿主機(jī)的swap大小凫海。
內(nèi)存的軟性限制(--memory-reservation)
是一種軟性限制,用于節(jié)制容器內(nèi)存使用男娄。給 --memory-reservation設(shè)置一個(gè)比--memory小的值后行贪,雖然容器最多可以使用--memroy使用的內(nèi)存大小,但宿主機(jī)內(nèi)存資源緊張時(shí)模闲,在系統(tǒng)下次內(nèi)存回收時(shí)建瘫,系統(tǒng)會(huì)回收容器的部分內(nèi)存頁(yè),強(qiáng)迫容器內(nèi)存占用回到--memory-reservation設(shè)置的大小尸折。
沒有設(shè)置時(shí)(默認(rèn)情況下) --memory-reservation的值和-m限制的值相同啰脚。 設(shè)置為0時(shí) 會(huì)比-m的參數(shù)大,等同于沒設(shè)置实夹。
$ docker run -it -m 500M --memory-reservation 200M ubuntu:16.04 /bin/bash
如果容器使用了大于200M但小于500M內(nèi)存時(shí)橄浓,下次系統(tǒng)的內(nèi)存回收會(huì)嘗試將容器的內(nèi)存鎖緊到200M以下。
$ docker run -it --memory-reservation 1G ubuntu:16.04 /bin/bash
容器可以使用盡可能多的內(nèi)存亮航, --menory-reservation確保容器不會(huì)長(zhǎng)時(shí)間占用太多內(nèi)存荸实。·
OMM killer
默認(rèn)情況下缴淋,在出現(xiàn)out-of-memory(OOM)錯(cuò)誤時(shí)准给,系統(tǒng)會(huì)殺死容器內(nèi)的進(jìn)程來獲取更多空閑內(nèi)存,這個(gè)殺死進(jìn)程來節(jié)省內(nèi)存的進(jìn)程重抖,稱之為OOMkiller露氮。可以通過設(shè)置 --oom-kill-disable選項(xiàng)來禁止OOM killer 殺死容器內(nèi)進(jìn)程钟沛。 但是請(qǐng)確保只有在使用了-m/--memory 選項(xiàng)時(shí)才使用 --oom-kill-disable禁用OOMKiller沦辙。如果沒有設(shè)置-m選項(xiàng),卻禁用了OOM-Killer讹剔,可能會(huì)造成出現(xiàn)out-of-memory錯(cuò)誤時(shí)油讯,系統(tǒng)通過殺死宿主機(jī)進(jìn)程獲取更多內(nèi)存。
$ docker run -it -m 100M --oom-kill-disable ubuntu:16.04 /bin/bash
限制容器內(nèi)存為100M延欠,并禁止OOM Killer:(正確使用)
$ docker run -it --oom-kill-disable ubuntu:16.04 /bin/bash
沒有限制容器內(nèi)存大小陌兑,并禁用了OOM Killer:(錯(cuò)誤使用)
容器沒有限制內(nèi)存, 可能會(huì)導(dǎo)致系統(tǒng)無內(nèi)存可用由捎, 并嘗試殺死系統(tǒng)進(jìn)程來獲取更多可用內(nèi)存兔综。
一般一個(gè)容器只有一個(gè)進(jìn)程,這個(gè)唯一進(jìn)程被殺死,容器也就被殺死了软驰,可以通過 --oom-score-adj 選項(xiàng)來設(shè)置在系統(tǒng)內(nèi)存不夠時(shí)涧窒,容器被殺死的優(yōu)先級(jí)。設(shè)置負(fù)數(shù)不可能被殺死锭亏,正值有可能被殺死纠吴。
核心內(nèi)存限制
核心內(nèi)存和用戶內(nèi)存不同的地方在于核心內(nèi)存不能被交換出, 不能交換出的特性使得容器可以通過消耗太多內(nèi)存來堵塞一些系統(tǒng)服務(wù)慧瘤。核心內(nèi)存包括:
-stack pages(棧頁(yè)面)
-slab pages
-socket memory pressure
-tcp memory pressure
$ docker run -it -m 500M --kernel-memory 50M ubuntu:16.04 /bin/bash
容器中的進(jìn)程最多使用500M內(nèi)存戴已,在這500M中, 最多只有50M核心內(nèi)存
$ docker run -it --kernel-memory 50M ubuntu:16.04 /bin/bash
沒有設(shè)置用戶內(nèi)存锅减, 所以在容器中可以使用盡可能多的內(nèi)存糖儡,但是最多使用50M核心內(nèi)存
Swappiness
默認(rèn)情況下,容器的內(nèi)核可以交換出一定比例的匿名頁(yè)怔匣, --memory-swappiness就是用來設(shè)置這個(gè)比例的握联。 --menory-swappiness 可以設(shè)置為從0到100。0表示關(guān)閉匿名頁(yè)交換每瞒。100表示所有的匿名頁(yè)都可以交換金闽。默認(rèn)情況下,如果不使用 --memory-swappiness独泞,則該值從父進(jìn)程繼承而來。
$ docker run -it --memory-swappiness=0 ubuntu:16.04 /bin/bash
CPU限制
概述
Docker提供的CPU資源限制選項(xiàng)可以在多核系統(tǒng)上限制容器能利用那些vCPU苔埋。而對(duì)容器最多能使用的CPU時(shí)間有兩種限制方式:
- 有多個(gè)CPU密集型的容器競(jìng)爭(zhēng)CPU時(shí)懦砂,設(shè)置各個(gè)容器能使用的CPU時(shí)間相對(duì)比例。
- 以絕對(duì)的方式設(shè)置容器在每個(gè)調(diào)度周期內(nèi)最多能使用的CPU時(shí)間
CPU限制相關(guān)參數(shù)
docker run 命令和CPU限制相關(guān)的所有選項(xiàng)如下
選項(xiàng) 描述
--cpuset-cpus="" 允許使用的CPU集组橄, 值可以為0-3荞膘,0, 1
-c,--cpu-shares=0 CPU共享權(quán)值(相對(duì)權(quán)重)
--cpu-period=0 限制CPU CFS的周期玉工, 范圍從1ms~1s羽资,即[1000, 1000000]
--cpu-quota=0 限制CPU CFS配額,必須不小于1ms遵班,即>-1000
--cpuset-mems="" 允許在上執(zhí)行的內(nèi)存節(jié)點(diǎn)(MEMs),只對(duì)NUMA系統(tǒng)有效
其中 :
--cpuset-cpus 用于設(shè)置容器可以使用的vCPU核屠升,
-c, --cpu-shares用于設(shè)置多個(gè)容器競(jìng)爭(zhēng)CPU時(shí),各個(gè)容器相對(duì)能分配到的CPU時(shí)間比例狭郑。
--cpu-period 和--cpu-quata 用于據(jù)對(duì)設(shè)置容器能使用CPU時(shí)間腹暖。
CPU集
設(shè)置容器可以在那些CPU核上運(yùn)行
如下,表示容器中的進(jìn)程可以在cpu1和cpu3上執(zhí)行
$ docker run -it --cpuset-cpus="1,3" ubuntu:16.04 /bin/bash
如下翰萨,表示容器中的進(jìn)程可以在cpu0脏答, cpu1及cpu2上執(zhí)行
$ docker run -it --cpuset-cpus="0-2" ubuntu:16.04 /bin/bash
在NUMA系統(tǒng)上,可以設(shè)置容器可以使用的內(nèi)存節(jié)點(diǎn)
如下,表示容器中的進(jìn)程只能使用內(nèi)存節(jié)點(diǎn)1和3上的內(nèi)存
$ dcoker run -it --cpuset-mems="1,3" ubuntu:16.04 /bin/bash
如下殖告,表示容器中的進(jìn)程只能使用內(nèi)存節(jié)點(diǎn)0,1,2上的內(nèi)存
$ docker run -it --cpuset-mems="0-2" ubuntu:16.04 /bin/bash
CPU資源的相對(duì)限制
默認(rèn)情況下阿蝶,所有的容器得到同等比例的CPU周期。在有多個(gè)容器競(jìng)爭(zhēng)CPU時(shí)我們可以設(shè)置每個(gè)容器能使用的CPU時(shí)間比例黄绩。這個(gè)比例叫做共享權(quán)值羡洁。通過-c 或 --cpu-shares 設(shè)置。Docker默認(rèn)每個(gè)容器的權(quán)值為1024.不設(shè)置或?qū)⑵湓O(shè)置為0宝与,都將使用這個(gè)默認(rèn)值焚廊。系統(tǒng)會(huì)根據(jù)每個(gè)容器的共享權(quán)值和所有容器共享權(quán)值和比例來給容器分配CPU時(shí)間。
注意:這個(gè)比例只有在CPU密集型的任務(wù)執(zhí)行時(shí)才有用习劫。在四核的系統(tǒng)上咆瘟, 假設(shè)有4個(gè)單進(jìn)程的容器,他們每一個(gè)都能各自使用一個(gè)核的100% CPU時(shí)間诽里。不管他們的cpu共享權(quán)值時(shí)多少(前提時(shí)未設(shè)置---cpuset-cpus 限制使用的核)
如下袒餐,多于3核心的系統(tǒng)。 用-c=512的選項(xiàng)啟動(dòng)容器 c1谤狡,且該容器只有一個(gè)進(jìn)程灸眼。用 -c=1024的選項(xiàng)啟動(dòng)容器c2,且該容器有兩個(gè)進(jìn)程墓懂。CPU權(quán)值分布可能如下
PID container CPU CPU share
100 {C0} 0 100% of CPU0
101 {C1} 1 100% of CPU1
102 {C1} 2 100% of CPU2
CPU資源的絕對(duì)限制
linux通過 CFS (Completely Fair Scheduler焰宣,完全公平調(diào)度器)來調(diào)度各個(gè)進(jìn)程對(duì)CPU的使用。CFS默認(rèn)的調(diào)度周期時(shí)100ms
CFS周期的有效范圍是1ms~1s
--cpu-period 設(shè)置容器進(jìn)程的調(diào)度周期捕仔,范圍1000~1000000
--cpu-quota 設(shè)置每個(gè)周期內(nèi)容器能使用的CPU時(shí)間 >=1000匕积。 兩者結(jié)合使用
如下,將CFS調(diào)度的周期設(shè)為50000榜跌, 將容器在每個(gè)周期內(nèi)的CPU配額設(shè)置未25000, 表示該容器每50ms可以得到50%的CPU運(yùn)行時(shí)間闪唆。
$ docker run -it --cpu-period=50000 --cpu-quota=25000 ubuntu:16.04 /bin/bash
將配額設(shè)置為周期的兩倍,表示在每個(gè)周期可以使用兩個(gè)vCPU的100%時(shí)間
$ docker run -it --cpu-period=50000 --cpu-quota=25000 ubuntu:16.04 /bin/bash
正確的理解“絕對(duì)”
參數(shù)--cpu-quota設(shè)置容器在調(diào)度周期內(nèi)使用cpu時(shí)間钓葫,其實(shí)是一個(gè)上限悄蕾。
如下,啟動(dòng)一個(gè)容器础浮,并將其綁定到cpu1上執(zhí)行帆调,設(shè)置--cpu-period和--cpu-quota都設(shè)置為50000。
docker run -rm --name test01 --cpu-cpus 1 --cpu-period 50000 --cpu-quota 50000 deadloop /bin/bash
觀察改容器對(duì)CPU的使用率在100%左右豆同。
$ docker stats test01
再使用相同參數(shù)啟動(dòng)另一個(gè)容器
docker run -rm --name test02 --cpu-cpus 1 --cpu-period 50000 --cpu-quota 50000 deadloop /bin/bash
觀察兩個(gè)容器贷帮,每個(gè)容器對(duì)cpu的使用率在50%左右。說明容器并沒有在每個(gè)周期內(nèi)使用50000的cpu時(shí)間
$ docker stats test01 test02
結(jié)束第二個(gè)容器诱告, 增加-c 2048參數(shù) 重新啟動(dòng)
$ docker stop test02
$ docker run -rm --name test02 --cpu-cpus 1 --cpu-period 50000 --cpu-quota 50000 -c 2048 deadloop /bin/bash
再次觀察容器cpu的使用率撵枢, test01使用率在33%左右民晒, test02使用率在66%左右。 第二個(gè)容器的共享值是2048锄禽,第一個(gè)容器test01的默認(rèn)共享值是1024.
磁盤IO配額控制
參數(shù) IO寫速度配置 device-write-bps
docker run -it --name test --device-write-bps /dev/sda:1mb ubuntu:16.04
容器的寫磁盤速度被限制到了1MB/s
容器空間大小限制
在daemon啟動(dòng)參數(shù)中潜必,使用dm.basesize來指定,重啟docker daemon服務(wù)沃但。
若docker使用devicemapper作為驅(qū)動(dòng)存儲(chǔ)磁滚,重啟會(huì)導(dǎo)致宿主機(jī)上的所有本地鏡像和容器被清理。
Docker如何運(yùn)行APP
構(gòu)建一個(gè)鏡像宵晚。
如前面所述垂攘,Docker Image是一個(gè)構(gòu)建容器的只讀模板,它包含了容器啟動(dòng)所需的所有信息淤刃,包括運(yùn)行哪些進(jìn)程和配置數(shù)據(jù)晒他。所有的鏡像都會(huì)基于一個(gè)基本鏡像構(gòu)建,緊接著會(huì)根據(jù)Dockerfile中的指令創(chuàng)建模板逸贾,對(duì)于每個(gè)指令陨仅,在鏡像上創(chuàng)建一個(gè)新的層。一旦鏡像創(chuàng)建完成铝侵,就可以將它們推送到中央registry:Docker Index灼伤,以供他人使用。然而咪鲜,Docker Index為鏡像提供了兩個(gè)級(jí)別的訪問權(quán)限:公有和私有訪問狐赡。您可以將鏡像存儲(chǔ)在私有倉(cāng)庫(kù)。Docker官網(wǎng)有私有倉(cāng)庫(kù)的套餐可以供你選擇疟丙∮敝叮總之,公有庫(kù)是可搜索和可重復(fù)使用的隆敢,而私有庫(kù)只能給擁有權(quán)限的成員訪問发皿。Docker Client可用于Docker Index內(nèi)的鏡像搜索崔慧。運(yùn)行容器拂蝎。
運(yùn)行容器源于我們?cè)诘谝徊街袆?chuàng)建的鏡像。當(dāng)一個(gè)容器被啟動(dòng)后惶室,一個(gè)讀寫層會(huì)被添加到鏡像的頂層温自。當(dāng)分配合適的網(wǎng)絡(luò)和IP地址后,最應(yīng)用程序就可以在容器中運(yùn)行了皇钞。
Docker鏡像(image):
Docker鏡像是一個(gè)特殊的文件系統(tǒng)悼泌,除了提供容器運(yùn)行時(shí)所需的程序、庫(kù)夹界、資源馆里、配置等文件外,還包含了一些為運(yùn)行時(shí)準(zhǔn)備的一些配置參數(shù)(如匿名卷、環(huán)境變量鸠踪、用戶等)丙者。鏡像不包含任何動(dòng)態(tài)數(shù)據(jù),其內(nèi)容在構(gòu)建之后也不會(huì)被改變营密。
分層存儲(chǔ):
docker鏡像鏡像并非是像一個(gè)ISO那樣的打包文件械媒,鏡像只是一個(gè)虛擬的概念,其實(shí)際體現(xiàn)并非由一個(gè)文件組成评汰,而是由一組文件系統(tǒng)組成纷捞,或者說,由多層文件系統(tǒng)聯(lián)合組成被去。
鏡像構(gòu)建時(shí)主儡,會(huì)一層層構(gòu)建,前一層是后一層的基礎(chǔ)编振。每一層構(gòu)建完就不會(huì)再發(fā)生改變缀辩,后一層上的任何改變只發(fā)生在自己這一層。比如踪央,刪除前一層文件的操作臀玄,實(shí)際不是真的刪除前一層的文件,而是僅在當(dāng)前層標(biāo)記為該文件已刪除畅蹂。在最終容器運(yùn)行的時(shí)候健无,雖然不會(huì)看到這個(gè)文件,但是實(shí)際上該文件會(huì)一直跟隨鏡像液斜。
Docker容器:
鏡像是靜態(tài)的文件累贤,容器是鏡像運(yùn)行時(shí)的實(shí)體。
容器的實(shí)質(zhì)是進(jìn)程少漆。容器(進(jìn)程)特點(diǎn):進(jìn)程運(yùn)行于屬于自己的獨(dú)立的命名空間臼膏。因此容器可以擁有自己的root文件系統(tǒng)、自己的網(wǎng)絡(luò)配置示损、自己的進(jìn)程空間渗磅,甚至自己的用戶ID空間。容器內(nèi)的進(jìn)程是運(yùn)行在一個(gè)隔離的環(huán)境里检访,使用起來始鱼,就好像是在一個(gè)獨(dú)立于宿主的系統(tǒng)下操作一樣。
每一個(gè)容器運(yùn)行時(shí)脆贵,是以鏡像為基礎(chǔ)層医清,在其上創(chuàng)建一個(gè)當(dāng)前容器的存儲(chǔ)層,我們可以稱這個(gè)為容器運(yùn)行時(shí)讀寫而準(zhǔn)備的存儲(chǔ)層為容器存儲(chǔ)層卖氨』崂樱可以理解鏡像是一個(gè)只包含只讀層的文件系統(tǒng)负懦。容器以鏡像為基礎(chǔ),在多層文件之上添加了一層讀寫層(容器存儲(chǔ)層)柏腻,他的生存周期與容器一樣密似。 當(dāng)刪除容器的讀寫層后,容器也就恢復(fù)為一個(gè)鏡像葫盼。 可以使用數(shù)據(jù)卷跳過讀寫層直接對(duì)宿主機(jī)進(jìn)行讀寫操作残腌,而數(shù)據(jù)卷的生命周期獨(dú)立于容器,使用數(shù)據(jù)卷贫导,容器可以隨意刪除抛猫,而數(shù)據(jù)不會(huì)丟失。
Docker Registry:一個(gè)集中的存儲(chǔ)孩灯、分發(fā)鏡像的服務(wù)
一個(gè)DockerRegistry中可以包含多個(gè)倉(cāng)庫(kù)(Repository)闺金;每個(gè)倉(cāng)庫(kù)可以包含多個(gè)標(biāo)簽(Tag);每個(gè)標(biāo)簽對(duì)應(yīng)一個(gè)鏡像峰档。