[TOC] 一、Docker介紹 1.1 什麼是Docker Docker是一個開源的應用容器引擎,使用Go語言開發,基於Linux內核的cgroup,namespace,Union FS等技術,對應用進程進行封裝隔離,並且獨立於宿主機與其他進程,這種運行時封裝的狀態稱為容器。 Docker ...
目錄
- 一、Docker介紹
- 二、Docker安裝
- 三、鏡像管理
- 四、容器管理
- 五、管理應用程式數據
- 六、容器網路
- 七、Dockerfile
- 八、企業級鏡像倉庫Harbor
- 九、圖形化界面管理
- 十、構建容器監控系統
一、Docker介紹
1.1 什麼是Docker
Docker是一個開源的應用容器引擎,使用Go語言開發,基於Linux內核的cgroup,namespace,Union FS等技術,對應用進程進行封裝隔離,並且獨立於宿主機與其他進程,這種運行時封裝的狀態稱為容器。
Docker早期版本實現是基於LXC,併進一步對其封裝,包括文件系統、網路互聯、鏡像管理等方面,極大簡化了容器管理。從0.7版本以後開始去除LXC,轉為自省研發的libcontainer,從1.11版本開始,進一步為使用runC和containerd。
Docker理念是將應用及依賴包打包到一個可移植的容器中,可發佈到任意Linux發行版Docker引擎上。使用沙箱機制運行程式,程式之間相互隔離。
1.2 Docker體繫結構
Containerd:是一個簡單的守護進程,使用runC管理容器。向Docker Engine提供介面。
Shim:只負責管理一個容器。
runC:是一個輕量級的工具,只用來運行容器。
- Docker Client:客戶端
- Docker Daemon:守護進程
- Docker Images:鏡像
- Docker Container:容器
- Docker Registry:鏡像倉庫
1.3 Docker內部組件
- Namespaces
命名空間,Linux內核提供的一種對進程資源隔離的機制,例如進程、網路、掛載點等資源。
- CGroup
控制組,Linux內核提供的一種限制進程資源的機制;例如CPU、記憶體等資源。
- UnionFS
聯合文件系統,支持將不同位置的目錄掛載到同一虛擬文件系統,形成一種分層的模型。
1.4 什麼是容器?
- 對軟體和其依賴的標準化打包
- 應用之間相互隔離
- 共用同一個OS Kernel
- 可以運行在很多主流操作系統上
1.5 容器和虛擬機的區別
以KVM為例與Docker對比
- 啟動時間
Docker妙級啟動,KVM分鐘級啟動。
- 輕量級
容器鏡像帶下通常以M為單位,虛擬機以G為單位。
容器資源占用小,要比虛擬機部署更快捷。
- 性能
容器共用宿主機內核,系統級虛擬化,占用資源少,沒有Hypervisor層開銷,容器性能基本接近物理機;
虛擬機需要Hypervisior層支持,虛擬化一些設備,具備完整的GuestOS,虛擬化開銷大,因而降低性能,沒有容器性能好。
- 安全性
由於共用宿主機內核,只是進程級隔離,因此隔離性和穩定性不如虛擬機,容器具有一定許可權訪問宿主機內核,存在一定安全隱患。
- 使用要求
KVM基於硬體的完全虛擬化、需要贏家CPU虛擬化技術支持;
容器共用所主機內核,可運行在主流的Linux發行版,不用考慮CPU是否支持虛擬化技術。
1.6 虛擬化+容器
二、Docker安裝
2.1 Docker官方網站
https://wwww.docker.com
2.2 Docker版本
- 社區版(Community Edition,CE)
- 企業版(Enterprise Edition,EE)
2.3支持平臺
- Linux(CentOS,Debian,Fedora,Oracle Linux,RHEL,SUSE和Ubuntu)
- Mac
- Windows
2.4 Linux安裝Docker
2.4.1 Docker文檔
https://docs.docker.com
https://docs.docker.com/install/linux/docker-ce/centos/#set-up-the-repository
2.4.2 安裝Docker
2.4.2.1關閉防火牆
systemctl stop firewalld
systemctl disable firewalld
2.4.2.2關閉selinux
vi /etc/selinux/config
SELINUX=disabled #設置為disabled
reboot #重啟伺服器
# 查看selinux狀態
[root@localhost ~]# getenforce
Disabled
2.4.2.3安裝所需的包
yum install -y yum-utils device-mapper-persistent-data lvm2
2.4.2.4配置yum源
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
2.4.2.5安裝docker-ce
yum install docker-ce -y
2.4.2.6啟動
systemctl start docker
# 加入開機啟動
systemctl enable docker
2.4.2.7運行hello-world
docker run hello-world
2.4.2.8查看docker版本
[root@localhost ~]# docker info
Containers: 1
Running: 0
Paused: 0
Stopped: 1
Images: 1
Server Version: 18.09.0
Storage Driver: overlay2
Backing Filesystem: xfs
Supports d_type: true
Native Overlay Diff: true
Logging Driver: json-file
Cgroup Driver: cgroupfs
Plugins:
Volume: local
Network: bridge host macvlan null overlay
Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
Swarm: inactive
Runtimes: runc
Default Runtime: runc
Init Binary: docker-init
containerd version: c4446665cb9c30056f4998ed953e6d4ff22c7c39
runc version: 4fc53a81fb7c994640722ac585fa9ca548971871
init version: fec3683
Security Options:
seccomp
Profile: default
Kernel Version: 3.10.0-862.el7.x86_64
Operating System: CentOS Linux 7 (Core)
OSType: linux
Architecture: x86_64
CPUs: 1
Total Memory: 1.779GiB
Name: localhost.localdomain
ID: JDCF:RJAD:HIZF:ZAGM:EZNS:46YY:I2AM:OKBH:PRCS:AQBB:4DGT:X3RZ
Docker Root Dir: /var/lib/docker
Debug Mode (client): false
Debug Mode (server): false
Registry: https://index.docker.io/v1/
Labels:
Experimental: false
Insecure Registries:
127.0.0.0/8
Live Restore Enabled: false
Product License: Community Engine
[root@localhost ~]# docker version
Client:
Version: 18.09.0
API version: 1.39
Go version: go1.10.4
Git commit: 4d60db4
Built: Wed Nov 7 00:48:22 2018
OS/Arch: linux/amd64
Experimental: false
Server: Docker Engine - Community
Engine:
Version: 18.09.0
API version: 1.39 (minimum version 1.12)
Go version: go1.10.4
Git commit: 4d60db4
Built: Wed Nov 7 00:19:08 2018
OS/Arch: linux/amd64
Experimental: false
2.4.2.9查看運行了哪些docker
[root@localhost ~]# docker run -it nginx <<== -it前臺運行、再打開一個終端用於查看
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
336509fd6799 nginx "nginx -g 'daemon of…" 8 minutes ago Up 8 minutes 80/tcp epic_ride
2.4.2.10查看容器信息
[root@localhost ~]# docker inspect 336509fd6799 <<==容器的id,用docker ps查看得到
[
{
"Id": "336509fd679988cf9e22d9fb1157e3bed5695aeb91d8d706b903b4943f33c30d",
"Created": "2018-11-08T12:30:38.462038658Z",
"Path": "nginx",
"Args": [
"-g",
"daemon off;"
],
"State": {
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 1926,
"ExitCode": 0,
"Error": "",
"StartedAt": "2018-11-08T12:30:38.800291064Z",
"FinishedAt": "0001-01-01T00:00:00Z"
},
"Image": "sha256:62f816a209e6b57dd5fe98c1994fe3ab19ba4e1fee2a5ec6d77f303be4ed90e9",
"ResolvConfPath": "/var/lib/docker/containers/336509fd679988cf9e22d9fb1157e3bed5695aeb91d8d706b903b4943f33c30d/resolv.conf",
"HostnamePath": "/var/lib/docker/containers/336509fd679988cf9e22d9fb1157e3bed5695aeb91d8d706b903b4943f33c30d/hostname",
"HostsPath": "/var/lib/docker/containers/336509fd679988cf9e22d9fb1157e3bed5695aeb91d8d706b903b4943f33c30d/hosts",
"LogPath": "/var/lib/docker/containers/336509fd679988cf9e22d9fb1157e3bed5695aeb91d8d706b903b4943f33c30d/336509fd679988cf9e22d9fb1157e3bed5695aeb91d8d706b903b4943f33c30d-json.log",
"Name": "/epic_ride",
"RestartCount": 0,
"Driver": "overlay2",
"Platform": "linux",
"MountLabel": "",
"ProcessLabel": "",
"AppArmorProfile": "",
"ExecIDs": null,
"HostConfig": {
"Binds": null,
"ContainerIDFile": "",
"LogConfig": {
"Type": "json-file",
"Config": {}
},
"NetworkMode": "default",
"PortBindings": {},
"RestartPolicy": {
"Name": "no",
"MaximumRetryCount": 0
},
"AutoRemove": false,
"VolumeDriver": "",
"VolumesFrom": null,
"CapAdd": null,
"CapDrop": null,
"Dns": [],
"DnsOptions": [],
"DnsSearch": [],
"ExtraHosts": null,
"GroupAdd": null,
"IpcMode": "shareable",
"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": 0,
"NanoCpus": 0,
"CgroupParent": "",
"BlkioWeight": 0,
"BlkioWeightDevice": [],
"BlkioDeviceReadBps": null,
"BlkioDeviceWriteBps": null,
"BlkioDeviceReadIOps": null,
"BlkioDeviceWriteIOps": null,
"CpuPeriod": 0,
"CpuQuota": 0,
"CpuRealtimePeriod": 0,
"CpuRealtimeRuntime": 0,
"CpusetCpus": "",
"CpusetMems": "",
"Devices": [],
"DeviceCgroupRules": null,
"DiskQuota": 0,
"KernelMemory": 0,
"MemoryReservation": 0,
"MemorySwap": 0,
"MemorySwappiness": null,
"OomKillDisable": false,
"PidsLimit": 0,
"Ulimits": null,
"CpuCount": 0,
"CpuPercent": 0,
"IOMaximumIOps": 0,
"IOMaximumBandwidth": 0,
"MaskedPaths": [
"/proc/acpi",
"/proc/kcore",
"/proc/keys",
"/proc/latency_stats",
"/proc/timer_list",
"/proc/timer_stats",
"/proc/sched_debug",
"/proc/scsi",
"/sys/firmware"
],
"ReadonlyPaths": [
"/proc/asound",
"/proc/bus",
"/proc/fs",
"/proc/irq",
"/proc/sys",
"/proc/sysrq-trigger"
]
},
"GraphDriver": {
"Data": {
"LowerDir": "/var/lib/docker/overlay2/31cc93e4ef8b9da5b5d98bc9a68cfdd8c1ba2a31bf65bcb21754defd68d85c5d-init/diff:/var/lib/docker/overlay2/240731a3ae18beffce7a5053fb4b45c4a93c52c14b2b18e25751bd5ef5bce0b5/diff:/var/lib/docker/overlay2/613cf356b8ebdacffabca1e2f03c02102a19d13df25caef091c10858ec058731/diff:/var/lib/docker/overlay2/82d2821d41013463c69c23a8c1e58a96ab84ae9c6399a181d0b37f0459c8007b/diff",
"MergedDir": "/var/lib/docker/overlay2/31cc93e4ef8b9da5b5d98bc9a68cfdd8c1ba2a31bf65bcb21754defd68d85c5d/merged",
"UpperDir": "/var/lib/docker/overlay2/31cc93e4ef8b9da5b5d98bc9a68cfdd8c1ba2a31bf65bcb21754defd68d85c5d/diff",
"WorkDir": "/var/lib/docker/overlay2/31cc93e4ef8b9da5b5d98bc9a68cfdd8c1ba2a31bf65bcb21754defd68d85c5d/work"
},
"Name": "overlay2"
},
"Mounts": [],
"Config": {
"Hostname": "336509fd6799",
"Domainname": "",
"User": "",
"AttachStdin": true,
"AttachStdout": true,
"AttachStderr": true,
"ExposedPorts": {
"80/tcp": {}
},
"Tty": true,
"OpenStdin": true,
"StdinOnce": true,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"NGINX_VERSION=1.15.6-1~stretch",
"NJS_VERSION=1.15.6.0.2.5-1~stretch"
],
"Cmd": [
"nginx",
"-g",
"daemon off;"
],
"ArgsEscaped": true,
"Image": "nginx",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": null,
"Labels": {
"maintainer": "NGINX Docker Maintainers <[email protected]>"
},
"StopSignal": "SIGTERM"
},
"NetworkSettings": {
"Bridge": "",
"SandboxID": "f98bbeec0b3b1822c8dd90123c99c7e8225470140148e1dc6075d0bf2685d74b",
"HairpinMode": false,
"LinkLocalIPv6Address": "",
"LinkLocalIPv6PrefixLen": 0,
"Ports": {
"80/tcp": null
},
"SandboxKey": "/var/run/docker/netns/f98bbeec0b3b",
"SecondaryIPAddresses": null,
"SecondaryIPv6Addresses": null,
"EndpointID": "a6b4036fb031698c228b5b2567da7b07df949a960bffbe119645e88a9730cb27",
"Gateway": "172.17.0.1",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"MacAddress": "02:42:ac:11:00:02",
"Networks": {
"bridge": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"NetworkID": "8a60ffdd13c42e28bfa9f6431d0264c790781ff8b5238dfc1f3af34c3d36d9ca",
"EndpointID": "a6b4036fb031698c228b5b2567da7b07df949a960bffbe119645e88a9730cb27",
"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
}
}
}
}
]
[root@localhost ~]# curl -I 172.17.0.2
HTTP/1.1 200 OK
Server: nginx/1.15.6
Date: Thu, 08 Nov 2018 12:43:20 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 06 Nov 2018 13:32:09 GMT
Connection: keep-alive
ETag: "5be197d9-264"
Accept-Ranges: bytes
2.4.2.11進入容器中
[root@localhost ~]# docker exec -it 336509fd6799 bash
root@336509fd6799:/# ls
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
root@336509fd6799:/# exit
exit
三、鏡像管理
3.1 鏡像是什麼
- 一個分層存儲的文件
- 一個軟體的環境
- 一個鏡像可以創建N個容器
- 一種標準化的交付
- 一個不包含Linux內核而又精簡的Linux操作系統
鏡像不是一個單一的文件,而是有多層構成。我們可以通過docker history
[root@localhost ~]# docker history nginx <<== 查看鏡像有哪些分層
IMAGE CREATED CREATED BY SIZE COMMENT
62f816a209e6 37 hours ago /bin/sh -c #(nop) CMD ["nginx" "-g" "daemon… 0B
<missing> 37 hours ago /bin/sh -c #(nop) STOPSIGNAL [SIGTERM] 0B
<missing> 37 hours ago /bin/sh -c #(nop) EXPOSE 80/tcp 0B
<missing> 37 hours ago /bin/sh -c ln -sf /dev/stdout /var/log/nginx… 22B
<missing> 37 hours ago /bin/sh -c set -x && apt-get update && apt… 53.8MB
<missing> 37 hours ago /bin/sh -c #(nop) ENV NJS_VERSION=1.15.6.0.… 0B
<missing> 37 hours ago /bin/sh -c #(nop) ENV NGINX_VERSION=1.15.6-… 0B
<missing> 3 weeks ago /bin/sh -c #(nop) LABEL maintainer=NGINX Do… 0B
<missing> 3 weeks ago /bin/sh -c #(nop) CMD ["bash"] 0B
<missing> 3 weeks ago /bin/sh -c #(nop) ADD file:f8f26d117bc4a9289… 55.3MB
[root@localhost ~]# cd /var/lib/docker/
[root@localhost docker]# ls
builder buildkit containerd containers image network overlay2 plugins runtimes swarm tmp trust volumes
[root@localhost docker]# cd overlay2/
[root@localhost overlay2]# ls
240731a3ae18beffce7a5053fb4b45c4a93c52c14b2b18e25751bd5ef5bce0b5
31cc93e4ef8b9da5b5d98bc9a68cfdd8c1ba2a31bf65bcb21754defd68d85c5d
31cc93e4ef8b9da5b5d98bc9a68cfdd8c1ba2a31bf65bcb21754defd68d85c5d-init
613cf356b8ebdacffabca1e2f03c02102a19d13df25caef091c10858ec058731
802c4abe1551fbbba1e4445b149852e2b0a8eb969adc2a45955d60ea88cdd370
82d2821d41013463c69c23a8c1e58a96ab84ae9c6399a181d0b37f0459c8007b
b5044ef06828dd2656c0d59f03cd854917033fe8ebd2e26bc3332b359cfcc148
b5044ef06828dd2656c0d59f03cd854917033fe8ebd2e26bc3332b359cfcc148-init
backingFsBlockDev
l
3.1.1 鏡像從那裡來?
Docker Hub是由Docker公司負責維護的公共註冊中心,包含大量的容器鏡像,Docker工具預設從這個公共鏡像庫下載鏡像。地址:https://hub.docker.com/explore
3.1.2 配置鏡像加速器
https://www.daocloud.io/mirror
curl -sSL https://get.daocloud.io/daotools/set_mirror.sh | sh -s http://f1361db2.m.daocloud.io
systemctl restart docker
3.2 鏡像與容器聯繫
如圖,容器其實是在鏡像的最上面加了一層讀寫層,在運行容器里文件改動時,會先從鏡像裡面要寫的文件複製到容器自己的文件系統中(讀寫層)。
如果容器刪除了,最上面的讀寫層也就被刪除了,改動也就丟失了。所以無論多少個容器共用一個鏡像,所做的寫操作都是從鏡像的文件系統中複製過來操作的,並不會修改鏡像的源文件,這種方式提高磁碟利用率。
若想持久化這些改動,可以通過docker commit將容器保存成一新的鏡像。
root@localhost ~]# docker run -itd nginx
5ba9e0be87ade5e68481bface386c8ef592bb80bbe7bf28cf1572e832c8ce355
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5ba9e0be87ad nginx "nginx -g 'daemon of…" 51 seconds ago Up 50 seconds 80/tcp sharp_mayer
[root@localhost ~]# docker exec -it 5ba9e0be87ad bash
root@5ba9e0be87ad:/# ls
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
root@5ba9e0be87ad:/# touch nginx.txt
root@5ba9e0be87ad:/# exit
exit
[root@localhost ~]# docker inspect 5ba9e0be87ad
....
# 存儲驅動
GraphDriver": {
"Data": {
"LowerDir": "/var/lib/docker/overlay2/44cfba513bee96fa98dd85ef9cbf8a88f8286c90291b498a615be6f590bda66a-init/diff:/var/lib/docker/overlay2/240731a3ae18beffce7a5053fb4b45c4a93c52c14b2b18e25751bd5ef5bce0b5/diff:/var/lib/docker/overlay2/613cf356b8ebdacffabca1e2f03c02102a19d13df25caef091c10858ec058731/diff:/var/lib/docker/overlay2/82d2821d41013463c69c23a8c1e58a96ab84ae9c6399a181d0b37f0459c8007b/diff",
"MergedDir": "/var/lib/docker/overlay2/44cfba513bee96fa98dd85ef9cbf8a88f8286c90291b498a615be6f590bda66a/merged",
"UpperDir": "/var/lib/docker/overlay2/44cfba513bee96fa98dd85ef9cbf8a88f8286c90291b498a615be6f590bda66a/diff",
"WorkDir": "/var/lib/docker/overlay2/44cfba513bee96fa98dd85ef9cbf8a88f8286c90291b498a615be6f590bda66a/work"
},
"Name": "overlay2"
},
...
[root@localhost ~]# cd /var/lib/docker/overlay2/44cfba513bee96fa98dd85ef9cbf8a88f8286c90291b498a615be6f590bda66a
[root@localhost 44cfba513bee96fa98dd85ef9cbf8a88f8286c90291b498a615be6f590bda66a]# ls
diff link lower merged work
[root@localhost 44cfba513bee96fa98dd85ef9cbf8a88f8286c90291b498a615be6f590bda66a]# ls diff/ # 與驚喜差異
nginx.txt root run var
[root@localhost 44cfba513bee96fa98dd85ef9cbf8a88f8286c90291b498a615be6f590bda66a]# ls merged/ <<==Nginx工作的數據驅動存儲
bin boot dev etc home lib lib64 media mnt nginx.txt opt proc root run sbin srv sys tmp usr var
[root@localhost 44cfba513bee96fa98dd85ef9cbf8a88f8286c90291b498a615be6f590bda66a]# ls work/
work
3.3 管理鏡像常用命令
docker image --help
指令 | 描述 |
---|---|
ls | 列出鏡像 |
build | 構建鏡像來自Dockerfile |
history | 查看鏡像歷史 |
inspect | 顯示一個或多個鏡像詳細信息 |
pull | 推送一個鏡像到鏡像倉庫 |
rm | 移除一個或多個鏡像 |
prune | 移除未使用的鏡像。沒有被標記或被任何容器引用的。 |
tag | 創建一個引用源鏡像標記目標鏡像 |
export | 導出容器文件系統到tar歸檔文件 |
import | 導入容器文件系統tar歸檔創建鏡像 |
save | 保存一個或多個鏡像到tar歸檔文件 |
load | 載入鏡像來自tar歸檔或標準輸入 |
四、容器管理
4.1 創建容器常用選項
docker container run --help
選項 | 描述 |
---|---|
-i,-interactive | 互動式 |
-t,-tty | 分配一個偽終端 |
-d,-detach | 運行容器到後臺 |
-e,-env | 設置環境變數 |
-p,-publish list | 發佈容器埠到主機 |
-P,-publish-all | 發佈容器所有EXPOSE埠到宿主機隨機埠 |
-name string | 指定容器名稱 |
-h,-hostname | 設置容器主機名 |
-ip string | 指定容器IP,只能用於自定義網路 |
-network | 連接容器到一個網路 |
-mount mount | 將文件系統附加到容器 |
-v,-volume list | 綁定掛載一個捲 |
-restart string | 容器退出時重啟策略,預設no,可選值:[always|on-failure] |
4.2 容器資源限制
選項 | 描述 |
---|---|
-m,-memory | 容器可以使用的最大記憶體量 |
-memory-swap | 允許交換磁碟的記憶體量 |
-memory-swappiness=<0-100> | 容器使用SWAP分區交換的百分比(0-100,預設為-1) |
-oom-kill-disable | 禁用OOM Killer |
-cpus | 可以使用的CPU數量 |
-cpuset-cpus | 限制容器使用特定的CPU核心,(0-3,0,1) |
-cpu-shares | CPU共用(相對權重) |
示例:
4.2.1 記憶體限額
允許容器最多使用500M記憶體和100M的swap,並禁用OOM Killer:
# 允許使用的swap=memory-swap - memory
# memory-swap='-1'時,無限制使用swap
# memory-swap 不設置時,預設swap的值時memory的2倍
# memory-swap的值等於memory值時,禁用swap
docker run -d --name Nginx01 --memory="500m" --memory-swap="600M" --oom-kill-disable nginx
4.2.2 CPU限額
允許容器最多使用一個半的CPU:
docker run -d --name nginx04 --cpus="1.5" nginx
允許容器最多使用50%的CPU:
docker run -d --name nginx05 --cpus='.5' nginx
4.3 管理容器常用命令
docker container --help
選項 | 描述 |
---|---|
ls | 列出容器 |
inspect | 查看一個或多個容器詳細信息 |
commit | 創建一個新鏡像來自一個容器 |
cp | 拷貝文件/文件夾到一個容器 |
logs | 獲取一個容器日誌 |
port | 列出或指定容器埠映射 |
top | 顯示一個容器運行的進程 |
stats | 顯示容器資源使用統計 |
stop/start | 停止/啟動一個或多個容器 |
rm | 刪除一個或多個容器 |
五、管理應用程式數據
5.1 將宿主機數據掛載到容器中的三種方式
Docker提供三種方式數據從宿主機掛載到容器中:
- Volumes:Docker管理宿主機文件系統的一部分(/var/lib/docker/volumes)。保存數據的最佳方式。
- bind mounts:將宿主機上的任意位置的文件或者目錄掛載到容器中。
- tmpfs:掛載存儲在主機系統的記憶體中,而不會寫入主機的文件系統。如果不希望將數據持久化存儲到任何位置,可以使用tmpfs,同時避免寫入容器可寫層提高性能。
5.2 Volume
- 管理捲
docker volume create nginx-vol
docker volume ls
docker volume inspect nginx-vol
- 用捲創建一個容器
# 新語法
docker run -d --name=nginx-test --mount src=nginx-vol,dst=/usr/share/nginx/html nginx
# 舊語法
docker run -d --name=nginx-test -v nginx-vol:/usr/share/nginx/html nginx
- 清理
docker stop nginx-test
docker rm nginx-test
docker volume rm nginx-vol
註意:
1. 如果沒有指定捲,自動創建。
2. 建議使用—mount,更通用。
https://docs.docker.com/engine/admin/volumes/volumes/#start-a-container-with-a-volume
5.3 Bind Mounts
- 用捲創建一個容器
# 新語法
docker run -d --name=nginx-test --mount type=bind,src=/app/wwwroot,dst=/usr/share/nginx/html nginx
# 舊語法
docker run -d --name=nginx-test -v /app/wwwroot:/usr/share/nginx/html nginx
- 驗證綁定
docker inspect nginx-test
- 清理
docker stop nginx-test
docker rm nginx-test
註意:
1.2 如果源文件/目錄沒有存在,不會自動創建,會拋出一個錯誤。
1.3 如果掛載目標在容器中非空目錄,則該目錄現有內容將被隱藏。
https://docs.docker.com/engine/admin/volumes/bind-mounts/#start-a-container-with-a-bind-mount
Volume特點
- 多個運行容器之間共用數據。
- 當容器停止或悲移除時,該捲依然存在。
- 多個容器可以同時掛載相同的捲。
- 當明確刪除捲時,捲才會被刪除。
- 將容器的數據存儲在遠程主機或其他存儲上
- 將數據從一臺Docker主機遷移到另一臺時,先停止容器,然後備份捲的目錄(/var/lib/docker/volumes)
Bind Mounts特點
- 從主機共用配置文件到容器。預設情況下,掛載主機/etc/resolv.conf到每個容器,提供DNS解析。
- 在Docker主機上的開發環境和容器之間共用源代碼。例如,可以將Maven target目錄掛載到容器中,每次在Docker主機上構建Maven項目時,容器都可以訪問構建的項目包。
- 當Docker主機的文件或目錄結構保證與容器所需的綁定掛載一致時。
六、容器網路
6.1 Docker四種網路模式
- bridge
-net=bridge
預設網路,Docker啟動後創建一個docker0網橋,預設創建的容器也是添加到這個網橋中。
- host
-net=host
容器不會獲得一個獨立的network namespace,而是與宿主機共用一個,這就意味著容器不會有自己的網卡信息,而是使用宿主機的。容器除了網路,其他都是隔離的。
- none
-net=none
獲取獨立的network namespave,但不為容器進行任何網路配置,需要我們手動配置。
- container
-net=container:Name/ID
與指定的容器使用同一個network namespace,具有同樣的網路配置信息,兩個容器除了網路,其他都還黑隔離的。
- 自定義網路
與預設的bridge原理一樣,但自定義網路具備內部DNS發現,可以通過容器名或者主機名容器之間網路通信。
6.2 容器網路訪問原理
Linux IP信息包過濾原理:
Docker主要通過netfilter/iptables實現網路通信。
iptables由netfilter和iptables組成,netfilter組件是Linux內核集成的信息包過濾系統,它維護一個信息包過濾表,這個表用於控制信息包過濾處理的規則集,而iptables只是一個在用戶空間的工具,用於增刪改查這個過濾表的規則。
表 | 鏈 |
---|---|
filter(過濾) | INPUT、OUTPUT、FORWARD |
nat(地址轉換) | PREROUTING、POSTROUTING、OUTPUT |
mangle(拆包、修改、封裝) | INPUT、OUTPUT、PREROUTING、 POSTROUTING、OUTPUT |
raw(數據包狀態跟蹤) | PREROUTING、OUTPUT |
容器訪問外部
# iptables -t nat -nL
Chain POSTROUTING (policy ACCEPT) target prot opt source MASQUERADE all -- 172.17.0.0/16
destination
0.0.0.0/0
外部訪問容器
Chain DOCKER (2 references) target prot opt source DNAT tcp -- 0.0.0.0/0
destination
0.0.0.0/0
tcp dpt:88 to:172.18.0.2:80
6.3 橋接宿主機網路與配置固定IP
- 臨時生效
# 網橋名稱
br_name=br0
# 添加網橋
brctl addbr $br_name
# 給網橋設置IP
ip addr add 192.168.1.120/24 dev $br_name
# 刪除已存在的eth0網卡配置
ip addr del 192.168.1.120/24 dev eth0
# 激活網卡
ip link set $br_name up
# 添加eth0到網橋
brctl addif $br_name eth0
# 添加路由
ip route add default via 192.168.1.1 dev br0
還需要在Docker啟動時橋街這個網橋:
# vi /usr/lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd -b=br0
# systemctl restart docker
- 永久生效
# vi /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0
TYPE=Ethernet
ONBOOT=yes
BRIDGE=br0
# vi /etc/sysconfig/network-scripts/ifcfg-br0
DEVICE=br0
TYPE=Bridge
ONBOOT=yes
BOOTPROTO=static
IPADDR=192.168.3.10
NETMASK=255.255.255.0
GATEWAY=192.168.3.1
DNS1=114.114.114.114
- 配置固定IP
C_ID=$(docker run -itd --net=none ubuntu)
C_PID=$(docker inspect -f '{{.State.Pid}}' $C_ID)
# 創建network namespace目錄並將容器的network namespace軟連接到此目錄,以便ip netns命令讀取 mkdir -p /var/run/netns
ln -s /proc/$C_PID/ns/net /var/run/netns/$C_PID
# 添加虛擬網卡veth+容器PID,類型是veth pair,名稱是vp+容器PID
ip link add veth$C_PID type veth peer name vp$C_PID
# 添加虛擬網卡到br0網橋
brctl addif br0 veth$C_PID
# 激活虛擬網卡
ip link set veth$C_PID up
# 設置容器網路信息
IP='192.168.0.123/24'
GW='192.168.0.1'
# 給進程配置一個network namespace
ip link set vp$C_PID netns $C_PID
# 在容器進程裡面設置網卡信息
ip netns exec $C_PID ip link set dev vp$C_PID name eth0
ip netns exec $C_PID ip link set eth0 up
ip netns exec $C_PID ip addr add $IP dev eth0
ip netns exec $C_PID ip route add default via 192.168.1.1
- pipework工具配置容器固定IP
git clone https://github.com/jpetazzo/pipework.git cp pipework/pipework /usr/local/bin/
docker run -itd --net=none --name test01 ubuntu pipework br0 test01 192.168.0.123/[email protected]
七、Dockerfile
7.1 Dockerfile格式
FROM centos:latest
MAINTAINER huwl
RUN yum install gcc -y
COPY run.sh /usr/bin
EXPOSE 80
CMD ['run.sh]
7.2 Dockerfile常用指令
指令 | 描述 |
---|---|
FROM | 構建新鏡像是基於那個鏡像 |
MAINTAINER | 鏡像維護者姓名或郵箱地址 |
RUN | 構建鏡像時運行的Shell命令 |
COPY | 拷貝文件或目錄到鏡像中 |
ENV | 設置環境變數 |
USER | 為RUN、CMD和ENTRPOTIN執行命令指定運行用戶 |
EXPOSE | 聲明容器運行的服務埠 |
HEALTHCHECK | 容器中服務健康檢查 |
WORKDIR | 為RUN、CMD、ENTRYPOTIN、COPY和ADD設置工作目錄 |
ENTRYPOIN | 運行容器時執行,如果有多個ENTRYPOIN指令,最後一個生效 |
CMD | 運行容器時執行,如果有多個CMD指令,最後一個生效 |
7.3 Build構建鏡像
Usage:docker build [OPTIONS] PATH | URL | - [flags]
Options:
-t, --tag list # 鏡像名稱
-f,--file string #指定Dockerfile文件位置
# docker build .
# docker bulid -t shykes/myapp .
# docker bulid -t shykes/myapp -f /path/Dockerfile /path
# docker bulid -t shykes/myapp http://www.example.com/Dockerfile
7.4 企業應用案例
7.4.1 構建Nginx基礎鏡像
- Dockerfile
FROM centos:7
RUN yum install -y gcc gcc-c++ make openssl-devel pcre-devel dg-devel iproute net-tools telnet wget curl && yum clean all && rm -rf /var/cache/yum/*
RUN wget http://nginx.org/download/nginx-1.15.5.tar.gz && tar zxf nginx-1.15.5.tar.gz && cd nginx-1.15.5 && ./configure --prefix=/usr/local/nginx --with-http_ssl_module --with-http_stub_status_module && make && make install
ENV PATH $PATH:/usr/local/nginx/sbin
WORKDIR /usr/local/nginx
EXPOSE 80
CMD ["./sbin/nginx","-g","daemon off;"]
- 構建鏡像
docker build -t nginx:v1 -f Dockerfile .
# Successfully built 373a0bdefe50
# Successfully tagged nginx:v1
[root@localhost /]# docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx v1 373a0bdefe50 56 seconds ago 335MB
<none> <none> d582c01a839f 4 minutes ago 200MB
nginx latest 62f816a209e6 2 days ago 109MB
centos 7 75835a67d134 4 weeks ago 200MB
hello-world latest 4ab4c602aa5e 2 months ago 1.84kB
- 啟動測試
[root@localhost /]# docker run -d --name nginx100 -p 80:80 nginx:v1
a29daf4614116f7dba18461e871d1a45ec9b55f722a98bead791c12294b9f1d3
[root@localhost /]# docker ps -l
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a29daf461411 nginx:v1 "./sbin/nginx -g 'da…" 6 seconds ago Up 5 seconds 0.0.0.0:80->80/tcp nginx100
[root@localhost /]# curl -I http://192.168.56.146/
HTTP/1.1 200 OK
Server: nginx/1.15.5
Date: Fri, 09 Nov 2018 12:34:03 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Fri, 09 Nov 2018 12:29:20 GMT
Connection: keep-alive
ETag: "5be57da0-264"
Accept-Ranges: bytes
7.4.2 構建PHP基礎鏡像
- dockerfile
FROM centos:7
RUN yum install -y gcc gcc-c++ make gd-devel libxml2-devel libcurl-devel libjpeg-devel libpng-devel openssl-devel
ADD php-5.6.31.tar.gz /tmp/
RUN cd /tmp/php-5.6.31 && \
./configure --prefix=/usr/local/php \
--with-config-file-path=/usr/local/php/etc \
--with-mysql --with-mysqli \
--with-openssl --with-zlib --with-curl --with-gd \
--with-jpeg-dir --with-png-dir --with-iconv \
--enable-fpm --enable-zip --enable-mbstring && \
make -j 4 && \
make install && \
cp /usr/local/php/etc/php-fpm.conf.default /usr/local/php/etc/php-fpm.conf && \
sed -i "s/127.0.0.1/0.0.0.0/" /usr/local/php/etc/php-fpm.conf && \
sed -i "21a \daemonize = no" /usr/local/php/etc/php-fpm.conf
COPY php.ini /usr/local/php/etc
RUN rm -rf /tmp/php-5.6.31* && yum clean all
WORKDIR /usr/local/php
EXPOSE 9000
CMD ["./sbin/php-fpm", "-c", "/usr/local/php/etc/php-fpm.conf"]
- 構建php鏡像
docker build -t php:v1 -f dockerfile .
- 啟動測試
[root@localhost php]# docker run -d --name php01 php:v1
ed5276251a6bf5124efba4b314d29a2dbfd12ddc0e0c3371ea16184a07c12bbc
[root@localhost php]# docker ps -l
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ed5276251a6b php:v1 "./sbin/php-fpm -c /…" 5 seconds ago Up 4 seconds 9000/tcp php01
[root@localhost php]# docker exec -it php01 bash
[root@ed5276251a6b php]# ls
bin etc include lib php sbin var
[root@ed5276251a6b php]# sbin/php-fpm -v
PHP 5.6.31 (fpm-fcgi) (built: Nov 10 2018 01:10:28)
Copyright (c) 1997-2016 The PHP Group
Zend Engine v2.6.0, Copyright (c) 1998-2016 Zend Technologies
7.4.3 構建Tomcat基礎鏡像並項目測試
- dockerfile
FROM centos:7
ADD jdk-8u45-linux-x64.tar.gz /usr/local
ENV JAVA_HOME /usr/local/jdk1.8.0_45
ADD apache-tomcat-8.0.46.tar.gz /usr/local
COPY server.xml /usr/local/apache-tomcat-8.0.46/conf
RUN rm -f /usr/local/*.tar.gz
WORKDIR /usr/local/apache-tomcat-8.0.46
EXPOSE 8080
ENTRYPOINT ["./bin/catalina.sh", "run"]
- 構建Tomcat鏡像
docker build -t tomcat:v1 -f Dockerfile .
- 啟動測試
[root@localhost tomcat]# docker run -d --name tomcat01 -p 8080:8080 tomcat:v1
b9ba85bc64748c90ebe8df19e41c36490881cbcf174dab00d127ae6bf1141814
[root@localhost tomcat]# curl -I http://192.168.56.146:8080
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=UTF-8
Transfer-Encoding: chunked
Date: Sat, 10 Nov 2018 01:26:59 GMT
7.5.1 快速部署LNMP網站平臺
- 創建自定義網路
docker network create lnmp
- 創建MySQL容器
docker run -d --name lnmp_mysql --net lnmp --mount src=mysql-vol,dst=/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -e MYSQL_DATABASE=wordpress mysql:5.7 --character-set-server=utf8
- 創建PHP容器
docker run -d --name lnmp_php --net lnmp --mount src=wwwroot,dst=/wwwwroot php:v1
- 創建Nginx容器
docker run -d --name lnmp_nginx --net lnmp -p 80:80 --mount type=bind,src=$(pwd)/nginx.conf,dst=/usr/local/nginx/conf/nginx.conf --mount src=wwwroot,dst=/wwwroot nginx:v1
- 以wordpress博客為例
https://cn.wordpress.org/wordpress-4.9.4-zh_CN.tar.gz
八、企業級鏡像倉庫Harbor
8.1 Harbor介紹
Habor是由VMWare公司開源的容器鏡像倉庫。事實上,Habor是在Docker Registry上進行了相應的企業級擴展,從而獲得了更加廣泛的應用,這些新的企業級特性包括:管理用戶界面,基於角色的訪問控制,AD/DALP集成以及審計日誌等,足以滿足基本企業需求。
官方地址:https://vmware.github.io/harbor/cn/
組件 | 功能 |
---|---|
harbor-adminserver | 配置管理中心 |
harbor-db | MySQL資料庫 |
harbor-jobservice | 負責鏡像複製 |
harbor-log | 記錄操作日誌 |
harbor-ui | web管理頁面和API |
Nginx | 前端代理,負責前端頁面和鏡像上傳或下載轉發 |
reids | 會話 |
registry | 鏡像存儲 |
8.2 Harbor部署
Harbor安裝有3種方式:
- 線上安裝:從Docker Hub下載Harbor相關鏡像,因此安裝軟體包非常小
- 離線安裝:安裝包包含部署的相關鏡像,因此安裝包比較大
- OVA安裝程式:當用戶具有vCenter環境時,使用此安裝程式,在部署OVA後啟動Harbor
離線安裝下載地址:https://github.com/goharbor/harbor/releases
- 部署
curl -L "https://github.com/docker/compose/releases/download/1.22.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
tar xf harbor-offline-installer-v1.6.1.tgz
cd harbor
vim harbor.cfg
harbor_admin_password = Harbor12345
./prepare
./install.sh
[root@localhost harbor]# docker-compose ps
Name Command State Ports
-------------------------------------------------------------------------------------------------------------------------------------
harbor-adminserver /harbor/start.sh Up (healthy)
harbor-db /entrypoint.sh postgres Up (healthy) 5432/tcp
harbor-jobservice /harbor/start.sh Up
harbor-log /bin/sh -c /usr/local/bin/ ... Up (healthy) 127.0.0.1:1514->10514/tcp
harbor-ui /harbor/start.sh Up (healthy)
nginx nginx -g daemon off; Up (healthy) 0.0.0.0:443->443/tcp, 0.0.0.0:4443->4443/tcp, 0.0.0.0:80->80/tcp
redis docker-entrypoint.sh redis ... Up 6379/tcp
registry /entrypoint.sh /etc/regist ... Up (healthy) 5000/tcp
- 訪問
http://192.168.56.146/harbor/sign-in
8.3 Harbor基礎使用
- 預設上傳鏡像連接使用https,添加http受信任
[root@localhost harbor]# cat /etc/docker/daemon.json
{
"registry-mirrors": ["http://f1361db2.m.daocloud.io"],
"insecure-registries": ["192.168.56.146"] #<<= 加入harbor的地址
}
- 重啟docker
systemctl restart docker
在Harbor web管理——“系統管理”——“用戶管理”——新建用戶,在——“項目”——“library倉庫” ——“成員”把之前添加的用戶進來並賦予許可權
- 登錄倉庫上傳鏡像
docker tag nginx:v1 192.168.56.146/library/nginx:v1
docker login harbor地址
docker push 192.168.56.146/library/nginx:v1
九、圖形化界面管理
9.1 Portainer
官網:https://portainer.io
https://portainer.io/install.html
Portainer是一個開源、輕量級Docker管理用戶界面,基於Docker API,可管理Docker主機或Swarm集群,支持最新版Docker和Swarm模塊。
- 創建捲
docker volume create portainer_data
- 創建Portainer容器
docker run -d -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer
- 訪問portainer
http://192.168.56.146:9000
十、構建容器監控系統
10.1 cAdvisor+InfluxDB+Grafna
- 創建monitor
docker network create monitor
- Influxdb
docker run -d --name influxdb --net monitor -p 8083:8083 -p 8086:8086 tutum/influxdb
- cAdvisor
docker run -d --name=cadvisor --net monitor -p 8081:8080 --mount type=bind,src=/,dst=/rootfs,ro --mount type=bind,src=/var/run,dst=/var/run --mount type=bind,src=/sys,dst=/sys,ro --mount type=bind,src=/var/lib/docker/,dst=/var/lib/docker,ro google/cadvisor -storage_driver=influxdb -storage_driver_db=cadvisor -storage_driver_host=influxdb:8086
- Grafana
docker run -d --name grafana --net monitor -p 3000:3000 grafana/grafana