1,概述
虛擬化技術:容器(應用層)、虛擬機(軟件層)
docker:隔離,鏡像占用資源小,秒級
vm:GB級
docker基於Go語言開發的
2,docker基礎
2.1,架構
圖1 架構圖
鏡像(image):
docker鏡像就像一個模板,例如:redis鏡像》run》redis容器(對外提供服務)
一個鏡像可以創建多個容器!!!
容器(container):
利用容器技術獨立運行一個或者一組應用,通過鏡像創建
啟動、停止、刪除
倉庫(repository):類似github、gitlab代碼倉庫
存放鏡像的地方:公有倉庫和私有倉庫
2.2,安裝docker
圖2 查看自己的服務器內核情況
圖3 通過數據庫
# 1,先刪除老版本
sudo apt-get remove docker docker-engine docker.io containerd runc
# 2,設置倉庫
sudo apt-get update
sudo apt-get install \
ca-certificates \
curl \
gnupg \
lsb-release
# 3,直接進入阿里雲docker加速鏡像設置國內的鏡像地址(https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors)
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://g8kfoxhi.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
# 4,安裝docker
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io
# 5,查看是否安裝成功(執行hello-world程序)
docker search hello-world
docker pull hello-world
docker run hello-world
# 其他 docker的資源路徑
/var/lib/docker
# 如果想要協助該資源則可以直接
rm -rf /var/lib/docker
2.3,docker hello-world啟動流程
圖4 docker鏡像啟動流程
2.4,底層原理
docker是怎么工作?
docker是一個Client-Server結構的系統,docker的守護進程運行在主機上。通過socket從客戶端訪問!
圖5 docker底層
docker為什么比虛擬機快?
1,docker只在應用層進行抽象
2,docker(秒級別)利用的是宿主機的內核,vm(分鍾級別)需要Guest OS
所以說,新建一個容器的時候,docker不需要像虛擬機那樣重新加載一個操作系統內核,避免引導!
圖6 虛擬機與docker架構區別
圖7 docker與虛擬機的性能差異
備注:當前docker也支持全平台
2.5,docker常用命令
幫助命令
docker version # 顯示版本
docker info # 系統信息
docker [命令] --help # 幫忙命令
鏡像命令
docker images # 查看所有鏡像
REPOSITORY
搜索
docker search [namelike]
Options:
-f, --filter filter Filter output based on conditions provided
--format string Pretty-print search using a Go template
--limit int Max number of search results (default 25)
--no-trunc Don't truncate output
下載
docker pull [name] # 如果不寫tag,默認就是latest
Usage: docker pull [OPTIONS] NAME[:TAG|@DIGEST]
Pull an image or a repository from a registry
Options:
-a, --all-tags Download all tagged images in the repository
--disable-content-trust Skip image verification (default true)
--platform string Set platform if server is multi-platform capable
-q, --quiet Suppress verbose output
例如:
docker pull mysql
docker pull docker.io/library/mysql:latest # 等價
刪除鏡像
docker rmi -f ${docker images -qa} # 刪除所有
docker rmi -f [鏡像id 鏡像id ...] # 刪除單個或多個
容器命令
docker run [可選參數] image
--name #容器名稱
-d #后台方式運行
-it #使用交換方式運行,進入容器查看內容
-p #指定容器的端口 例如 -p 8080:8080
-p ip:主機端口:容器端口
-p 主機端口:容器端口(常用)
-P #隨機一個端口
# 測試centos
[root@iZbp1jbs6mikemed8a6mooZ:~]# docker run -it centos /bin/bash
[root@9f7972f753e0 /]# ls
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
[root@9f7972f753e0 /]# exit
列出所有運行的容器
docker ps #顯示所有正在運行的容器
docker ps -a #顯示所有容器
docker ps -n #顯示n個
docker ps -q #只顯示id
退出容器
exit #直接容器停止退出
ctrl +p +q
刪除容器
docker rm [id] #只能刪除未運行
docker rm -f [id] #強制刪除所有容器
docker rm -f ${docker ps -aq} #強制刪除所有容器
docker ps -a -q|xargs docker rm #刪除所有容器
啟動和停止容器
docker start [id]
docker restart [id]
docker stop [id]
docker kill [id] #強制停止
常用的其他命令
docker run -d [name] # 后台啟動
# 常見的坑:docker容器使用后台運行,就必須要有一個前台進程,docker發現沒有應用,就會自動停止
日志
Usage: docker logs [OPTIONS] CONTAINER
Fetch the logs of a container
Options:
--details Show extra details provided to logs
-f, --follow Follow log output
--since string Show logs since timestamp (e.g. 2013-01-02T13:23:37Z) or relative (e.g. 42m for 42 minutes)
-n, --tail string Number of lines to show from the end of the logs (default "all")
-t, --timestamps Show timestamps
--until string Show logs before a timestamp (e.g. 2013-01-02T13:23:37Z) or relative (e.g. 42m for 42 minutes)
# 樣例
docker logs -f -t --tail 100 ba8c6c794fae # 查看最近的100條日志
docker logs -ft ba8c6c794fae # 查看最近的100條日志
docker run -d centos /bin/sh -c "while true;do echo wanyu;sleep 1;done"
查看容器中的進程信息
[root@iZbp1jbs6mikemed8a6mooZ:~]# docker top acba17f136c3
UID PID PPID C STIME TTY TIME CMD
root 859775 859753 0 Nov29 ? 00:00:00 nginx: master process nginx -g daemon off;
systemd+ 859834 859775 0 Nov29 ? 00:00:00 nginx: worker process
systemd+ 859835 859775 0 Nov29 ? 00:00:00 nginx: worker process
查看docker中容器的狀態
docker stats
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
1196c69ed611 webdav-aliyundriver 1.86% 404.3MiB / 7.429GiB 5.32% 151MB / 144MB 49.2kB / 152kB 48
6cde4548c0a8 consul 0.15% 22.07MiB / 7.429GiB 0.29% 289kB / 8.53MB 12.8MB / 478MB 10
3fe6fe9b36e0 zipkin 0.18% 262.2MiB / 7.429GiB 3.45% 190kB / 4.79MB 58.7MB / 86kB 48
acba17f136c3 nginx 0.00% 5.898MiB / 7.429GiB 0.08% 109kB / 118kB 3.96MB / 0B 5
ba8c6c794fae rabbitmq 0.17% 111.6MiB / 7.429GiB 1.47% 1.42MB / 4.9MB 8.44MB / 94.2kB 25
3457dfb68671 postgres 0.00% 28.11MiB / 7.429GiB 0.37% 671kB / 533kB 14.7MB / 249MB 7
1ba5c5143b3c redis-test 0.27% 7.52MiB / 7.429GiB 0.10% 468kB / 947kB 3.74MB / 24.6kB 5
b4e6a28e2ec3 nexus 0.64% 1.572GiB / 7.429GiB 21.17% 5.06MB / 18.5MB 6.34MB / 308MB 106
查看容器的信息
Usage: docker inspect [OPTIONS] NAME|ID [NAME|ID...]
Return low-level information on Docker objects
Options:
-f, --format string Format the output using the given Go template
-s, --size Display total file sizes if the type is container
--type string Return JSON for specified type
點擊查看docker inspect [id]
[root@iZbp1jbs6mikemed8a6mooZ:~]# docker inspect ba8c6c794fae [ { "Id": "ba8c6c794faed04c6d72d5fe44ee81856ee786175325c33bb99899cab2e54ea9", "Created": "2021-11-15T01:00:05.26730652Z", "Path": "docker-entrypoint.sh", "Args": [ "rabbitmq-server" ], "State": { "Status": "running", "Running": true, "Paused": false, "Restarting": false, "OOMKilled": false, "Dead": false, "Pid": 245415, "ExitCode": 0, "Error": "", "StartedAt": "2021-11-28T14:55:17.581464973Z", "FinishedAt": "2021-11-28T14:55:05.650833939Z" }, "Image": "sha256:a4eb038c2ecb80281487ebbdf40938bbc05ebf976df23ff664dec072aad5546a", "ResolvConfPath": "/var/lib/docker/containers/ba8c6c794faed04c6d72d5fe44ee81856ee786175325c33bb99899cab2e54ea9/resolv.conf", "HostnamePath": "/var/lib/docker/containers/ba8c6c794faed04c6d72d5fe44ee81856ee786175325c33bb99899cab2e54ea9/hostname", "HostsPath": "/var/lib/docker/containers/ba8c6c794faed04c6d72d5fe44ee81856ee786175325c33bb99899cab2e54ea9/hosts", "LogPath": "/var/lib/docker/containers/ba8c6c794faed04c6d72d5fe44ee81856ee786175325c33bb99899cab2e54ea9/ba8c6c794faed04c6d72d5fe44ee81856ee786175325c33bb99899cab2e54ea9-json.log", "Name": "/rabbitmq", "RestartCount": 0, "Driver": "overlay2", "Platform": "linux", "MountLabel": "", "ProcessLabel": "", "AppArmorProfile": "docker-default", "ExecIDs": null, "HostConfig": { "Binds": null, "ContainerIDFile": "", "LogConfig": { "Type": "json-file", "Config": {} }, "NetworkMode": "default", "PortBindings": { "15672/tcp": [ { "HostIp": "", "HostPort": "15672" } ], "5672/tcp": [ { "HostIp": "", "HostPort": "5672" } ] }, "RestartPolicy": { "Name": "always", "MaximumRetryCount": 0 }, "AutoRemove": false, "VolumeDriver": "", "VolumesFrom": null, "CapAdd": null, "CapDrop": null, "CgroupnsMode": "host", "Dns": [], "DnsOptions": [], "DnsSearch": [], "ExtraHosts": null, "GroupAdd": null, "IpcMode": "private", "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, "DeviceRequests": null, "KernelMemory": 0, "KernelMemoryTCP": 0, "MemoryReservation": 0, "MemorySwap": 0, "MemorySwappiness": null, "OomKillDisable": false, "PidsLimit": null, "Ulimits": null, "CpuCount": 0, "CpuPercent": 0, "IOMaximumIOps": 0, "IOMaximumBandwidth": 0, "MaskedPaths": [ "/proc/asound", "/proc/acpi", "/proc/kcore", "/proc/keys", "/proc/latency_stats", "/proc/timer_list", "/proc/timer_stats", "/proc/sched_debug", "/proc/scsi", "/sys/firmware" ], "ReadonlyPaths": [ "/proc/bus", "/proc/fs", "/proc/irq", "/proc/sys", "/proc/sysrq-trigger" ] }, "GraphDriver": { "Data": { "LowerDir": "/var/lib/docker/overlay2/e9c85a92ac0b77f7cde594a77161a09da13466171602e9d25523f5d19b3b16eb-init/diff:/var/lib/docker/overlay2/35fd3bcf07f11dcb9411055f9a769cd2c200409f7e5ad7b3bb86310ada66ddaf/diff:/var/lib/docker/overlay2/e0bcd1bcb4c5255bb60b96009ded735001428bd7192eedce421579baad70686d/diff:/var/lib/docker/overlay2/45572bc4887aa6081a5020c0d873ca265db119543390ed1a8c972297246f4774/diff:/var/lib/docker/overlay2/bdeca6a433e28a38697efcf02f2ef67e1f5b7ac6cde5e5969d7c9390da7c9000/diff:/var/lib/docker/overlay2/7d797d0cbba46fcddb2ba1ab7e22332f4470019a41303a7c7d8e586a4dea5c6b/diff:/var/lib/docker/overlay2/500b8c37f7bbf6b8d392e4cd9a1317366d8323a689a115d2bce96b19a8e14c27/diff:/var/lib/docker/overlay2/a58f0d5dd6ece8510c32fab5a508a285888a3e8a1a4bca1c164ae488a507d0dd/diff:/var/lib/docker/overlay2/9c2252ca7416153ddc579aeff11f7195e21d7a0db20b1f74f6d73a0d98c7dbd5/diff:/var/lib/docker/overlay2/62a25cea110c9408ec62c08b3de6e4121aea0b60ff18dd32575b33898a36fece/diff", "MergedDir": "/var/lib/docker/overlay2/e9c85a92ac0b77f7cde594a77161a09da13466171602e9d25523f5d19b3b16eb/merged", "UpperDir": "/var/lib/docker/overlay2/e9c85a92ac0b77f7cde594a77161a09da13466171602e9d25523f5d19b3b16eb/diff", "WorkDir": "/var/lib/docker/overlay2/e9c85a92ac0b77f7cde594a77161a09da13466171602e9d25523f5d19b3b16eb/work" }, "Name": "overlay2" }, "Mounts": [ { "Type": "volume", "Name": "45692529f011e22ffe3b097f4fea2ba54dc305635d4ea056b422143190a684e7", "Source": "/var/lib/docker/volumes/45692529f011e22ffe3b097f4fea2ba54dc305635d4ea056b422143190a684e7/_data", "Destination": "/var/lib/rabbitmq", "Driver": "local", "Mode": "", "RW": true, "Propagation": "" } ], "Config": { "Hostname": "rabbitmqhost", "Domainname": "", "User": "", "AttachStdin": false, "AttachStdout": false, "AttachStderr": false, "ExposedPorts": { "15672/tcp": {}, "15691/tcp": {}, "15692/tcp": {}, "25672/tcp": {}, "4369/tcp": {}, "5671/tcp": {}, "5672/tcp": {} }, "Tty": false, "OpenStdin": false, "StdinOnce": false, "Env": [ "RABBITMQ_DEFAULT_USER=admin", "RABBITMQ_DEFAULT_PASS=rabbitmq", "PATH=/opt/rabbitmq/sbin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "OPENSSL_VERSION=1.1.1l", "OPENSSL_SOURCE_SHA256=0b7a3e5e59c34827fe0c3a74b7ec8baef302b98fa80088d7f9153aa16fa76bd1", "OPENSSL_PGP_KEY_IDS=0x8657ABB260F056B1E5190839D9C4D26D0E604491 0x5B2545DAB21995F4088CEFAA36CEE4DEB00CFE33 0xED230BEC4D4F2518B9D7DF41F0DB4D21C1D35231 0xC1F33DD8CE1D4CC613AF14DA9195C48241FBF7DD 0x7953AC1FBC3DC8B3B292393ED5E9E43F7DF9EE8C 0xE5E52560DD91C556DDBDA5D02064C53641C25E5D", "OTP_VERSION=24.1.5", "OTP_SOURCE_SHA256=a6b28da8a6382d174bb18be781476c7ce36aae792887dc629f331b227dfad542", "RABBITMQ_DATA_DIR=/var/lib/rabbitmq", "RABBITMQ_VERSION=3.9.9", "RABBITMQ_PGP_KEY_ID=0x0A9AF2115F4687BD29803A206B73A36E6026DFCA", "RABBITMQ_HOME=/opt/rabbitmq", "RABBITMQ_LOGS=-", "HOME=/var/lib/rabbitmq", "LANG=C.UTF-8", "LANGUAGE=C.UTF-8", "LC_ALL=C.UTF-8" ], "Cmd": [ "rabbitmq-server" ], "Image": "rabbitmq", "Volumes": { "/var/lib/rabbitmq": {} }, "WorkingDir": "", "Entrypoint": [ "docker-entrypoint.sh" ], "OnBuild": null, "Labels": {} }, "NetworkSettings": { "Bridge": "", "SandboxID": "0391b2e391560ec3c1411dbb8a9c2b3c554e7054d4a7eb7043f5ec9d9527dd5a", "HairpinMode": false, "LinkLocalIPv6Address": "", "LinkLocalIPv6PrefixLen": 0, "Ports": { "15672/tcp": [ { "HostIp": "0.0.0.0", "HostPort": "15672" }, { "HostIp": "::", "HostPort": "15672" } ], "15691/tcp": null, "15692/tcp": null, "25672/tcp": null, "4369/tcp": null, "5671/tcp": null, "5672/tcp": [ { "HostIp": "0.0.0.0", "HostPort": "5672" }, { "HostIp": "::", "HostPort": "5672" } ] }, "SandboxKey": "/var/run/docker/netns/0391b2e39156", "SecondaryIPAddresses": null, "SecondaryIPv6Addresses": null, "EndpointID": "48435f72b1cb9c41ab511f61fdd7a77133af1585b1c63e171dda4c41dc9025c0", "Gateway": "172.17.0.1", "GlobalIPv6Address": "", "GlobalIPv6PrefixLen": 0, "IPAddress": "172.17.0.6", "IPPrefixLen": 16, "IPv6Gateway": "", "MacAddress": "02:42:ac:11:00:06", "Networks": { "bridge": { "IPAMConfig": null, "Links": null, "Aliases": null, "NetworkID": "2b8b92432a38ddbe5b410f687d5ca9dd37372d552895d571564cadd8b0b93134", "EndpointID": "48435f72b1cb9c41ab511f61fdd7a77133af1585b1c63e171dda4c41dc9025c0", "Gateway": "172.17.0.1", "IPAddress": "172.17.0.6", "IPPrefixLen": 16, "IPv6Gateway": "", "GlobalIPv6Address": "", "GlobalIPv6PrefixLen": 0, "MacAddress": "02:42:ac:11:00:06", "DriverOpts": null } } } } ]
進入正在運行的容器
# 通常使用后台執行,進入容器中修改一些配置
docker exec -it [id] /bin/bash # 進入容器后開啟新的終端
docker attach [id] # 進入容器正在執行的終端,不會啟動新的終端,退出會關閉!!
文件拷貝
# 將容器內的文件拷貝到外部
docker cp 752b54e35d4d:/home/wanyu.java /home
# 拷貝是手動過程,未來使用-v卷的集合可以實現數據打通
3,練習部署
3.1,es+kibana
難點
1,暴露的端口很多
2,特別耗費內存
3,數據一般需要放置到安全目錄!掛載
啟動命令
# --net somenetwork ? 網絡配置
docker network create somenetwork
docker run -d --name elasticsearch --net somenetwork -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:tag
# elasticsearch特別卡頓
# 直接訪問9200端口查看
點擊查看http://ip:9200/
{ "name" : "ab061e45a753", "cluster_name" : "docker-cluster", "cluster_uuid" : "FubYpwPzT8iksfByFF-i_g", "version" : { "number" : "7.6.2", "build_flavor" : "default", "build_type" : "docker", "build_hash" : "ef48eb35cf30adf4db14086e8aabd07ef6fb113f", "build_date" : "2020-03-26T06:34:37.794943Z", "build_snapshot" : false, "lucene_version" : "8.4.0", "minimum_wire_compatibility_version" : "6.8.0", "minimum_index_compatibility_version" : "6.0.0-beta1" }, "tagline" : "You Know, for Search" }
# 增加內存限制
docker run -d --name elasticsearch2 --net somenetwork -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx512m" elasticsearch:tag
點擊查看docker stats
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS 9620da899a40 elasticsearch2 0.20% 219.4MiB / 7.429GiB 2.88% 876B / 0B 164kB / 156kB 36 1196c69ed611 webdav-aliyundriver 0.14% 404.5MiB / 7.429GiB 5.32% 155MB / 147MB 49.2kB / 152kB 48 6cde4548c0a8 consul 0.26% 21.91MiB / 7.429GiB 0.29% 289kB / 8.53MB 12.9MB / 479MB 10 3fe6fe9b36e0 zipkin 3.13% 261.7MiB / 7.429GiB 3.44% 190kB / 4.79MB 58.8MB / 86kB 49 acba17f136c3 nginx 0.00% 6.023MiB / 7.429GiB 0.08% 110kB / 119kB 5.82MB / 0B 5 ba8c6c794fae rabbitmq 0.18% 112MiB / 7.429GiB 1.47% 1.44MB / 5.44MB 8.93MB / 94.2kB 25 3457dfb68671 postgres 0.00% 28.41MiB / 7.429GiB 0.37% 671kB / 533kB 14.8MB / 250MB 7 1ba5c5143b3c redis-test 0.15% 7.656MiB / 7.429GiB 0.10% 470kB / 973kB 4.07MB / 24.6kB 5 b4e6a28e2ec3 nexus 0.53% 1.572GiB / 7.429GiB 21.16% 5.06MB / 18.5MB 6.35MB / 309MB 106
直接使用外部的ip地址連接也可以
3.2,部署portainer
docker run -d -p 8082:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
直接訪問ip:8082即可
具體可參考鏈接3
注意:不要貿然放開2375 端口,除非你想被docker中的挖礦病毒入侵!!!
4,docker鏡像原理
鏡像就是一種輕量級、可執行的獨立軟件包,用來打包軟件運行環境和基於運行環境開發的軟件,包含運行某個軟件所需的所有內容(代碼、運行時、庫、環境變量和配置文件)。
4.1,UnionFS(聯合文件系統)
一種分層、輕量級且高性能的文件系統,支持對文件系統的修改作為一次提交來層層的疊加,同時可以將不同目錄掛載到同一個虛擬文件系統下(unitseveral directories into a single virtual)。Union文件系統 是docker鏡像基礎,鏡像可以通過分層來進行繼承,基於基礎鏡像(沒有父級鏡像),可以制作各種文件具體的應用鏡像。
特性:一次同時加載多個文件系統,但從外面看起來,只能看到一個文件系統,聯合加載回波各層文件系統疊加起來,這樣最終的文件系統會包含所有底層的文件和目錄。
4.2,docker鏡像加載原理
docker鏡像用我自己的話說就是蓋樓房一樣,一層一層的搭建,先是地基(bootfs)、一層(rootfs)、二層、......n層。-萬雨
bootfs(boot file system)主要包含BootLoader和kernel,BootLoader主要是引導加載kernel,Linux剛啟動時會加載bootfs文件系統,在docker鏡像的最底層是bootfs。這一層與我們典型的Linux/unix系統是一樣的,包含boot加載器和內核。當boot加載完成之后整個內核就都在內存中了,此時內存的使用權已交由bootfs轉交給內核,此時系統也會協助bootfs。
rootfs(root file system),在bootfs之上。包含的就是典型Linux系統中的/dev,/proc,/bin,/etc等標准目錄和文件。rootfs就是各種不同的操作系統發行版。
核心點:由於unionFS的緣故,docker上層的東西可以共用下層相同的文件,所以使得docker很輕巧!!!
對於一個精簡的OS,rootfs可以很小,只需要包含最基本的命令,工具和程序庫就可以了,因為底層直接用host的kernel,自己只需要提供rootfs即可。由此可見對於不同的Linux發行版,bootfs基本上都是一致的,rootfs會有差別,因為不同的發行版可以公用bootfs。
虛擬機是分鍾級別,容器是秒級!
4.3,分層原理
下載一個鏡像里面是由很多層(layer)的,分層下載、共有!
docker image inspect redis #注意其中的layers
點擊查看docker image inspect redis
[ { "Id": "sha256:02c7f2054405dadaf295fac7281034e998646996e9768e65a78f90af62218be3", "RepoTags": [ "redis:latest" ], "RepoDigests": [ "redis@sha256:e595e79c05c7690f50ef0136acc9d932d65d8b2ce7915d26a68ca3fb41a7db61" ], "Parent": "", "Comment": "", "Created": "2021-09-03T13:26:48.395038582Z", "Container": "3627b30c1a4cf3ef703e0516beee6428efe1b08a5314f5f106b84250635809cb", "ContainerConfig": { "Hostname": "3627b30c1a4c", "Domainname": "", "User": "", "AttachStdin": false, "AttachStdout": false, "AttachStderr": false, "ExposedPorts": { "6379/tcp": {} }, "Tty": false, "OpenStdin": false, "StdinOnce": false, "Env": [ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "GOSU_VERSION=1.12", "REDIS_VERSION=6.2.5", "REDIS_DOWNLOAD_URL=http://download.redis.io/releases/redis-6.2.5.tar.gz", "REDIS_DOWNLOAD_SHA=4b9a75709a1b74b3785e20a6c158cab94cf52298aa381eea947a678a60d551ae" ], "Cmd": [ "/bin/sh", "-c", "#(nop) ", "CMD [\"redis-server\"]" ], "Image": "sha256:332cd8bceec776c2152877041d9e60cbaf4ba95504335e888311bcc1444155a7", "Volumes": { "/data": {} }, "WorkingDir": "/data", "Entrypoint": [ "docker-entrypoint.sh" ], "OnBuild": null, "Labels": {} }, "DockerVersion": "20.10.7", "Author": "", "Config": { "Hostname": "", "Domainname": "", "User": "", "AttachStdin": false, "AttachStdout": false, "AttachStderr": false, "ExposedPorts": { "6379/tcp": {} }, "Tty": false, "OpenStdin": false, "StdinOnce": false, "Env": [ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "GOSU_VERSION=1.12", "REDIS_VERSION=6.2.5", "REDIS_DOWNLOAD_URL=http://download.redis.io/releases/redis-6.2.5.tar.gz", "REDIS_DOWNLOAD_SHA=4b9a75709a1b74b3785e20a6c158cab94cf52298aa381eea947a678a60d551ae" ], "Cmd": [ "redis-server" ], "Image": "sha256:332cd8bceec776c2152877041d9e60cbaf4ba95504335e888311bcc1444155a7", "Volumes": { "/data": {} }, "WorkingDir": "/data", "Entrypoint": [ "docker-entrypoint.sh" ], "OnBuild": null, "Labels": null }, "Architecture": "amd64", "Os": "linux", "Size": 105408201, "VirtualSize": 105408201, "GraphDriver": { "Data": { "LowerDir": "/var/lib/docker/overlay2/e85c9d4bafcf1c40dcf4c7267ca818d50c2f45431a0d1653a66bb68a2dca9137/diff:/var/lib/docker/overlay2/89f9dfc82617f584b5c188baed7551df3fbf3b3bd63a80304d10052e31e8fb84/diff:/var/lib/docker/overlay2/35ec30c65570785f546b2f7bee4c01b0de4ab167ec80d9be38b0a0b2828e5723/diff:/var/lib/docker/overlay2/94e27980d165ce69590d62121ae8e0bb3a10a0ee0964a1e3b0e6d006731b8535/diff:/var/lib/docker/overlay2/424f20b09e163cec1a6802233c76cdf1c5c0e46c32acec0dcf7aa4c9f8efd5c4/diff", "MergedDir": "/var/lib/docker/overlay2/25abbc429add8302f431fdbefb3dd5b55370129f5de3a53f450aa9ea10dfc47b/merged", "UpperDir": "/var/lib/docker/overlay2/25abbc429add8302f431fdbefb3dd5b55370129f5de3a53f450aa9ea10dfc47b/diff", "WorkDir": "/var/lib/docker/overlay2/25abbc429add8302f431fdbefb3dd5b55370129f5de3a53f450aa9ea10dfc47b/work" }, "Name": "overlay2" }, "RootFS": { "Type": "layers", "Layers": [ "sha256:d000633a56813933cb0ac5ee3246cf7a4c0205db6290018a169d7cb096581046", "sha256:bdad86443e47c5665683ac41c1f24f28479d830d7e3cc47d0a337ee5166c7714", "sha256:6a7992ac480029d82b7dbb757d16fe5d023aa283ed32b52267cd1fe9e6b73c49", "sha256:be43d2475cf809c0f2ec31950e849d0f888f3121970fd99196a11a903f8c3820", "sha256:be5818ef2907adfe19be14bf66647b5fb5a2029143f9297f8ce1ff1fd1d35753", "sha256:c54e0c16ea22fa873c12f6a7f3fb4e021bb58d67c292156a6ce6e08637458b7c" ] }, "Metadata": { "LastTagTime": "0001-01-01T00:00:00Z" } } ]
4.4,commit鏡像
docker commit 提交一個容器為新的副本
# 命令和git原理類似
docker commit -m="提交的描述信息" -a="作者" 容器id 目標鏡像名:[tag]
實戰測試
# 1,啟動一個默認的Tomcat
# 2,發現這個默認的Tomcat是沒有webapps應用,鏡像
docker pull tomcat # 下載Tomcat鏡像
docker run -d -p 8080:8080 tomcat # 后台模式運行
docker exec -it [id] /bin/bash # 進入操作台
# 3,將自己的文件拷貝進去
cd /usr/local/tomcat
cp -r webapps.dist/* webapps
# 4,將改動后的文件commit為一個鏡像
查看8080端口頁面
將上述修改后的鏡像重新打包!
# 使用docker inspect [鏡像id] 查看原始鏡像layer和重新提交的layer數據差異!
5,容器數據卷
5.1,命令
docker的理念是將應用和環境打包成一個鏡像!(但是,數據也打包成鏡像就不太好吧!數據丟失!)
容器之間可以有一個數據共享技術!docker容器中產生的數據,同步到本地!
卷技術-目錄掛載,將容器中的目錄掛載到Linux中的目錄中!
1,容器持久化和同步操作;
2,容器間也可以進行數據共享!
docker run -it -v /home/docker_v:/home centos /bin/bash
docker inspect [容器id]
5.2,實戰:mysql
docker pull mysql
docker run -d -p 3310:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=你自己設置的數據庫密碼 --name mysql-wanyu mysql
# 下面的是官方測試
docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
使用dbeaver直接連接mysql成功!注意需要修改其中的allowPublicKeyRetrieval=true配置!
直接在mysql中創建一個新的數據庫時,由於容器數據卷技術本地目錄會有test庫相關文件變更
5.3,具名和匿名掛載
# 匿名掛載
-v 容器路徑!
docker run -d -P --name nginx01 -v /etc/nginx nginx # 匿名掛載(待測試)
docker run -d -P --name nginx02 -v nginx-wanyu:/etc/nginx nginx # 具名掛載
docker volume ls # 查看數據卷情況
# 這個可以發現volume name中會有相關的匿名掛載
查看匿名掛載的目錄
docker inspect [容器id]
docker volume inspect nginx-wanyu
如何確定是具名掛載還是匿名掛載,還是指定路徑掛載?
-v 容器路徑 # 匿名掛載
-v 卷名:容器內路徑 # 具名掛載
-v /宿主機路徑:容器內路徑 # 指定路徑掛載
拓展:
# 通過 -v 容器內路徑:ro rw 改變讀寫權限
# ro readonly
# rw readwrite
docker run -d -P --name nginx03 -v nginx-wanyu:/etc/nginx:ro nginx
docker run -d -P --name nginx03 -v nginx-wanyu:/etc/nginx:rw nginx
5.4,打包樣例centos(展示volume特性)
# 創建一個dockerfile文件,名字可以隨機 建議Dockerflie
# 文件中的內容 指令(大寫)
FROM centos
VOLUME ["/volume01","/volume02"]
CMD echo "----end-----"
CMD /bin/bash
# 里面每一個命令就是鏡像的一層
docker build -f /home/docker-test-volume/dockerfile1 -t wanyu/centos:1.0 .
5.5,數據卷容器
多個centos同步數據
docker run -it --name docker01 wanyu/centos:1.0
docker run -it --name docker02 --volumes-from docker01 wanyu/centos:1.0
# 此時兩個容器的自定義數據卷是共享的!(通過--volumes-from創建的容器,其數據是共享的)
docker01中的volume是匿名數據卷,刪除docker01,其他的容器數據卷不受影響!
多個mysql實現數據共享(當前不好實現!)
docker run -d -p 3310:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=activeclub --name mysql-wanyu01 mysql
docker run -d -P -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql
docker run -d -P -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql02 mysql
docker run -d -P --volumes-from mysql02 -e MYSQL_ROOT_PASSWORD=123456 --name mysql03 mysql
docker run -d -p 3310:3306 -v /etc/mysql/conf.d -v /var/lib/mysql -e MYSQL_ROOT_PASSWORD=activeclub --name mysql-wanyu0 mysql
docker run -d -p 3311:3306 --volumes-from mysql-wanyu0 -e MYSQL_ROOT_PASSWORD=activeclub --name mysql-wanyu1 mysql
報錯
好像會因為這個數據卷已經被其他容器讀寫中,導致本次讀寫被拒絕了!
當前的情況是:只有關閉原有的mysql-wanyu0容器,才能正常使用mysql-wanyu1
6,DockerFile
DockerFile就是用來構建docker鏡像的構建文件!命令腳本
通過這個腳本可以生成鏡像,鏡像是一層層的,腳本的一個個的命令
6.1,基礎知識
構架步驟:
1,編寫一個dockerfile文件
2,docker build構建成一個鏡像
3,docker run 運行鏡像
4,docker push 發布鏡像(dockerHub、阿里雲鏡像倉庫)
dockerfile是面向開發的,以后要發布項目,做鏡像,需要編寫dockerfile文件,這個文件十分簡單!
docker鏡像逐漸成為企業交付的標准,必須掌握!
dockerfile:構建文件,構建了一切的步驟,源代碼(編譯鏈)
docker image:通過dockerfile構建生成的鏡像,最終發布和運行的產品,原來是jar、war,后續就是直接docker鏡像部署
docker container:容器就是鏡像運行起來提供服務的組件!
6.2,dockerfile命令
1,每個保留關鍵字(指令)都必須是大寫
2,執行是從上到下
3,# 表示注釋
4,每個指令都會創建提交一個新的鏡像,並提交
FROM # 基礎進行,一切從這里開始構建
MAINTAINER # 鏡像的作者,姓名+郵箱
RUN # 鏡像構建的時候需要運行的命令
ADD # 步驟,添加內容
WORKDIR # 鏡像的工作目錄
VOLUME # 掛載的數據卷
EXPOSE # 暴露端口配置
CMD # 指定這個容器啟動的時候要運行的命令,只有最后一個會生效,可被替代
ENTRYPOINT # 指定這個容器啟動的時候要運行的命令,可以追加命令
ONBUILD # 當構建一個被繼承的dockerfile,這個時候就會運行ONBUILD,觸發指令
COPY # 類似ADD,將我們的文件拷貝到鏡像中
ENV # 構建的時候設置環境變量,設置內存大小或者其他環境參數
6.3,實戰:centos
docker hub中99%的鏡像都是以FROM scratch開始!然后配置需要的軟件和配置來構建的
任務:構建一個帶有vim、ifconfig命令的centos鏡像
# 1。編寫dockerfile的文件dockerfile-centos
FROM centos
MAINTAINER wanyu<XXXXXX@qq.com>
ENV MYPATH /usr/local
WORKDIR $MYPATH
RUN yum -y install vim
RUN yum -y install net-tools
EXPOSE 80
CMD echo $MYPATH
CMD echo "----end----"
CMD /bin/bash
# 2,通過dockerfile文件構建鏡像
docker build -f dockerfile-centos -t wanyu-centos:1.0 .
點擊查看docker stats
[root@iZbp1jbs6mikemed8a6mooZ:/home/dockerfile-test]# docker build -f dockerfile-centos -t wanyu-centos:1.0 . Sending build context to Docker daemon 2.048kB Step 1/10 : FROM centos ---> 5d0da3dc9764 Step 2/10 : MAINTAINER wanyu ---> Running in e6809c7dd314 Removing intermediate container e6809c7dd314 ---> 0ea1bdd2f8ec Step 3/10 : ENV MYPATH /usr/local ---> Running in 68267f5b4fe0 Removing intermediate container 68267f5b4fe0 ---> 62d54a07b103 Step 4/10 : WORKDIR $MYPATH ---> Running in cc5b572d010f Removing intermediate container cc5b572d010f ---> 1ea33fe2b5ef Step 5/10 : RUN yum -y install vim ---> Running in 538d3635db9a CentOS Linux 8 - AppStream 771 kB/s | 8.2 MB 00:10 CentOS Linux 8 - BaseOS 4.3 MB/s | 3.5 MB 00:00 CentOS Linux 8 - Extras 19 kB/s | 10 kB 00:00 Dependencies resolved. ================================================================================ Package Arch Version Repository Size ================================================================================ Installing: vim-enhanced x86_64 2:8.0.1763-16.el8 appstream 1.4 M Installing dependencies: gpm-libs x86_64 1.20.7-17.el8 appstream 39 k vim-common x86_64 2:8.0.1763-16.el8 appstream 6.3 M vim-filesystem noarch 2:8.0.1763-16.el8 appstream 49 k which x86_64 2.21-16.el8 baseos 49 k Transaction Summary ================================================================================ Install 5 Packages Total download size: 7.8 M Installed size: 30 M Downloading Packages: (1/5): gpm-libs-1.20.7-17.el8.x86_64.rpm 231 kB/s | 39 kB 00:00 (2/5): vim-filesystem-8.0.1763-16.el8.noarch.rp 475 kB/s | 49 kB 00:00 (3/5): which-2.21-16.el8.x86_64.rpm 389 kB/s | 49 kB 00:00 (4/5): vim-enhanced-8.0.1763-16.el8.x86_64.rpm 652 kB/s | 1.4 MB 00:02 (5/5): vim-common-8.0.1763-16.el8.x86_64.rpm 527 kB/s | 6.3 MB 00:12 -------------------------------------------------------------------------------- Total 563 kB/s | 7.8 MB 00:14 warning: /var/cache/dnf/appstream-02e86d1c976ab532/packages/gpm-libs-1.20.7-17.el8.x86_64.rpm: Header V3 RSA/SHA256 Signature, key ID 8483c65d: NOKEY CentOS Linux 8 - AppStream 1.6 MB/s | 1.6 kB 00:00 Importing GPG key 0x8483C65D: Userid : "CentOS (CentOS Official Signing Key) " Fingerprint: 99DB 70FA E1D7 CE22 7FB6 4882 05B5 55B3 8483 C65D From : /etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial Key imported successfully Running transaction check Transaction check succeeded. Running transaction test Transaction test succeeded. Running transaction Preparing : 1/1 Installing : which-2.21-16.el8.x86_64 1/5 Installing : vim-filesystem-2:8.0.1763-16.el8.noarch 2/5 Installing : vim-common-2:8.0.1763-16.el8.x86_64 3/5 Installing : gpm-libs-1.20.7-17.el8.x86_64 4/5 Running scriptlet: gpm-libs-1.20.7-17.el8.x86_64 4/5 Installing : vim-enhanced-2:8.0.1763-16.el8.x86_64 5/5 Running scriptlet: vim-enhanced-2:8.0.1763-16.el8.x86_64 5/5 Running scriptlet: vim-common-2:8.0.1763-16.el8.x86_64 5/5 Verifying : gpm-libs-1.20.7-17.el8.x86_64 1/5 Verifying : vim-common-2:8.0.1763-16.el8.x86_64 2/5 Verifying : vim-enhanced-2:8.0.1763-16.el8.x86_64 3/5 Verifying : vim-filesystem-2:8.0.1763-16.el8.noarch 4/5 Verifying : which-2.21-16.el8.x86_64 5/5 Installed: gpm-libs-1.20.7-17.el8.x86_64 vim-common-2:8.0.1763-16.el8.x86_64 vim-enhanced-2:8.0.1763-16.el8.x86_64 vim-filesystem-2:8.0.1763-16.el8.noarch which-2.21-16.el8.x86_64 Complete! Removing intermediate container 538d3635db9a ---> 6e05fa365556 Step 6/10 : RUN yum -y install net-tools ---> Running in 37e396baef2f Last metadata expiration check: 0:00:23 ago on Sun Dec 5 15:38:25 2021. Dependencies resolved. ================================================================================ Package Architecture Version Repository Size ================================================================================ Installing: net-tools x86_64 2.0-0.52.20160912git.el8 baseos 322 k Transaction Summary ================================================================================ Install 1 Package Total download size: 322 k Installed size: 942 k Downloading Packages: net-tools-2.0-0.52.20160912git.el8.x86_64.rpm 1.5 MB/s | 322 kB 00:00 -------------------------------------------------------------------------------- Total 470 kB/s | 322 kB 00:00 Running transaction check Transaction check succeeded. Running transaction test Transaction test succeeded. Running transaction Preparing : 1/1 Installing : net-tools-2.0-0.52.20160912git.el8.x86_64 1/1 Running scriptlet: net-tools-2.0-0.52.20160912git.el8.x86_64 1/1 Verifying : net-tools-2.0-0.52.20160912git.el8.x86_64 1/1 Installed: net-tools-2.0-0.52.20160912git.el8.x86_64 Complete! Removing intermediate container 37e396baef2f ---> 6bda7a481d68 Step 7/10 : EXPOSE 80 ---> Running in 6d975d602b27 Removing intermediate container 6d975d602b27 ---> d79a352bafc1 Step 8/10 : CMD echo $MYPATH ---> Running in 1e98f38f7472 Removing intermediate container 1e98f38f7472 ---> 25aa4791b8c4 Step 9/10 : CMD echo "----end----" ---> Running in ab3d6b669573 Removing intermediate container ab3d6b669573 ---> 7a046095a7b7 Step 10/10 : CMD /bin/bash ---> Running in 1f30a110730a Removing intermediate container 1f30a110730a ---> 16fb3dd27c56 Successfully built 16fb3dd27c56 Successfully tagged wanyu-centos:1.0
可以通過docker history [鏡像id]查看鏡像構建歷史
例如:postgres的構建歷史
CMD與ENTRYPOINT區別(待實踐)
測試CMD命令
測試ENTRYPOINT命令
# 直接執行docker run id -l
很多命令只有細微的區別,最好的學習就是對比執行效果!
6.4,實戰:Tomcat鏡像
兩個關鍵的文件下載地址
https://mufasa-blog-images.oss-cn-beijing.aliyuncs.com/img/apache-tomcat-9.0.33.tar.gz
https://mufasa-blog-images.oss-cn-beijing.aliyuncs.com/img/jdk-8u311-linux-x64.tar.gz
FROM centos
MAINTAINER wanyu<xxxx@qq.com>
COPY readme.txt /usr/local/readme.txt
ADD jdk-8u311-linux-x64.tar.gz /usr/local
ADD apache-tomcat-9.0.33.tar.gz /usr/local
RUN yum -y install vim
ENV MYPATH /usr/local/jdk1.8.0_311
WORKDIR $MYPATH
ENV JAVA_HOME /usr/local/jdk1.8.0_311
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.33
ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.33
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
EXPOSE 8080
CMD touch /usr/local/apache-tomcat-9.0.33/logs/catalina.out
CMD /usr/local/apache-tomcat-9.0.33/bin/startup.sh && tail -f /usr/local/apache-tomcat-9.0.33/logs/catalina.out
docker build -t wanyuTomcat .
docker run -d -p 9090:8080 --name wanyuTomcat 1f4f43c5147a
6.5,發布鏡像到阿里雲
1,直接登錄阿里雲,進入控制台搜索鏡像服務
2,自己創建鏡像倉庫
3,直接在鏡像倉庫中有類似github倉庫的命令教學
docker login --username=XXXXX registry.cn-hangzhou.aliyuncs.com # 登錄鏡像
docker pull registry.cn-hangzhou.aliyuncs.com/activeclub/private:[鏡像版本號]
docker tag [ImageId] registry.cn-hangzhou.aliyuncs.com/activeclub/private:[鏡像版本號]
docker push registry.cn-hangzhou.aliyuncs.com/activeclub/private:[鏡像版本號]
6.6,將自己的springBoot項目打包docker鏡像(待)
使用阿里雲流水線CI/CD持續化集成工具很方便(devops)
1,構架springboot項目
2,打包應用
3,編寫dockerfile
4,構架鏡像
5,發布運行
流程:
1,
7,Docker網絡
ip addr
# lo:本機回環地址
# eth0:阿里雲內網地址
# docker0:docker生成的地址
# 代表三種不同的環境,docker如何處理網絡訪問?
veth-path虛擬網絡技術
docker中的所有網絡接口都是虛擬的,虛擬的轉發效率高!
高可用問題:
docker中直接使用類似consul那種服務名注冊的形式,以容器名稱來代替ip,實現重啟動態更換ip但是不用額外更換ip
7.2,--link
docker run -d -P --name tomcat02 --link tomcat01 tomcat
# 之后就可以直接在tomcat02容器中直接
ping tomcat01
7.3,自定義網絡
docker network ls
網絡模式:
bridge:橋接docker(默認,自定義)
none:不配置網絡
host:和宿主機共享網絡
container:容器網絡聯調(使用較少,局限較大)
# 啟動命令 --net bridge,這個就是docker0
docker run -d -P --name tomcat01 tomcat
docker run -d -P --name tomcat01 --net bridge tomcat
# docker0特點:默認,域名不能訪問,--link可以打通連接
# 可以自定義網絡
# --dirver bridge
# --subnet 192.168.0.0/16
# --gateway 192.168.0.1
docker network create --driver bridge --subnet 192.168.0.0/16 --getway 192.168.0.1 mynet
直接將容器運行在自定義的網絡中,同一個網路中的容器之間可以通過名字互相ping通網絡!!!
優勢:不同的集群使用不同的網絡,保證集群網絡是安全和健康的
7.4,網絡聯通
# 測試打通tomcat - mynet
docker network connect mynet tomcat03
# 聯通之后就是tomcat01放到mynet網絡下
# 一個容器兩個ip
# 阿里雲服務:公網ip、私網ip
7.5,部署redis集群(待)
詳情見我的博文Redis技術總結中的redis集群篇
8,參考鏈接
1,https://docs.docker.com/get-started/overview/
8,jenkins