Docker入门——保姆级

Docker概述

—— Notes from WAX through KuangShen

准确来说,这是一篇学习笔记!!!

Docker为什么出现

一款产品:开发—上线 两套环境!应用环境如何铜鼓?

开发 – 运维。避免“在我的电脑米问题呀!!!”

环境配置十分麻烦,没一个机器都要部署环境(集群Redis、ES…)!费时费力。

发布一个项目(jar + (Redis、Mysql、jdk、ES))能否带上安装环境进行打包发布。

Windows开发,最后发布到Linux:

传统:开发项目,运维来做。

现在:开发打包部署上线,一套流程做完。

例:

java – apk – 发布(应用商店) – 张三使用apk – 安装即可使用!

java – jar(环境) – 打包项目带上环境(镜像)-- (Docker仓库:商店)-- 下载发布的镜像 – 直接运行即可!

Docker给出以上问题的解决方案!

Docker的思想来自于集装箱!

隔离:Docker核心思想,打包装箱!每个箱子是互相隔离的

Docker通过隔离机制,可以将服务器利用到极致!

Docker的历史

2010年,几个搞IT的年轻人,就在没美国成立了一家公司dotCloud

做一些pass的云计算服务,LXC有关的容器技术!

他们将自己的技术(容器话技术)命名 就是Docker!

Docker刚刚诞生的时候,没有引起行业注意!公司举步维艰,于是决定开源!!!

2013,Docker开源!

Docker越来越多的人发现Docker的有点!火了,每个月都会更新一个版本!

2014年4月9日,Docker1.0发布!

Docker为什么这么火?极其轻巧

在容器技术出来之前,我们都是使用虚拟技术!

虚拟机:在Windows中装一个Vmware,通过这个软件可以虚拟化出来一个或多个电脑,但是十分笨重。

虚拟机也是属于虚拟化技术,Docker容器技术,也是一种虚拟化技术

vm:linux centos原生镜像(一个电脑) 隔离,需要开启多个虚拟机! 几个G大小
docker:隔离,镜像(最核心的环境4m + jdk + mysql)十分轻巧,运行镜像就可以了,几 M Kb  秒级启动

到现在,所有开发人员都必须会的工具 Docker。

聊聊docker

Docker是基于 Go 语言开发的,开源项目!

官网:https://www.docker.com

文档:https://docs.docker.com 超详细

仓库地址:https://hub.docker.com

Docker的作用

虚拟机技术缺点:

1、资源占用多

2、冗余步骤多

3、启动慢

Docker和虚拟技术的不同:

  • 统虚拟机,虚拟出一切硬件,运行一个完整的操作系统,然后在这个系统上安装和运行软件

  • 容器内的应用直接运行再宿主机的内核,容器是没有自己的内核的,也没有虚拟我们的硬件,所以轻便

  • 每个容器内是相互隔离的,每个容器内都有一个属于自己的文件系统,互不影响

DevOps(开发/运维)

应用更快速的交付和部署

  • 传统方式:一堆帮助文档,安装程序

  • Docker:打包镜像发布测试,意见运行

更快捷的升级和扩缩容

  • 使用Docker以后,我们不熟应用就类似搭积木简单

  • 项目打包为一个镜像,扩容 服务器A 服务器B

更简单的系统运维

  • 在容器化之后,开发、测试测试环境都是高度一致的。

更高效的计算资源利用:

  • Docker是内核级的虚拟化,可以在一个物理机上运行很多个容器实例。服务器的性能能利用到极致。

docker的安装

docker的基本组成

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cXdU4l9R-1691285233022)(C:\Users\wax\AppData\Roaming\Typora\typora-user-images\image-20210424153809962.png)]

镜像(image):

Docker镜像好比一个模板,可以通过这个模板来创建容器服务。

通过这个镜像可以创建多个容器(最终服务运行或项目运行就是在容器中的)

容器(container):

Docker利用容器技术,独立运行一个或者一组应用,通过镜像来创建。

虽然不是很准确,但是可以粗略的连接容器就是一个简单的LInux系统

仓库(repository):

仓库就是存放镜像的地方

仓库分为公有仓库和私有仓库

Docker Hub

阿里云…都有容器服务器

安装docker

安装环境

  1. 需要会一点Linux的基础
  2. CentOS(本次用例)

环境查看

#系统版本是3.10以上的
[root@sa ~]# uname -r
3.10.0-957.el7.x86_64
[root@sa ~]# 
#系统版本
[root@sa ~]# cat /etc/os-release 
NAME="CentOS Linux"
VERSION="7 (Core)"
ID="centos"
ID_LIKE="rhel fedora"
VERSION_ID="7"
PRETTY_NAME="CentOS Linux 7 (Core)"
ANSI_COLOR="0;31"
CPE_NAME="cpe:/o:centos:centos:7"
HOME_URL="https://www.centos.org/"
BUG_REPORT_URL="https://bugs.centos.org/"CENTOS_MANTISBT_PROJECT="CentOS-7"
CENTOS_MANTISBT_PROJECT_VERSION="7"
REDHAT_SUPPORT_PRODUCT="centos"
REDHAT_SUPPORT_PRODUCT_VERSION="7"

安装docker

帮助文档:https://docs.docker.com/engine/install/

# 1、删除旧的版本
sudo yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate \docker-engine
# 2、依赖包
sudo yum install -y yum-utils# 3、设置镜像的仓库,当然也可以设置阿里云的
sudo yum-config-manager \--add-repo \https://download.docker.com/linux/centos/docker-ce.repo              官方
sudo yum-config-manager \--add-repo \https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo     阿里云#更新yum软件包索引
yum makecache fast# 4、安装docekr  -ce表示社区版    -ee表示企业版
yum install docker-ce docker-ce-cli containerd.io# Ubuntu 安装sudo apt install docker.io# 5、运行docker
sudo systemctl start docker# 6、查看版本信息,有则是安装成功
docker version# 7、查看启动是否成功
docker run hello-world   # 会打印“Hello from Docker!” 则成功

卸载docker

# 1、卸载依赖
sudo yum remove docker-ce docker-ce-cli containerd.io# 2、删除资源
sudo rm -rf /var/lib/docker
sudo rm -rf /var/lib/containerd

hello world流程

此处就不画图了:

docker run 开始,docker就会在本地查找镜像,

有,则直接运行该镜像。没有,就会在docker Hub(官方镜像仓库)上去下载,下载到本地后直接运行,没有下载到则返回错误

底层原理

docker是怎么工作的

Docker是一个 Client - Server结构的系统,Docker的守护进程运行在主机上。通过Socket从客户端访问!

DockerServer 接收到Docekr Client的指令执行!
在这里插入图片描述

Docker 为什么比 VM 快

  1. Docker有着比虚拟机更少的抽象层
  2. Docker利用的是宿主机的内核,VM需要的是 Guest OS。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Kr2YNtvt-1691285233023)(Docker-入门.assets/95a51974f5cb22bbf85a4650fe3a901f.png)]

所以说,新建一容器的时候,Docker不需要像虚拟机一样重新加载一个操作系统内核,避免引导。虚拟机是加载Guest OS,分钟级别,而Docker是利用宿主机的操作系统,省略了这个复杂的过程,秒级启动。

当然,安全性方面,肯定还是VM虚拟机更安全,毕竟是一个完整的虚拟系统。

Docker的常用命令

帮助命令

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jIj51yeg-1691285233024)(Docker-入门.assets/image-20210524201159034.png)]

docker version				# 显示docker版本信息
docker info					# 显示docker的系统信息,包括镜像和容器的数量
docekr --help				# 帮助

帮助文档 https://docs.docker.com/reference/

镜像命令

Docker images 查看所有本地镜像

[root@sa ~]# docker images
REPOSITORY              TAG                 IMAGE ID            CREATED             SIZE
hello-world             latest              d1165f221234        2 months ago        13.3kB
vue-docker-demo-image   latest              4835e3101950        8 months ago        135MB
docker-demo-image       latest              831b48a0447e        8 months ago        133MB# 含义
REPOSITORY		镜像的仓库源
TAG				镜像的标签
IMAGE ID		镜像的id
REPOSITORY		镜像创建时间
SIZE			镜像大小# 可选项-a, --all             Show all images (default hides intermediate images)		# 显示所有镜像--digests         Show digests 											# 显示摘要-f, --filter filter   Filter output based on conditions provided--format string   Pretty-print images using a Go template--no-trunc        Don't truncate output-q, --quiet           Only show numeric IDs									# 只显示id

docekr search 搜索镜像

[root@sa ~]# docker search mysql
NAME           DESCRIPTION 			         STARS  OFFICIAL            AUTOMATED
mysql                MySQL is a widely used, open-source relation…   10876  	 [OK] 
mariadb       		 MariaDB Server is a high performing open sou…   4102   	 [OK] 
mysql/mysql-server   Optimized MySQL Server Docker images. Create…   808       					 [OK]
...
[root@sa ~]# # 可选项,通过收藏来过滤-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
[root@sa ~]# docker search mysql --filter=STARS=3000
NAME                DESCRIPTION                                     STARS               OFFICIAL            AUTOMATED
mysql               MySQL is a widely used, open-source relation…   10876               [OK]                
mariadb             MariaDB Server is a high performing open sou…   4102                [OK]     
[root@sa ~]#

**docker pull ** 下载镜像

# 下载镜像 docker pull 镜像名[:tag]
[root@sa ~]# docker pull mysql
Using default tag: latest				# 如果没有指定tag,默认就是latest
latest: Pulling from library/mysql
69692152171a: Pull complete 			# 分层下载,docker image的核心--联合文件系统
1651b0be3df3: Pull complete 
951da7386bc8: Pull complete 
0f86c95aa242: Pull complete 
37ba2d8bd4fe: Pull complete 
6d278bb05e94: Pull complete 
497efbd93a3e: Pull complete 
f7fddf10c2c2: Pull complete 
16415d159dfb: Pull complete 
0e530ffc6b73: Pull complete 
b0a4a1a77178: Pull complete 
cd90f92aa9ef: Pull complete 
Digest: sha256:d50098d7fcb25b1fcb24e2d3247cae3fc55815d64fec640dc395840f8fa80969		# 签名
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest		# 真实地址
[root@sa ~]# # 以下两个命令等价
docker pull mysql
docker pull docekr.io/library/mysql:latest

docker images 查看镜像

[root@sa ~]# docker images
REPOSITORY              TAG                 IMAGE ID            CREATED             SIZE
mysql                   latest              c0cdc95609f1        3 days ago          556MB
hello-world             latest              d1165f221234        2 months ago        13.3kB
vue-docker-demo-image   latest              4835e3101950        8 months ago        135MB
[root@sa ~]# 

docker rmi 删除镜像

# docker rmi 容器id  -f  强制删除(运行中的)
# docker rmi 容器id 容器id 容器id  删除多个容器
[root@sa ~]# docker rmi d11
Untagged: hello-world:latest
Untagged: hello-world@sha256:5122f6204b6a3596e048758cabba3c46b1c937a46b5be6225b835d091b90e46c
Deleted: sha256:d1165f2212346b2bab48cb01c1e39ee8ad1be46b87873d9ca7a4e434980a7726
Deleted: sha256:f22b99068db93900abe17f7f5e09ec775c2826ecfe9db961fea68293744144bd
[root@sa ~]# # 批量删除
# -f 强制删除,-aq 仅显示所有的镜像id
[root@sa ~]# docker rmi -f $(docker images -aq)

容器命令

有了镜像才可以创建容器

以centOS镜像为例:

docker pull centos

新建容器并启动

docekr run [可选参数] image# 参数说明
--name="name"			# 容器名称 name01  name02,用来区分容器
-d 						# 后台方式运行
-it						# 使用交互方式运行,进入容器查看内容
-p						# 指定容器的端口-p ip:主机端口:容器端口  映射-p 主机端口:容器端口(常用)-p 容器端口-P(大写p)				# 随机指定端口# 启动并进入容器,你会发现,现在的用户名就是容器的id
[root@sa ~]# 
[root@sa ~]# docker run -it centos /bin/bash
[root@74457211455c /]# 
[root@74457211455c /]# 
# 退出就是exit
...

列出所有运行的容器

docker ps	# 列出正在运行的容器-a 		# 列出所有容器,包含已经停止的-n=? 	# 列出最近创建的容器,带数字-q		# 只列出容器的id# 列出所有容器,包含已经停止的
[root@sa ~]# docker ps -a
CONTAINER ID        IMAGE                   COMMAND                  CREATED             STATUS                    PORTS               NAMES
74457211455c        centos                  "/bin/bash"              2 minutes ago       Up 2 minutes                                  happy_wilson

退出容器

exit		# 直接停止容器并退出
Ctrl +p +q  # 容器不停止退出

删除容器

docker rm 						# 容器id-f 	# 强制删除正在运行的容器docker rm -f $(docker ps -aq)	# 删除所有的容器
docker ps -aq |xargs docker rm	# 也可以删除所有容器

启动容器

docker start	容器id		# 启动容器
docker restart	容器id		# 重启容器
docker stop		容器id		# 停止当前正在运行的容器
docker kill		容器id		# 轻质停止当前容器

其他常用命令

后台启动

# 命令 docker run -d 镜像名
[root@sa ~]# docker run -d centos
26e18764513a7ebf03f73dda143d5b1bb73054cbf74bae10d8f22ba16d4c4ea9
[root@sa ~]# 
# 会产生的问题:ps发现centos 直接停了
# 原因:docke容器使用后台运行,就必须要有一个前台进程,docker发现没有应用,就会自动停止

查看日志

docker logs -tf --tail# 显示日志
-tf				# 显示日志 -t时间戳 -f Follow log output(不断输出日志)
--tail number	# 要显示的日志条数,后接数字

查看容器中的进程信息

# 命令 docker top 容器id
[root@sa ~]# docker top 8b
UID    PID        PPID    C   STIME        TTY       TIME        CMD
root   21913     21895    0     04:28     pts/0    00:00:00     /bin/bash
[root@sa ~]# 

查看镜像的元数据

# 命令 docker inspect 容器id[root@sa ~]# docker inspect 8b
[{"Id": "8bdbd34f37a64afa4e80eaafdaa517bd98a8ed1b3be178b2fb386865d4df7f05","Created": "2021-05-18T20:28:55.704722287Z","Path": "/bin/bash","Args": [],"State": {"Status": "running","Running": true,"Paused": false,"Restarting": false,"OOMKilled": false,"Dead": false,"Pid": 21913,"ExitCode": 0,"Error": "","StartedAt": "2021-05-18T20:28:56.270071675Z","FinishedAt": "0001-01-01T00:00:00Z"},"Image": "sha256:300e315adb2f96afe5f0b2780b87f28ae95231fe3bdd1e16b9ba606307728f55","ResolvConfPath": "/var/lib/docker/containers/8bdbd34f37a64afa4e80eaafdaa517bd98a8ed1b3be178b2fb386865d4df7f05/resolv.conf","HostnamePath": "/var/lib/docker/containers/8bdbd34f37a64afa4e80eaafdaa517bd98a8ed1b3be178b2fb386865d4df7f05/hostname","HostsPath": "/var/lib/docker/containers/8bdbd34f37a64afa4e80eaafdaa517bd98a8ed1b3be178b2fb386865d4df7f05/hosts","LogPath": "/var/lib/docker/containers/8bdbd34f37a64afa4e80eaafdaa517bd98a8ed1b3be178b2fb386865d4df7f05/8bdbd34f37a64afa4e80eaafdaa517bd98a8ed1b3be178b2fb386865d4df7f05-json.log","Name": "/interesting_black","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,"Capabilities": null,"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/1664d1df131ceec26e30d5f1288e4a76104ba149a4e2ed91df49cbae1d5b5c95-init/diff:/var/lib/docker/overlay2/85c0301341e0be53f9854cc3148968bb232564ca6cac942efebc0b9328ec192c/diff","MergedDir": "/var/lib/docker/overlay2/1664d1df131ceec26e30d5f1288e4a76104ba149a4e2ed91df49cbae1d5b5c95/merged","UpperDir": "/var/lib/docker/overlay2/1664d1df131ceec26e30d5f1288e4a76104ba149a4e2ed91df49cbae1d5b5c95/diff","WorkDir": "/var/lib/docker/overlay2/1664d1df131ceec26e30d5f1288e4a76104ba149a4e2ed91df49cbae1d5b5c95/work"},"Name": "overlay2"},"Mounts": [],"Config": {"Hostname": "8bdbd34f37a6","Domainname": "","User": "","AttachStdin": true,"AttachStdout": true,"AttachStderr": true,"Tty": true,"OpenStdin": true,"StdinOnce": true,"Env": ["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"],"Cmd": ["/bin/bash"],"Image": "centos","Volumes": null,"WorkingDir": "","Entrypoint": null,"OnBuild": null,"Labels": {"org.label-schema.build-date": "20201204","org.label-schema.license": "GPLv2","org.label-schema.name": "CentOS Base Image","org.label-schema.schema-version": "1.0","org.label-schema.vendor": "CentOS"}},"NetworkSettings": {"Bridge": "","SandboxID": "f90c37e119e8231aee5aed42652c64393959cd87f061092347b98b21a5764f8e","HairpinMode": false,"LinkLocalIPv6Address": "","LinkLocalIPv6PrefixLen": 0,"Ports": {},"SandboxKey": "/var/run/docker/netns/f90c37e119e8","SecondaryIPAddresses": null,"SecondaryIPv6Addresses": null,"EndpointID": "d3f5369c06fc9c93af1b5bfbc45617ee24b7900e88a33ac66793b80712912f88","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": "d29efb6707572fecd8ccaadfb2f011525f39fa0a9fb0a7732be8af61baf34003","EndpointID": "d3f5369c06fc9c93af1b5bfbc45617ee24b7900e88a33ac66793b80712912f88","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@sa ~]# 

进入正在运行的容器

# 进入正在运行的容器# 方式一:
docker exec -it 容器id bashShell# 方式二:
docker attch 容器id# docker exec	进入容器后开启一个新的终端
# docker attch	进入容器正在执行的终端,不会开启新的进程

容器和主机之间的拷贝

# 从容器内拷贝文件到主机
docker cp 容器id:/路径 /主机路径  # 建议使用绝对路径# 进入容器
[root@sa ~]# docker exec -it f2 /bin/sh
sh-4.4# 
sh-4.4# touch 123.txt
sh-4.4# ls
123.txt  ks-script-esd4my7v  ks-script-eusq_sc5
sh-4.4# exit
[root@sa ~]# # 将容器内的文件拷贝至主机
[root@sa ~]# docker cp  f2:/tmp/123.txt ./
[root@sa ~]# 
[root@sa ~]# docker ps 					 # 说明只要容器还在,启不启动数据都在
CONTAINER ID   IMAGE    COMMAND    CREATED      STATUS      PORTS     NAMES
[root@sa ~]# 
[root@sa ~]# docker ps -a
CONTAINER ID  IMAGE COMMAND   				 CREATED  	STATUS  PORTS   NAMES
f24dcc07e0e5 centos "/bin/sh -c 'while t…"   15 ago     Exited      vigilant_hypatia
[root@sa ~]# 

Docker 镜像讲解

镜像是什么

镜像是一种轻量级、可执行的独立软件包(类似于免安装),用来打包软件运行环境和基于运行环境开发的软件,他包含运行某个软件所需的所有内容,包括代码、运行是所需的库、环境变量及配置文件等等。

Docker镜像加载原理

UnionFS(联合文件系统)

UnionFS:Union文件系统是一种分层、轻量级并且高性能的文件系统,他支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂在到同一个虚拟文件系统(unite several directories into a single virtual filesystem)下。Union文件系统时Docker镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。

特性:以此同时加载多个文件系统,单对外表现,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录

Docker镜像加载原理

Docker的镜像实际上有一层一层的文件系统组成,这种层级的文件系统叫联合文件系统

Bootfs(boot file system)主要包含bootloader 和kernel,BootLoader主要是引导加载kerner,Linux刚启动时会加载bootfs文件系统,在Docker镜像的最底层是bootfs。这一层与我们经典的Linux/Unix系统是一样的,包含boot加载器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs。

rootfs(root file system),在bootfs之上。包含的就是典型Linux系统中的/dev, /proc, /etc等标准目录文件。rootfs就是各种不同的操作系统发行版,例如:Ubuntu、CentOS等。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JUvjsVsI-1691285233025)(Docker-入门.assets/image-20210605100943326.png)]

平时安装的虚拟机CentOS都是好几个G,但是Docker这里的才几百兆,为什么?

因为Docker镜像一般都是非常精简的,不要忘了,他用的宿主机的内核,自己只需要提供rootfs就可以了。所以镜像只需提供最基本的命令、工具和程序即可。由此,对于不同的Linux发行版,bootfs基本是一致的,rootfs会有差别,因此不同的发行版可以共用bootfs。

分层理解

分层的镜像

​ 在下载镜像时,可以注意到下载日志输出的是一层层下载的

分层的好处:

最大的好处莫过于资源共享!例如,有多个镜像都是相同的Base镜像构建而来,那么宿主机只需要在磁盘上保留一份Base镜像,同时,内存中也只需要加载一份Base镜像,这样就可以为所有的容器服务了,而且镜像的每一层都可以被共享。

查看镜像分层的方式可以通过 docker inspect 命令查看

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WIBMsGcc-1691285233026)(Docker-入门.assets/image-20210605150403314.png)]

理解:

所有的Docker镜像都起始于一个基础镜像层,当进行修改或增加新的内容时,就会在当前镜像层之上创建一个新的镜像层。

例如:基于Ubuntu Linux 16.04创建一个新的镜像,这就是新镜像的第一层,如果在该镜像中添加Python包,就会在基础镜像层之上创建第二个镜像层,如果继续添加,则依次往上新建。

这里其实忽略了一个重要的概念,那就是层,怎样的添加才能构成所谓的 “层"

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-X08F9UvE-1691285233026)(Docker-入门.assets/image-20210605164534407.png)]

Docker镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部!这一层就是我们通常说的容器层,容器之下的都叫镜像层。

分层理解2(理论更清晰)

比较好的理解:

Docker的镜像分层

接下来,我们来看看 Docker的镜像分层机制。

Docker镜像是分层构建的,Dockerfile 中每条指令都会新建一层。例如以下 Dockerfile:

FROM ubuntu:18.04
COPY . /app
RUN make /app
CMD python /app/app.py

以上四条指令会创建四层,分别对应基础镜像、复制文件、编译文件以及入口文件,每层只记录本层所做的更改,而这些层都是只读层。当你启动一个容器,Docker 会在最顶部添加读写层,你在容器内做的所有更改,如写日志、修改、删除文件等,都保存到了读写层内,一般称该层为容器层,如下图所示:

> [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9brxJaJt-1691285233027)(Docker-入门.assets/v2-4b2318880b12c3220fa59a9d9992dc90_720w.jpg)]docker layer

事实上,容器(container)和镜像(image)的最主要区别就是容器加上了顶层的读写层。所有对容器的修改都发生在此层,镜像并不会被修改,也即前面说的 COW(copy-on-write)技术。容器需要读取某个文件时,直接从底部只读层去读即可,而如果需要修改某文件,则将该文件拷贝到顶部读写层进行修改,只读层保持不变。

每个容器都有自己的读写层,因此多个容器可以使用同一个镜像,另外容器被删除时,其对应的读写层也会被删除(如果你希望多个容器共享或者持久化数据,可以使用 Docker volume)。

最后,执行命令 docker ps -s,可以看到最后有两列 size 和 virtual size。其中 size就是容器读写层占用的磁盘空间,而 virtual size 就是读写层加上对应只读层所占用的磁盘空间。如果两个容器是从同一个镜像创建,那么只读层就是 100%共享,即使不是从同一镜像创建,其镜像仍然可能共享部分只读层(如一个镜像是基于另一个创建)。因此,docker 实际占用的磁盘空间远远小于 virtual size 的总和。

> [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-w4oP9qIz-1691285233028)(Docker-入门.assets/v2-b71caf2dbcc2fa95e8545cb7c97998ac_720w.png)]

以上就是 Docker 镜像分层的主要内容,至于这些层的交互、管理就需要存储驱动程序,也即联合文件系统(UnionFS)。Docker 可使用多种驱动,如目前已经合并入 Linux 内核、官方推荐的overlay, 曾在 Ubuntu、Debian等发行版中得到广泛使用的 AUFS,以及devicemapper、zfs等等,需要根据 Docker以及宿主机系统的版本,进行合适的选择。

commit 镜像

docker commit 提交容器成为一个新的副本(镜像)# 命令和git类似
docker commit -m="提交的描述信息" -a="作者" 容器id 目标镜像名:[TAG]

容器数据卷

什么是容器数据卷

数据如果只保存在容器中,那么容器删除,则数据丢失。

有没有什么方式可以将容器中的数据同步或者说映射至本地/宿主机的长期保存所想要的数据。

容器之间也可以共享数据。

于是,有了卷技术。简单理解就是目录的挂载,将容器内的目录挂载到宿主机上,并且容器间也是可以数据共享的。

使用数据卷

方式一: 直接使用命令挂载 -v

# docker run -it -v 宿主机目录:容器内目录,宿主机目录可以不存在,会自动创建,最好使用绝对路径-it # 交互式启动-v  # 卷volume  挂载[root@sa ~]# docker run  -it -v ~/mont_volume:/home centos /bin/bash# 启动之后可根据 docker inspect 容器id 查看挂载结果
[root@sa ~]# docker inspect 0601e8ee0ec6

# 挂载以后基本上就理解成容器内核宿主机共用这个目录。
# 测试可发现,当容器停止后,在宿主机向mont_volume目录写入文件,然后重新启动容器,容器home目录可直接看到写入文件
# 即使,容器被删除,然后重新起一个容器,挂载宿主机目录还是mont_volume,那么,新容器也是可以直接看到写入文件。这也说明了,容器删除不会影响挂载的目录
# 总结,可用该方法将配置类的文件挂载出来,当我们需要修改容器配置时,无需进入容器即可修改

安装MySQL

# 1、获取镜像
[root@sa ~]# docker pull mysql# 2、安装mysql一定要注意配置密码
# Starting a MySQL instance is simple:
#
[root@sa ~] # docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
# ... where some-mysql is the name you want to assign to your container, my-secret-pw # is the password to be set for the MySQL root user and tag is the tag specifying the # MySQL version you want. See the list above for relevant tags.
# from  https://hub.docker.com/_/mysql# 3、启动镜像
[root@sa ~]# docker run -d -p 3310:3306 -v /home/myspl/conf:/etc/mysql/conf.d -v /home/mysql/date:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql ac4ca43eb68bc7bfadbd6da4cef7fa81f83d79eb10b9639cf8b7cbc016e50c9a-d 后台运行-p 端口映射-v 卷挂载-e 环境配置--name 容器名字(容器名字mysql01,而mysql是镜像名)
[root@sa ~]# 

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UjMETaWf-1691285233028)(Docker-入门.assets/image-20210626114415095.png)]

具名和匿名挂载

# 匿名挂载
-v 容器内目录
[root@sa ~]# docker run -d -P --name nginx -v /etc/nginx nginx# 查看所有的 volume 的情况
[root@sa ~]# docker volume ls
DRIVER              VOLUME NAME
local               ed11f4eedfbbdff94704282111ffe0d6a8bad21171f4c6af0be255f8a649ab27
[root@sa ~]## VOLIME NAME 实际上是一些具体的目录# 现在为了对比,起一个具名的挂在容器
[root@sa ~]# docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx
42ca9c1cd1447c2d6f79caa9c9197cd7083a597ce01abec60c0109018cc69b06
[root@sa ~]# 
[root@sa ~]# docker volume ls
DRIVER              VOLUME NAME
local               ed11f4eedfbbdff94704282111ffe0d6a8bad21171f4c6af0be255f8a649ab27
local               juming-nginx# 通过 -v 卷名:容器内路径
# 查看这个卷
[root@sa ~]# docker volume inspect ed11f4eedfbbdff94704282111ffe0d6a8bad21171f4c6af0be255f8a649ab27
[{"CreatedAt": "2021-05-29T23:21:35+08:00","Driver": "local","Labels": null,"Mountpoint": "/var/lib/docker/volumes/ed11f4eedfbbdff94704282111ffe0d6a8bad21171f4c6af0be255f8a649ab27/_data","Name": "ed11f4eedfbbdff94704282111ffe0d6a8bad21171f4c6af0be255f8a649ab27","Options": null,"Scope": "local"}
]
[root@sa ~]#  
[root@sa ~]# docker volume inspect juming-nginx
[{"CreatedAt": "2021-06-26T21:55:36+08:00","Driver": "local","Labels": null,"Mountpoint": "/var/lib/docker/volumes/juming-nginx/_data","Name": "juming-nginx","Options": null,"Scope": "local"}
]
[root@sa ~]# 
[root@sa juming-nginx]# cd _data/
[root@sa _data]# ls
conf.d  fastcgi_params  koi-utf  koi-win  mime.types  modules  nginx.conf  scgi_params  uwsgi_params  win-utf

总结:

所有的Docker容器的卷,在没有指定挂在目录的情况下都在 /var/lib/docker/volumes/xxxxx/_data

我们通过具名挂载可以方便的找到我们的一个卷,大多数情况下使用 具名挂载

# 如何确定是具名还是匿名挂载
-v	容器内路径				# 匿名挂载
-v  卷名:容器内路径		  # 具名挂载
-v  宿主机路径:容器内路径		# 指定路径挂载

拓展:(下面所说的权限都是针对容器而言,也就是如果在容器上是只读的,但,在宿主机上是可以进行写操作的)

# 通过 -v 容器内路径  :ro  :rw 来改变读写权限
# ro 只读
# rw 可读可写# 凡是设置了这个容器权限,容器对挂载的内容的权限就被限定了
[root@sa ~]# docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:ro nginx
[root@sa ~]# docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:rw nginx# 上面所说的权限都是针对容器而言,也就是如果在容器上是只读的,但是可以在宿主机上进行写操作(当然,宿主机本身对该路径可写)

数据卷之DockerFile

Dockerfile是用来构建docker镜像的构建文件。命令脚本。

通过这个脚本可以生成镜像,镜像是一层一层的,脚本时一个个的命令,每个命令就是一层

# 创建一个dockerfile文件,名字可以任意,最好还是dockerfile
# 一般格式:指令(全大写)  参数
# 文件内容如下:
[root@sa Dockerfile-test]# cat dockerfile1  # 以下的每个指令就是镜像的一层
FROM centos							# 将centos作为基础镜像				VOLUME ["volume01", "volume02"]		# 挂载数据卷CMD echo "----is wax ---- first --- Dockerfile----"
CMD /bin/bash[root@sa Dockerfile-test]# # 查看镜像生成过程
[root@sa Dockerfile-test]# docker build -f dockerfile1  -t wax-centos:0.1 .-f 指定dockerfile文件-t tag 目标文件一定不要忘了生成的文件存放路径—— 末尾的那个 .(当前目录)Sending build context to Docker daemon  2.048kB
Step 1/4 : FROM centos---> 300e315adb2f
Step 2/4 : VOLUME ["volume01", "volume02"]---> Running in 669152823e0d
Removing intermediate container 669152823e0d---> 5e192b1bef6d
Step 3/4 : CMD echo "----is wax ---- first --- Dockerfile----"---> Running in b65e28cc25db
Removing intermediate container b65e28cc25db---> cf5be1a83272
Step 4/4 : CMD /bin/bash---> Running in 8cb48405b199
Removing intermediate container 8cb48405b199---> 09081e56f27e
Successfully built 09081e56f27e
Successfully tagged wax-centos:0.1
[root@sa Dockerfile-test]# # 查看镜像
[root@sa Dockerfile-test]# docker images
REPOSITORY      TAG      IMAGE ID            CREATED             SIZE
wax-centos     0.1       09081e56f27e        5 minutes ago       209MB
redis          latest    fad0ee7e917a        3 weeks ago         105MB# 启动镜像
[root@sa Dockerfile-test]# docker run  -it 09081e56f27e /bin/bash
[root@93d0f80f1c21 /]# 
[root@93d0f80f1c21 /]#   可以看到已经成功进入
[root@93d0f80f1c21 /]# ls -l
total 0
...... # 篇幅问题省略
drwxr-xr-x.   2 root root   6 Nov  3  2020 srv
dr-xr-xr-x.  13 root root   0 May 15 10:53 sys
drwxrwxrwt.   7 root root 145 Dec  4  2020 tmp
drwxr-xr-x.  12 root root 144 Dec  4  2020 usr
drwxr-xr-x.  20 root root 262 Dec  4  2020 var
drwxr-xr-x.   2 root root   6 Jun 28 11:13 volume01    # 两个volume** 目录就是构建镜像时,
drwxr-xr-x.   2 root root   6 Jun 28 11:13 volume02	   # 自动挂载的数据卷目录# 可以看到两个volume实际上是匿名挂载,那么,查看其挂载的具体位置
[root@sa ~]# docker inspect 93d0f80f1c21
....."Mounts": [{"Type": "volume","Name": "c716f0d4f9*****bddf","Source": "/var/lib/docker/volumes/c716f0d4f9*****bddf/_data","Destination": "volume01","Driver": "local","Mode": "","RW": true,"Propagation": ""},{"Type": "volume","Name": "14e0ac65b55b5******d156e","Source": "/var/lib/docker/volumes/14e0ac65b55b5*****d156e/_data","Destination": "volume02","Driver": "local","Mode": "","RW": true,"Propagation": ""}],
......

实际上,这种方式为十分常用,因为我们的目的大多需要自己构建镜像。

假如,构建镜像没有自动挂载卷,那就要自己手动挂载了, -v 卷名:容器内路径 (手动当然 具名挂载 啦)

数据卷容器

作用:实现多个容器间的数据同步,共享。

命令: - -volumes - from container_name

一般把被挂载的容器也就是父容器 称之为数据卷容器

# 启动数据卷容器
[root@sa ~]# docker run  -it --name docker-father wax-centos:0.1 /bin/bash# 启动要和父容器共享的容器(为了简单,使用同一个镜像)
[root@sa ~]# docker run  -it --name docker-child01  --volumes-from docker-father wax-centos:0.1 /bin/bash# 在启动2个容器
[root@sa ~]# docker run  -it --name docker-child02  --volumes-from docker-father wax-centos:0.1[root@sa ~]# docker run  -it --name docker-child03  --volumes-from docker-child02 centos# 查看父容器 (123. 456是03创建的)
[root@8eb24755d5fd volume01]# ls
123.txt  456.txt  child01-create  child02-create# 查看03容器
[root@sa ~]# docker attach docker-child03
[root@f2eb5b35ae88 /]# ls
bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var  volume01  volume02
[root@f2eb5b35ae88 /]# 

直接给结论:

当我们删除任何一个容器时,其他容器的挂载目录不受影响。

可以看到,child03的镜像是基础的centos镜像,挂载到02上的,其自身并没有挂载volume01 、volume02,但是,使用了

–volumes-from 指令之后依然会挂载这两个目录。

另外,虽然03容器挂载的是02容器,但是停止并删除了02容器后,再在03中的volume01目录下创建文件在父容器、01中依然可以看到。另外,再把父容器删除,03中volume*目录下创建的文件,在01中还是可以看到。所以应该不是简单的拷贝。(原理我也不知奥)

另外,通过inspect可以看到,4个容器的挂载目录都是同一个地方,是不是突然明白了?也就是,即使,你把所有容器都删了,数据应该是还在的,都在宿主机上,需要注意的是,删除容器不影响数据(文件),但是在容器内删除文件是同步的,包括会同步到宿主机。其实这个比较好理解。

再另外,在宿主机上,删除宿主机上的被挂载目录,比如 /var/lib/docker/volumes/***/_data 的_data目录,那么已经启动的容器将无法在其挂载目录下进行操作——无法新建文件。就算手动将_data目录再创建出来,依然不能新建文件。需要停止后重启容器才可以新建。

Dockerfile

Dockerfile 介绍

Dockerfile 是用来构建docker镜像的文件,就是参数脚本!

构建步骤:

  1. 编写一个dockefile文件
  2. docker build 构建成一个镜像
  3. docker run 就可以运行镜像
  4. docker push 可以发布镜像

Dockerfile 构建过程

  1. 每个保留关键字(指令)都是大写
  2. 从上至下依次执行
  3. 使用 ‘#’ 注释
  4. 每一个指令都会创建提交一层新的镜像层

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iS8pNngJ-1691285233029)(Docker-入门.assets/image-20210724151251695.png)]

Dockerfile是面向开发的!

Dockerfile:构建文件,定义了所有步骤,源代码

Dockerimages:通过Dockerfile构建的镜像,做种发布和运行

Docker容器:容器就是镜像运行起来提供的服务

Dockerfile的指令

FROM 					# 基础镜像,一切从这里构建
MAINTAINER				# 镜像的作者、维护者
RUN						# 镜像构建的时候需要运行的命令
ADD						# 步骤:Ubuntu镜像,可以给他加vim配置文件啥的
WORKDIR					# 镜像的工作目录
VOLUME					# 挂载的目录
EXPOSE					# 保留端口配置
CMD						# 指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT				# 指定这个容器启动的时候要运行的命令,可以追加命令
ONBUILD					# 当构建一个被继承 Dockerfile,这个时候就会运行 ONBUILD 的指令
COPY					# 类似ADD,将文件拷贝至镜像中
ENV						# 构建的时候设置环境变量

实例

以ubuntu基础镜像为例

# 先通过 docker pull ubuntu  下载一个官方的最新的ubuntu基础镜像
#这里可以先尝试一下,刚下载的镜像是不支持vim 的,等下通过dockerFile制作一个带有vim的镜像#下面开始写dockerFile
root@wu:~/my_dockerfile# cat Dockerfile 
FROM ubuntuMAINTAINER wax<1123@qq.com>ENV MYPATH /usr/local
WORKDIR $MYPATHRUN apt-get update
RUN apt-get install -y vim
RUN apt-get install -y net-toolsEXPOSE 80CMD echo $MYPATHCMD echo "------end!-------"
CMD /bin/bash

这里需要注意一点,如果是在centos系统上安装的docker,那么大概率执行以上dockerFile将会是失败的。据说是,容器使用的资源库的源是来自宿主机的,也就是centos上不能执行atp-get,而是 yum install命令

接着,我们就来构建自己的镜像(删除了安装vim过程中的打印)

# dockerFile的构建命令 可以通过 docker build --help查看# -f 指定dockerFile文件  -t 指定目标镜像root@wu:~/my_dockerfile# docker build -f Dockerfile -t my_ubuntu:1.0 ./
Sending build context to Docker daemon  2.048kB
Step 1/11 : FROM ubuntu---> ff0fea8310f3
Step 2/11 : MAINTAINER wax<1123@qq.com>---> Using cache---> 350bceb3effd
Step 3/11 : ENV MYPATH /usr/local---> Using cache---> 792e5469839a
Step 4/11 : WORKDIR $MYPATH---> Using cache---> 1b2933c2de8f
Step 5/11 : RUN apt-get update---> Using cache---> cee70ef91575
Step 6/11 : RUN apt-get  install -y vim---> Using cache---> 628163e35047
Step 7/11 : RUN apt-get  install -y net-tools---> Using cache---> 66ceeb0d5a36
Step 8/11 : EXPOSE 80---> Using cache---> 1a3c9ff3333b
Step 9/11 : CMD echo $MYPATH---> Using cache---> b9007091be62
Step 10/11 : CMD echo "------end!--------"---> Using cache---> 1c85c73c79fe
Step 11/11 : CMD /bin/bash---> Using cache---> 66c8af1a3f90
Successfully built 66c8af1a3f90
Successfully tagged my_ubuntu:1.0
root@wu:~/my_dockerfile# 

完了之后就可以运行my_ubuntu镜像,并且可以直接执行vim 以及 ifconfg等命令。这里就不做演示了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/60268.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

243. 一个简单的整数问题2(树状数组)

输入样例&#xff1a; 10 5 1 2 3 4 5 6 7 8 9 10 Q 4 4 Q 1 10 Q 2 4 C 3 6 3 Q 2 4输出样例&#xff1a; 4 55 9 15 解析&#xff1a; 一般树状数组都是单点修改、区间查询或者单点查询、区间修改。这道题都是区间操作。 1. 区间修改用数组数组维护差分数组 2. 区间查询&am…

云原生之深入解析如何使用Devtron简化K8S应用开发

一、NeuVector 简介 ① 什么是 NeuVector &#xff1f; NeuVector 是业界首个端到端的开源容器安全平台&#xff0c;唯一为容器化工作负载提供企业级零信任安全的解决方案。NeuVector 是业界领先的安全和合规解决方案&#xff0c;已被全球知名企业广泛采用&#xff1b;其代码…

适用HarmonyOS 3.1版本及以上的应用及服务开发工具 DevEco Studio 3.1.1 Release 安装

文章目录 安装步骤1.下载安装包2.安装成功后&#xff0c;初次运行studio2.1 配置node与ohpm的环境2.2安装sdk2.3等待安装结束 3.创建项目3.1 点击Create Project3.2 选择一个空项目3.3 项目配置3.4 Finish、等待依赖下载完毕3.5 项目创建完成 tip 提示4.配置运行环境4.1 真机运…

爬虫015_python异常_页面结构介绍_爬虫概念介绍---python工作笔记034

来看python中的异常 可以看到不做异常处理因为没有这个文件所以报错了 来看一下异常的写法

Idea 反编译jar包

实际项目中&#xff0c;有时候会需要更改jar包源码来达到业务需求&#xff0c;本文章将介绍一下如何通过Idea来进行jar反编译 1、Idea安装decompiler插件 2、找到decompiler插件文件夹 decompiler插件文件夹路径为&#xff1a;idea安装路径/plugins/java-decompiler/lib 3、…

正则表达式的使用

1、正则表达式-教程 正则表达式&#xff1a;文本模式&#xff0c;包括普通字符&#xff08;例如&#xff0c;a到z之间的字母&#xff09;和特殊字符&#xff08;称为元字符&#xff09;。 正则表达式使用单个字符串来描述&#xff0c;匹配一系列匹配某个句法规则的字符串。 2、…

【uniapp】一文读懂app端安装包升级

一、前言 首先&#xff0c;在app端开发上线的过程中&#xff0c;会面临一个问题&#xff0c;就是关于app端的版本升级的问题。如果不做相关处理来引导用户的话&#xff0c;那么app就会出现版本没有更新出现的各种问题&#xff0c;我们常见的有在线升级和去指定地址下载安装两种…

计算机网络—IP

这里写目录标题 IP的基本认识网络层与数据链路层有什么关系IP地址基础知识IP 地址的分类什么是A、B、C类地址广播地址用来做什么什么是D、E类广播多播地址用于什么IP分类的优点IP分类的缺点 无分类地址CIDR如何划分网络号和主机号怎么进性子网划分 公有 IP 地址与私有 IP 地址公…

修改el-select样式;修改element-plus的下拉框el-select样式

修改el-select样式 .select_box{// 默认placeholder:deep .el-input__inner::placeholder {font-size: 14px;font-weight: 500;color: #3E534F;}// 默认框状态样式更改:deep .el-input__wrapper {height: 42px;background-color: rgba(0,0,0,0)!important;box-shadow: 0 0 0 …

获取Spring中bean工具类

获取Spring中bean工具类 工具类 package com.geekmice.springbootselfexercise.utils;import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org…

Flink源码之JobManager启动流程

从启动命令flink-daemon.sh中可以看出StandaloneSession入口类为org.apache.flink.runtime.entrypoint.StandaloneSessionClusterEntrypoint, 从该类的main方法会进入ClusterEntrypoint::runCluster中, 该方法中会创建出主要服务和组件。 StandaloneSessionClusterEntrypoint:…