docker容器创建私有仓库(第三篇)

目录

六、创建私有仓库

七、Docker资源限制

7.1、CPU使用率

7.2、CPU共享比例

7.3、CPU周期限制

7.4、CPU核心限制

7.5、CPU 配额控制参数的混合案例

7.6、内存限制

7.7、Block IO 的限制

7.8、限制bps 和iops

8、Docker数据持久化

8.1、数据持久化介绍

8.2、Volume的基本使用

8.2.1、管理卷

8.2.2、创建使用指定卷的容器

8.2.3、清理卷

8.3、Bind Mounts的基本使用

8.3.1 使用卷创建一个容器

8.3.2、验证绑定

8.3.3、清理

8.4、数据卷容器

8.4.1、数据卷容器概述

8.4.2、创建数据卷容器


六、创建私有仓库

仓库(Repository)是集中存放镜像的地方。

仓库注册服务器才是存放仓库具体的服务器(Registry),每个服务器上都可以放置多个仓库,而每个仓库下可以放置多个镜像,每个镜像上可以运行多个容器,每个容器上可以跑一个应用或应用组。

仓库自身可以分为:公共仓库和私有仓库

安装docker后,可以通过官方提供的registry镜像部署一套本地的私有仓库环境

[root@localhost ~]# mkdir -p /opt/data/registry[root@localhost ~]# docker run -d --restart=always -p 5000:5000 -v /opt/data/registry:/tmp/registry registryUnable to find image 'registry:latest' locally
latest: Pulling from library/registry
79e9f2f55bf5: Pull complete 
0d96da54f60b: Pull complete 
5b27040df4a2: Pull complete 
e2ead8259a04: Pull complete 
3790aef225b9: Pull complete 
Digest: sha256:169211e20e2f2d5d115674681eb79d21a217b296b43374b8e39f97fcf866b375
Status: Downloaded newer image for registry:latest
f5b026b082957e416f2facf2fb8739ee5002d31e44ffa05c71eff08c588b0f1f[root@localhost ~]# docker ps -lCONTAINER ID   IMAGE      COMMAND                   CREATED          STATUS          PORTS                                       NAMESf5b026b08295   registry   "/entrypoint.sh /etc…"   17 seconds ago   Up 16 seconds   0.0.0.0:5000->5000/tcp, :::5000->5000/tcp   hardcore_cori

 准备测试镜像

[root@localhost ~]# docker run -d -p 800:80 nginx                #将宿主机800端口映射给容器的业务端口Unable to find image 'nginx:latest' locally
latest: Pulling from library/nginx
a2abf6c4d29d: Pull complete 
a9edb18cadd1: Pull complete 
589b7251471a: Pull complete 
186b1aaa4aa6: Pull complete 
b4df32aa5a72: Pull complete 
a0bcbecc962e: Pull complete 
Digest: sha256:0d17b565c37bcbd895e9d92315a05c1c3c9a29f762b011a10c54a66cd53c9b31
Status: Downloaded newer image for nginx:latest
bc0698d60239d036f737d18370a81eb84a0a7f69ec536a8b208118aace4fa79a[root@localhost ~]# docker ps -lCONTAINER ID   IMAGE     COMMAND                   CREATED         STATUS         PORTS                                 NAMESbc0698d60239   nginx     "/docker-entrypoint.…"   7 seconds ago   Up 6 seconds   0.0.0.0:800->80/tcp, :::800->80/tcp   zealous_darwin

宿主机(192.168.2.118)访问8000端口测试:

[root@localhost ~]# docker logs bc0698d60239                #查看日志/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
2023/08/02 03:56:56 [notice] 1#1: using the "epoll" event method
2023/08/02 03:56:56 [notice] 1#1: nginx/1.21.5
2023/08/02 03:56:56 [notice] 1#1: built by gcc 10.2.1 20210110 (Debian 10.2.1-6) 
2023/08/02 03:56:56 [notice] 1#1: OS: Linux 3.10.0-1160.92.1.el7.x86_64
2023/08/02 03:56:56 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576
2023/08/02 03:56:56 [notice] 1#1: start worker processes
2023/08/02 03:56:56 [notice] 1#1: start worker process 32
2023/08/02 03:56:56 [notice] 1#1: start worker process 33
2023/08/02 03:56:56 [notice] 1#1: start worker process 34
2023/08/02 03:56:56 [notice] 1#1: start worker process 35
192.168.2.1 - - [02/Aug/2023:03:58:40 +0000] "GET / HTTP/1.1" 200 615 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36 Edg/115.0.1901.188" "-"
2023/08/02 03:58:40 [error] 34#34: *1 open() "/usr/share/nginx/html/favicon.ico" failed (2: No such file or directory), client: 192.168.2.1, server: localhost, request: "GET /favicon.ico HTTP/1.1", host: "192.168.2.118:800", referrer: "http://192.168.2.118:800/"
192.168.2.1 - - [02/Aug/2023:03:58:40 +0000] "GET /favicon.ico HTTP/1.1" 404 555 "http://192.168.2.118:800/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36 Edg/115.0.1901.188" "-"

 将修改过的nginx镜像做标记封装,准备上传到私有仓库

[root@localhost ~]# docker tag nginx 192.168.2.118:5000/nginx-test[root@localhost ~]# docker push 192.168.2.118:5000/nginx-testUsing default tag: latest
The push refers to repository [192.168.2.118:5000/nginx-test]
Get "https://192.168.2.118:5000/v2/": http: server gave HTTP response to HTTPS client[root@localhost ~]#  cat /etc/docker/daemon.json {"registry-mirrors":[ "https://nyakyfun.mirror.aliyuncs.com" ],"insecure-registries":["192.168.2.118:5000"]
}[root@localhost ~]# systemctl daemon-reload[root@localhost ~]# systemctl restart docker

将镜像上传到私有仓库

[root@localhost ~]# docker push 192.168.2.118:5000/nginx-testUsing default tag: latest
The push refers to repository [192.168.2.118:5000/nginx-test]
d874fd2bc83b: Pushed 
32ce5f6a5106: Pushed 
f1db227348d0: Pushed 
b8d6e692a25e: Pushed 
e379e8aedd4d: Pushed 
2edcec3590a4: Pushed 
latest: digest: sha256:ee89b00528ff4f02f2405e4ee221743ebc3f8e8dd0bfd5c4c20a2fa2aaa7ede3 size: 1570

从私有仓库中下载镜像到本地

[root@localhost ~]# docker rmi 192.168.2.118:5000/nginx-testUntagged: 192.168.2.118:5000/nginx-test:latest
Untagged: 192.168.2.118:5000/nginx-test@sha256:ee89b00528ff4f02f2405e4ee221743ebc3f8e8dd0bfd5c4c20a2fa2aaa7ede3[root@localhost ~]# docker imagesREPOSITORY   TAG       IMAGE ID       CREATED         SIZE
nginx        latest    605c77e624dd   19 months ago   141MB
registry     latest    b8604a3fe854   20 months ago   26.2MB[root@localhost ~]# docker pull 192.168.2.118:5000/nginx-testUsing default tag: latest
latest: Pulling from nginx-test
Digest: sha256:ee89b00528ff4f02f2405e4ee221743ebc3f8e8dd0bfd5c4c20a2fa2aaa7ede3
Status: Downloaded newer image for 192.168.2.118:5000/nginx-test:latest
192.168.2.118:5000/nginx-test:latest[root@localhost ~]# docker imagesREPOSITORY                      TAG       IMAGE ID       CREATED         SIZE
nginx                           latest    605c77e624dd   19 months ago   141MB
192.168.2.118:5000/nginx-test   latest    605c77e624dd   19 months ago   141MB
registry                        latest    b8604a3fe854   20 months ago   26.2MB

 

七、Docker资源限制

        Docker容器技术底层是通过Cgroup(Control Group 控制组)实现容器对物理资源使用的限制,限制的资源包括CPU、内存、磁盘三个方面。基本覆盖了常见的资源配额和使用量控制。

        Cgroup 是Linux 内核提供的一种可以限制、记录、隔离进程组所使用的物理资源的机制,被LXC及Docker等很多项目用于实现进程的资源控制。

        Cgroup 是提供将进程进行分组化管理的功能和接口的基础结构,Docker中I/O 或内存的分配控制等具体的资源管理功能都是通过Cgroup功能来实现的。这些具体的资源管理功能称为Cgroup子系统,以下是对几大子系统的介绍。

  1. blkio:限制块设备的输入输出控制。如:磁盘、光盘、USB等。
  2. cpu:限制CPU资源的访问
  3. cpuacct:产生Cgroup 任务的CPU资源报告。
  4. cpuset:限制分配单独的cpu 和内存资源。
  5. devices:允许或拒绝对设备的访问。
  6. freezer:暂停和恢复Cgroup 任务。
  7. memory:设置每个Cgroup 的内存限制以及产生内存资源报告。
  8. net_cls:用于标记每个网络包。
  9. ns:命名空间子系统。
  10. perf_event:增加了对每group 的监测跟踪的能力,可以监测属于某个特定的group 的所有线程以及运行在特定CPU 上的线程。

 centos-7-x86_64.tar提取链接:https://pan.baidu.com/s/155YCVkJr6rXKf7VP-ZXFwQ?pwd=e12x 
提取码:e12x

使用下面的Dockerfile 来创建一个基于CentOS的stress工具镜像。

[root@localhost ~]# cat centos-7-x86_64.tar.gz | docker import - centos:7sha256:bd0569f5d7da160cecb1437baf48b28d31a303777785053f4189ff1af97e7342[root@localhost ~]# mkdir stress[root@localhost ~]# cd stress[root@localhost stress]# vim DockerfileFROM centos:7
MAINTAINER crushlinux "crushlinux@163.com"
RUN yum -y install wget
RUN wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
RUN yum -y install stress[root@localhost stress]# docker build -t centos:stress .[+] Building 48.6s (8/8) FINISHED                                                   docker:default=> [internal] load build definition from Dockerfile                                          0.0s=> => transferring dockerfile: 288B                                                          0.0s=> [internal] load .dockerignore                                                             0.0s=> => transferring context: 2B                                                               0.0s=> [internal] load metadata for docker.io/library/centos:7                                   0.0s=> [1/4] FROM docker.io/library/centos:7                                                     0.0s=> [2/4] RUN yum -y install wget                                                            31.9s=> [3/4] RUN wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo   1.8s=> [4/4] RUN yum -y install stress                                                          14.1s => exporting to image                                                                        0.7s => => exporting layers                                                                       0.6s => => writing image sha256:4907ba4a7a63ba68cab027bcc5191665bad0898ad7229435b528e364e154d399  0.0s => => naming to docker.io/library/centos:stress                  

7.1、CPU使用率

        在CentOS7中可以通过修改对应的Cgroup配置文件cpu.cfs_quota_us的值来实现,直接执行echo命令将设定值导入到文件中就会立即生效。

例如将容器ddb8e55d1c09的CPU使用设置为20000,设置CPU的使用率限定为20%。

[root@localhost ~]# docker run -itd centos:stress /bin/bashddb8e55d1c094fe9734994ffe3a61fafebf2237eded6ebffa507f61d32921010[root@localhost ~]# docker ps -a CONTAINER ID   IMAGE           COMMAND                   CREATED         STATUS                      PORTS                                       NAMESddb8e55d1c09   centos:stress   "/bin/bash"               9 seconds ago   Up 8 seconds                                                            dazzling_euclid[root@localhost ~]# echo "20000" > /sys/fs/cgroup/cpu,cpuacct/docker/ddb8e55d1c094fe9734994ffe3a61fafebf2237eded6ebffa507f61d32921010/cpu.cfs_quota_us

7.2、CPU共享比例

        当多个容器任务运行时,很难计算CPU的使用率,为了使容器合理使用CPU资源,可以通过--cpu-shares选项设置容器按比例共享CPU资源,这种方式还可以实现CPU使用率的动态调整。

        命令中的--cpu-shares 选项值不能保证可以获得1 个vcpu 或者多少GHz 的CPU 资源,仅仅只是一个弹性的加权值。

        默认情况下,每个docker容器的cpu份额都是1024。单独一个容器的份额是没有意义的。只有在同时运行多个容器时,容器的CPU加权的效果才能体现出来。例如,两个容器A、B的CPU份额分别为1000和500,在CPU进行时间片分配的时候,容器A比容器B多一倍的机会获得CPU的时间片。但分配的结果取决于当时主机和其他容器的运行状态,实际上也无法保证容器A一定能获得CPU时间片。比如容器A的进程一直是空闲的,那么容器B 是可以获取比容器A更多的CPU时间片的。极端情况下,比如说主机上只运行了一个容器,即使它的CPU份额只有50,它也可以独占整个主机的CPU资源。

        Cgroups 只在容器分配的资源紧缺时,也就是说在需要对容器使用的资源进行限制时才会生效。因此无法单纯根据某个容器的CPU份额来确定有多少CPU 资源分配给它,资源分配结果取决于同时运行的其他容器的CPU分配和容器中进程运行情况。

        换句话说,可以通过cpu shares可以设置容器使用CPU的优先级,比如启动了两个容器及运行查看CPU使用百分比。

[root@localhost ~]# docker run -tid --name cpu512 --cpu-shares 512 centos:stress stress -c 10b2d3e64065f09a683e352722d187c097e2b4bf161a4cc08444a304700a101e23[root@localhost ~]#  docker run -tid --name cpu1024 --cpu-shares 1024 centos:stress stress -c 105c59dc0f47d3f6bde8003d8b6f684e6fc8268ef792d282e1c335abbbcc3edfa8[root@localhost ~]# docker ps -aCONTAINER ID   IMAGE           COMMAND                   CREATED              STATUS                   PORTS                                       NAMES5c59dc0f47d3   centos:stress   "stress -c 10"            10 seconds ago       Up 8 seconds                                                         
cpu1024b2d3e64065f0   centos:stress   "stress -c 10"            About a minute ago   Up About a minute                                                    cpu512ddb8e55d1c09   centos:stress   "/bin/bash"               53 minutes ago       Up 53 minutes                                                        dazzling_euclidbc0698d60239   nginx           "/docker-entrypoint.…"   4 hours ago          Exited (0) 2 hours ago                                               zealous_darwinf5b026b08295   registry        "/entrypoint.sh /etc…"   4 hours ago          Up About an hour         0.0.0.0:5000->5000/tcp, :::5000->5000/tcp   hardcore_cori[root@localhost ~]# docker exec -it b2d3e64065f0 /bin/bash[root@b2d3e64065f0 /]# toptop - 03:31:32 up  5:48,  0 users,  load average: 19.89, 12.06, 5.18
Tasks:  14 total,  11 running,   3 sleeping,   0 stopped,   0 zombie
%Cpu(s): 99.9 us,  0.1 sy,  0.0 ni,  0.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :  3861080 total,  1333692 free,   350952 used,  2176436 buff/cache
KiB Swap:  2097148 total,  2097148 free,        0 used.  3107816 avail Mem PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND                      9 root      20   0    7260     96      0 R  14.3  0.0   1:00.20 stress                       11 root      20   0    7260     96      0 R  14.3  0.0   0:59.15 stress                       12 root      20   0    7260     96      0 R  14.3  0.0   1:00.03 stress                       15 root      20   0    7260     96      0 R  14.3  0.0   1:01.25 stress                       13 root      20   0    7260     96      0 R  14.0  0.0   0:59.02 stress                       16 root      20   0    7260     96      0 R  14.0  0.0   1:01.54 stress                       8 root      20   0    7260     96      0 R  12.7  0.0   0:59.61 stress                       10 root      20   0    7260     96      0 R  12.7  0.0   0:59.41 stress                       7 root      20   0    7260     96      0 R  12.3  0.0   1:00.28 stress                       14 root      20   0    7260     96      0 R  12.3  0.0   0:59.47 stress                       1 root      20   0    7260    644    548 S   0.0  0.0   0:00.03 stress                       23 root      20   0   11772   1804   1448 S   0.0  0.0   0:00.01 bash                         39 root      20   0   11772   1808   1448 S   0.0  0.0   0:00.01 bash                         55 root      20   0   51864   1920   1408 R   0.0  0.0   0:00.00 top  

[root@localhost ~]# docker exec -it 5c59dc0f47d3 /bin/bash[root@5c59dc0f47d3 /]# toptop - 03:34:52 up  5:51,  0 users,  load average: 20.41, 16.06, 8.10
Tasks:  13 total,  11 running,   2 sleeping,   0 stopped,   0 zombie
%Cpu(s):100.0 us,  0.0 sy,  0.0 ni,  0.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :  3861080 total,  1338616 free,   345936 used,  2176528 buff/cache
KiB Swap:  2097148 total,  2097148 free,        0 used.  3112744 avail Mem PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND                      11 root      20   0    7260     92      0 R  30.9  0.0   1:56.49 stress                       12 root      20   0    7260     92      0 R  28.2  0.0   1:55.71 stress                       16 root      20   0    7260     92      0 R  28.2  0.0   1:57.39 stress                       14 root      20   0    7260     92      0 R  27.6  0.0   1:53.74 stress                       13 root      20   0    7260     92      0 R  25.2  0.0   1:57.68 stress                       7 root      20   0    7260     92      0 R  24.9  0.0   1:55.63 stress                       8 root      20   0    7260     92      0 R  24.9  0.0   1:55.41 stress                       9 root      20   0    7260     92      0 R  24.9  0.0   1:54.88 stress                       15 root      20   0    7260     92      0 R  24.9  0.0   1:59.09 stress                       10 root      20   0    7260     92      0 R  24.6  0.0   1:56.37 stress                       1 root      20   0    7260    640    548 S   0.0  0.0   0:00.01 stress                       17 root      20   0   11772   1808   1448 S   0.0  0.0   0:00.04 bash                         33 root      20   0   51860   1924   1408 R   0.0  0.0   0:00.00 top                          

        开启了10 个stress 进程,目的是充分让系统资源变得紧张。只有这样竞争资源,设定的资源比例才可以显现出来。如果只运行一个进行,会自动分配到空闲的CPU,这样比例就无法看出来。由于案例的环境不一样,可能导致上面两张图中占用CPU 百分比会不同,但是从cpu share 来看两个容器总比例一定会是1:2。

7.3CPU周期限制

docker 提供了--cpu-period、--cpu-quota 两个参数控制容器可以分配到的CPU 时钟周期。

  1. --cpu-period 是用来指定容器对CPU的使用要在多长时间内做一次重新分配。
  2. --cpu-quota 是用来指定在这个周期内,最多可以有多少时间用来跑这个容器。与--cpu-shares 不同的是:这种配置是指定一个绝对值,而且没有弹性在里面,容器对CPU 资源的使用绝对不会超过配置的值。

        cpu-period 和cpu-quota 的单位为微秒(μs)。cpu-period 的最小值为1000 微秒,

最大值为1 秒(10^6 μs),默认值为0.1 秒(100000 μs)。cpu-quota 的值默认为-1,

表示不做控制。cpu-period、cpu-quota 这两个参数一般联合使用。

        举个例子,如果容器进程需要每1 秒使用单个CPU 的0.2 秒时间,可以将cpu-period 设置为1000000(即1 秒),cpu-quota 设置为200000(0.2 秒)。当然,在多核情况下,如果允许容器进程需要完全占用两个CPU,则可以将cpu-period 设置为100000(即0.1 秒),cpu-quota 设置为200000(0.2 秒)。

[root@localhost ~]# docker run -it --cpu-period 10000 --cpu-quota 20000 centos:stress /bin/bash[root@aa6136f8cb7b /]# cat /sys/fs/cgroup/cpu/cpu.cfs_period_us 10000[root@aa6136f8cb7b /]# cat /sys/fs/cgroup/cpu/cpu.cfs_quota_us  20000

7.4、CPU核心限制

        多核CPU的服务器Docker还可以控制容器运行限定使用哪些CPU内核,可以使用--cpuset-cpus选项来使某些程序独享CPU核心,以便提高其处理速度,对应的Cgroup文件为/sys/fs/cgroup/cpuset/docker/容器ID号/cpuset.cpus。选项后直接跟参数0、1、2……表示第1个内核,第2个内核,第3个内核,与/proc/cpuinfo中的标号相同。

如果服务器有16个核心,那么CPU编号为0~15,使新建容器绑定第1~4的核心使用:

[root@localhost ~]# docker run -itd --cpuset-cpus 0,1,2,3 centos:stress /bin/bash
7f26046560e1f1e1d91dfe3d16bded32d37ffcaef964725a68eaf16b99722fa7或[root@localhost ~]# docker run -itd --cpuset-cpus 0-3 centos:stress /bin/bash
1b69dabb453be291dcd87dbeca4f15f6761c0868feae0d53ea80097fbbd210b6

那么该容器内的进程只会在0,1,2,3的CPU上运行。

通过下面指令也可以看到容器中进程与CPU 内核的绑定关系,可以认为达到了绑定CPU 内核的目的。

[root@localhost ~]# docker exec 1b69dabb453b taskset -c -p 1
pid 1's current affinity list: 0-3            #容器内部第一个进程编号一般为1

尽量使用绑定内核的方式分配CPU资源给容器进程使用,然后在配合--cpu-shares选项动态调整CPU使用资源的比例。

7.5CPU 配额控制参数的混合案例

        通过--cpuset-cpus 指定容器A 使用CPU 内核0,容器B 只是用CPU 内核1。在主机上只有这两个容器使用对应CPU 内核的情况,它们各自占用全部的内核资源,--cpu-shares 没有明显效果。

        --cpuset-cpus、--cpuset-mems 参数只在多核、多内存节点上的服务器上有效,并且必须与实际的物理配置匹配,否则也无法达到资源控制的目的。

        在系统具有多个CPU 内核的情况下,需要通过cpuset-cpus 为容器CPU 内核才能比较方便地进行测试。

用下列命令创建测试用的容器:

[root@localhost ~]# docker run -itd --name cpu3 --cpuset-cpus 3 --cpu-shares 512 centos:stress stress -c 1004cb93f1d76e4b30e001ad7b2afc51dfcedef818970edcf0763aba56a45cea2[root@localhost ~]# docker exec -it 004cb93f1d76 /bin/bash[root@004cb93f1d76 /]# toptop - 03:57:24 up  6:14,  0 users,  load average: 5.43, 15.35, 15.68
Tasks:   4 total,   2 running,   2 sleeping,   0 stopped,   0 zombie
%Cpu(s):  8.0 us,  0.1 sy,  0.0 ni, 91.9 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :  3861080 total,  1396020 free,   291912 used,  2173148 buff/cache
KiB Swap:  2097148 total,  2097148 free,        0 used.  3170028 avail Mem PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND                      7 root      20   0    7260     96      0 R 100.0  0.0   1:18.70 stress                       1 root      20   0    7260    436    352 S   0.0  0.0   0:00.01 stress                       8 root      20   0   11772   1800   1444 S   0.0  0.0   0:00.01 bash                         24 root      20   0   51880   1872   1388 R   0.0  0.0   0:00.00 top  
[root@localhost ~]# docker run -itd --name cpu4 --cpuset-cpus 3 --cpu-shares 1024 centos:stress stress -c 18998d47911ade2227fe71fce69a125be34a5714868cb7d4fbf3fe40a9fae4164[root@localhost ~]# docker exec -it 8998d47911ad /bin/bash[root@8998d47911ad /]# toptop - 04:00:08 up  6:16,  0 users,  load average: 2.03, 9.50, 13.38
Tasks:   4 total,   2 running,   2 sleeping,   0 stopped,   0 zombie
%Cpu(s): 24.8 us,  0.0 sy,  0.0 ni, 74.7 id,  0.0 wa,  0.0 hi,  0.5 si,  0.0 st
KiB Mem :  3861080 total,  1383908 free,   302924 used,  2174248 buff/cache
KiB Swap:  2097148 total,  2097148 free,        0 used.  3158056 avail Mem PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND                      7 root      20   0    7260     92      0 R  66.4  0.0   0:48.96 stress                       1 root      20   0    7260    432    352 S   0.0  0.0   0:00.01 stress                       8 root      20   0   11772   1804   1448 S   0.0  0.0   0:00.01 bash                         24 root      20   0   51852   1912   1408 R   0.0  0.0   0:00.00 top   

        上面的centos:stress 镜像安装了stress 工具,用来测试CPU 和内存的负载。通过在两个容器上分别执行stress -c 1 命令,将会给系统一个随机负载,产生1 个进程。这个进程都反复不停的计算由rand() 产生随机数的平方根,直到资源耗尽。

        观察到宿主机上的CPU 试用率,第三个内核的使用率接近100%,并且一批进程的CPU 使用率明显存在2:1 的使用比例的对比。

7.6、内存限制

与操作系统类似,容器可使用的内存包括两部分:物理内存和swap。Docker 通过下面两组参数来控制容器内存的使用量。

  1. -m --memory:设置内存的使用限额,例如100M, 1024M
  2. --memory-swap:设置内存swap 的使用限额。

当执行如下命令:

其含义是允许该容器最多使用200M 的内存和300M 的swap。

[root@localhost ~]# docker run -it -m 200M --memory-swap=300M progrium/stress --vm 1 --vm-bytes 280Mstress: info: [1] dispatching hogs: 0 cpu, 0 io, 1 vm, 0 hdd
stress: dbug: [1] using backoff sleep of 3000us
stress: dbug: [1] --> hogvm worker 1 [7] forked
stress: dbug: [7] allocating 293601280 bytes ...
stress: dbug: [7] touching bytes in strides of 4096 bytes ...
stress: dbug: [7] freed 293601280 bytes
stress: dbug: [7] allocating 293601280 bytes ...
stress: dbug: [7] touching bytes in strides of 4096 bytes ...
stress: dbug: [7] freed 293601280 bytes
  1. --vm 1:启动1 个内存工作线程。
  2. --vm-bytes 280M:每个线程分配280M 内存。

默认情况下,容器可以使用主机上的所有空闲内存。与CPU 的cgroups 配置类似,docker 会自动为容器在目录/sys/fs/cgroup/memory/docker/<容器的完整长ID>中创建相应cgroup 配置文件。

因为280M 在可分配的范围(300M)内,所以工作线程能够正常工作,其过程是:

  1. 分配280M 内存。
  2. 释放280M 内存。
  3. 再分配280M 内存。
  4. 再释放280M 内存。
  5. 一直循环......

如果让工作线程分配的内存超过300M,分配的内存超过限额,stress 线程报错,容器退出。

[root@localhost ~]# docker run -it -m 200M --memory-swap=300M progrium/stress --vm 1 --vm-bytes 380Mstress: info: [1] dispatching hogs: 0 cpu, 0 io, 1 vm, 0 hdd
stress: dbug: [1] using backoff sleep of 3000us
stress: dbug: [1] --> hogvm worker 1 [7] forked
stress: dbug: [7] allocating 398458880 bytes ...
stress: dbug: [7] touching bytes in strides of 4096 bytes ...
stress: FAIL: [1] (416) <-- worker 7 got signal 9
stress: WARN: [1] (418) now reaping child worker processes
stress: FAIL: [1] (422) kill error: No such process
stress: FAIL: [1] (452) failed run completed in 0s

7.7Block IO 的限制

默认情况下,所有容器能平等地读写磁盘,可以通过设置--blkio-weight 参数来改变容器block IO 的优先级。

--blkio-weight 与--cpu-shares 类似,设置的是相对权重值,默认为500。在下面的例子中,容器A 读写磁盘的带宽是容器B 的两倍。

[root@localhost ~]# docker run -it --name container_A --blkio-weight 600 centos:stress /bin/bash[root@9a1ade37e4a2 /]# cat /sys/fs/cgroup/blkio/blkio.weight600[root@9a1ade37e4a2 /]# cat /sys/fs/cgroup/blkio/blkio.weight[root@localhost ~]# [root@localhost ~]# docker run -it --name container_B --blkio-weight 300 centos:stress /bin/bash[root@82d39cad4b92 /]# cat /sys/fs/cgroup/blkio/blkio.weight300

7.8、限制bps iops

如果在一台服务器上进行容器的混合部署,那么会存在同时几个程序写磁盘数据的情况,这时可以通过--device-write-iops选项来限制每秒写io次数来限制制定设备的写速度。相应的还有--device-read-iops选项可以限制读取IO的速度,但是这种方法只能限制设备,而不能限制分区,相应的Cgroup写配置文件为/sys/fs/cgroup/blkio/容器ID/ blkio.throttle.write_iops_device。

  1. bps 是byte per second,每秒读写的数据量。
  2. iops 是io per second,每秒IO 的次数。

可通过以下参数控制容器的bps 和iops:

  • --device-read-bps,限制读某个设备的bps
  • --device-write-bps,限制写某个设备的bps
  • --device-read-iops,限制读某个设备的iops
  • --device-write-iops,限制写某个设备的iops

下面的示例是限制容器写/dev/sda 的速率为5 MB/s。

[root@localhost ~]# docker run -it --device-write-bps /dev/sda:5MB centos:stress /bin/bash[root@f4b37691fa4d /]# dd if=/dev/zero of=test bs=1M count=100 oflag=direct100+0 records in
100+0 records out
104857600 bytes (105 MB) copied, 20.006 s, 5.2 MB/s

        通过dd 测试在容器中写磁盘的速度。因为容器的文件系统是在host /dev/sda 上的,在容器中写文件相当于对宿主机/dev/sda 进行写操作。另外,oflag=direct 指定用direct

IO 方式写文件,这样--device-write-bps 才能生效。

结果表明,bps 5.2 MB/s 在限速5MB/s 左右。作为对比测试,如果不限速,结果如下:

[root@localhost ~]# docker run -it centos:stress /bin/bash[root@d324fcfe3cbb /]# dd if=/dev/zero of=test bs=1M count=100100+0 records in
100+0 records out
104857600 bytes (105 MB) copied, 0.0527029 s, 2.0 GB/s

8、Docker数据持久化

8.1、数据持久化介绍

在Docker中若要想实现容器数据的持久化(所谓的数据持久化即数据不随着Container的结束而销毁),需要将数据从宿主机挂载到容器中。目前Docker提供了三种不同的方式将数据从宿主机挂载到容器中。

(1)Volumes:Docker会管理宿主机文件系统的一部分资源,默认位于 /var/lib/docker/volumes 目录中;(最常用的方式)

[root@localhost ~]# docker run -it -v /opt/ centos /bin/bashUnable to find image 'centos:latest' locally
latest: Pulling from library/centos
a1d0c7532777: Already exists 
Digest: sha256:a27fd8080b517143cbbbab9dfb7c8571c40d67d534bbdee55bd6c473f432b177
Status: Downloaded newer image for centos:latest[root@630ab274dcd8 /]# touch /opt/test.txt[root@630ab274dcd8 /]# ls /opt/         test.txt[root@localhost ~]# ls /var/lib/docker/volumes/3e75601aeaa96d13807f38d22fd13666db6ead38af2ce543a249e5515d497bca/_data/test.txt

 目前所有Container的数据都保存在/var/lib/docker/volumes/目录下边,由于没有在创建时指定卷,所以Docker帮我们默认创建许多匿名(就上面这一堆很长ID的名字)卷。

(2)bind mounts:意为着可以指定存储在宿主机系统的任意位置;(比较常用的方式)

但是bind mounts在不同的宿主机系统之间是不可移植的,比如Windows和Linux的存储结构是不一样的,bind mount所指向的host目录也不能一样。这也是为什么bind mount不能出现在Dockerfile中的原因,因为会导致Dockerfile无法移植。

(3)tmpfs:挂载存储在宿主机系统的内存中,而不会写入宿主机的文件系统;(一般都不会用的方式)

8.2、Volume的基本使用

8.2.1、管理卷

创建一个自定义容器卷

[root@localhost ~]# docker volume create nginx-data
nginx-data

 查看所有容器卷

[root@localhost ~]# docker volume lsDRIVER    VOLUME NAME
local     nginx-data

查看指定容器卷详情信息

[root@localhost ~]# docker volume inspect nginx-data
[{"CreatedAt": "0001-01-01T00:00:00Z","Driver": "local","Labels": null,"Mountpoint": "/var/lib/docker/volumes/nginx-data/_data","Name": "nginx-data","Options": null,"Scope": "local"}
]

8.2.2、创建使用指定卷的容器

有了自定义容器卷,我们可以创建一个使用这个数据卷的容器

[root@localhost ~]# docker run -d -it --name=nginx -p 800:80 -v nginx-data:/usr/share/nginx/html nginx67a5acf397730011f702127cd7d5001f3c87d12060ed2b0e7bf2015c0d8ba94e[root@localhost ~]# docker exec -it nginx /bin/bashroot@67a5acf39773:/# ls /usr/share/nginx/html/50x.html  index.html

        选项-v代表挂载数据卷,这里使用自定数据卷nginx-data,并且将数据卷挂载到 /usr/share/nginx/html (这个目录是yum安装nginx的默认网页目录)。如果没有通过-v指定,那么Docker会默认帮我们创建匿名数据卷进行映射和挂载。

注意:

  1. 数据卷下无文件,显示容器对应目录下的文件
  2. 数据卷下有文件,显示数据卷原有文件,并将容器对应目录的文件隐藏,显示数据卷文件

可以看到网页目录下有两个默认页面,这时我们可以查看宿主机文件系统的数据

[root@localhost ~]# ls /var/lib/docker/volumes/nginx-data/_data/50x.html  index.html

   可以看到容器里面的两个默认页面,由此可知Volume帮我们做了类似于一个软链接的功能。在容器里边的改动,我们可以在宿主机里感知,而在宿主机里面的改动,在容器里边可以感知到。

  如果我们手动stop并且remove当前nginx容器,我们会发现容器卷里面的文件还在,并没有随着容器被删除掉。

[root@localhost ~]# docker stop nginxnginx[root@localhost ~]# docker rm nginxnginx[root@localhost ~]# ls /var/lib/docker/volumes/nginx-data/_data/50x.html  index.html

  所以在数据卷里边的东西是可以持久化的。如果下次还需要创建一个nginx容器,那么时候复用当前数据卷里面文件的。

[root@localhost ~]# docker run -d -it --name=nginx2 -p 801:80 -v nginx-data:/usr/share/nginx/html nginx6741a1c3ea19a45333e0330191c023bc3e04bfad85498edd4c160e0871996ea7[root@localhost ~]# docker exec -it nginx2 /bin/bashroot@6741a1c3ea19:/# ls /usr/share/nginx/html/50x.html  index.html

  此外,我们还可以启动多个nginx容器实例,共享同一个数据卷。数据卷的复用性和扩展性较强的。

8.2.3、清理卷

如果不再使用自定义数据卷了,那么可以手动清理掉:

[root@localhost ~]# docker volume rm -f nginx-datanginx-data[root@localhost ~]# docker volume lsDRIVER    VOLUME NAME

8.3、Bind Mounts的基本使用

8.3.1 使用卷创建一个容器

[root@localhost ~]# docker run -d -it --name=nginx -p 800:80 -v /wwwroot:/usr/share/nginx/html nginx0bc4e5c1975bb7fff3d8e5886e78c6711de7204ba7a09cddb24c410421c53f23

        这里指定了将宿主机上的 /wwwroot 目录(如果没有会自动创建)挂载到 /usr/share/nginx/html (这个目录是yum安装nginx的默认网页目录)。

docker挂载的默认权限是读写(rw),用户也可以通过ro指定为只读

[root@localhost ~]# docker run -d -it --name=nginx2 -p 801:80 -v /wwwroot:/usr/share/nginx/html:ro nginx0aba96663db35032504213f6aab44424e88d2e0a2e39592e3f1c94ae23e35269
[root@localhost ~]# docker exec -it nginx /bin/bashroot@0bc4e5c1975b:/# ls /usr/share/nginx/html/

   可以看到,与volumes不同,bind mounts的方式会隐藏掉被挂载目录里面的内容(如果非空的话),这里是/usr/share/nginx/html 目录下的内容被隐藏掉了,因此我们看不到。

但是,我们可以将宿主机上的文件随时挂载到容器中:

新建一个index.html,并在容器中查看

[root@localhost ~]# echo "test html" > /wwwroot/index.html[root@localhost ~]# docker exec -it nginx /bin/bashroot@0bc4e5c1975b:/# ls /usr/share/nginx/html/index.html

8.3.2、验证绑定

[root@localhost ~]# docker inspect nginx"HostConfig": {"Binds": ["/wwwroot:/usr/share/nginx/html"],

8.3.3、清理

[root@localhost ~]# docker stop nginxnginx[root@localhost ~]# docker rm nginxnginx[root@localhost ~]# ls /wwwroot/index.html

        同volumes一样,当我们清理掉容器之后,挂载目录里面的文件仍然还在,不会随着容器的结束而消失,从而实现数据持久化。

8.4数据卷容器

8.4.1、数据卷容器概述

用户需要在容器之间共享一些持续性更新的数据时,可以使用数据卷容器。数据容器也是一个普通的容器。里边带有设置好的数据卷,专门提供给其他容器挂载使用。 通过--volumes-from 数据卷容器名来实现。

8.4.2、创建数据卷容器

[root@localhost ~]# docker run -it -v /dbdata:/dbdata --name=dbdata centos /bin/bashUnable to find image 'centos:latest' locally
latest: Pulling from library/centos
a1d0c7532777: Already exists 
Digest: sha256:a27fd8080b517143cbbbab9dfb7c8571c40d67d534bbdee55bd6c473f432b177
Status: Downloaded newer image for centos:latest[root@36cd7b069c08 /]# exitexit

//创建一个数据卷容器,并在其中创建一个数据卷挂载到/dbdata

进入test1容器创建文件测试

[root@localhost ~]# docker run -it --volumes-from dbdata --name test1 centos /bin/bash[root@e06b68cbae34 /]# lsbin	dev  home  lib64       media  opt   root  sbin	sys  usr
dbdata	etc  lib   lost+found  mnt    proc  run   srv	tmp  var[root@e06b68cbae34 /]# touch dbdata/crushlinux[root@e06b68cbae34 /]# lsbin	dev  home  lib64       media  opt   root  sbin	sys  usr
dbdata	etc  lib   lost+found  mnt    proc  run   srv	tmp  var[root@e06b68cbae34 /]# ls dbdata/crushlinux[root@e06b68cbae34 /]# exitexit

//在test1容器的/dbdata目录创建测试文件

进入test2容器验证结果

[root@localhost ~]# docker run -it --volumes-from dbdata --name test2 centos /bin/bash[root@bbaf174a1aa9 /]# lsbin	dev  home  lib64       media  opt   root  sbin	sys  usr
dbdata	etc  lib   lost+found  mnt    proc  run   srv	tmp  var[root@bbaf174a1aa9 /]# ls dbdata/crushlinux

说明:

  1. 可以多次使用--volume-from参数从多个容器挂载多个目录。也可以从其他已经挂载了数据卷的容器来挂载数据卷(类似传递)。
  2. 再次强调:如果删除了挂载的容器,数据卷不会被自动删除。如果要删除容器的时候同时删除数据卷,需加上-v参数。

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

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

相关文章

操作系统的运行机制、中断和异常、系统调用

&#x1f40c;个人主页&#xff1a; &#x1f40c; 叶落闲庭 &#x1f4a8;我的专栏&#xff1a;&#x1f4a8; c语言 数据结构 javaweb 石可破也&#xff0c;而不可夺坚&#xff1b;丹可磨也&#xff0c;而不可夺赤。 操作系统 一、操作系统的运行机制1.1内核程序1.2应用程序1…

maven如何打包你会吗?

1.新建一个maven项目&#xff0c;在main/java中建立Main类 public class Main {public static void main(String[] args) {System.out.println("hello java ...");} } 2.添加依赖&#xff0c;使其成为可执行包 <build><plugins><!--打包成为可执行包-…

ESP32cam系列教程003:ESP32cam实现远程 HTTP_OTA 自动升级

文章目录 1.什么是 OTA2. ESP32cam HTTP_OTA 本地准备2.1 HTTP OTA 升级原理2.2 开发板本地基准程序&#xff08;程序版本&#xff1a;1_0_0&#xff09;2.3 开发板升级程序&#xff08;程序版本&#xff1a;1_0_1&#xff09;2.4 本地 HTTP_OTA 升级测试2.4.1 本地运行一个 HT…

ARP协议请求

文章目录 作用请求与应答流程数据包ARP协议以太网帧协议具体应用 作用 通过 IP地址 查找 MAC地址。 请求与应答流程 A&#xff1a;数据发送主机 B&#xff1a;目标主机 目前只知道目标主机IP地址&#xff0c;想把数据发送过去&#xff0c;需要查询到目标主机的MAC地址&#x…

Git使用详细教程

1. cmd面板的常用命令 clear&#xff1a;清屏cd 文件夹名称----进入文件夹cd … 进入上一级目录(两个点)dir 查看当前目录下的文件和文件夹(全拼:directory)Is 查看当前目录下的文件和文件夹touch 文件名----创建文件echo 内容 > 创建文件名----创建文件并写入内容rm 文件名…

vue3.3-TinyMCE:TinyMCE富文本编辑器基础使用

一、TinyMCE官网 GitHub - tinymce/tinymce TinyMCE中文文档中文手册 二、官网介绍 TinyMCE是一款易用、且功能强大的所见即所得的富文本编辑器。同类程序有&#xff1a;UEditor、Kindeditor、Simditor、CKEditor、wangEditor、Suneditor、froala等等。 TinyMCE的优势&…

LabVIEW开发小型减阻试验平台

LabVIEW开发小型减阻试验平台 湍流摩擦在粘性流体的阻力中起着重要作用&#xff0c;减少湍流摩擦是流体力学领域的热门话题之一。在油气管道的长距离流体输送中&#xff0c;泵站提供的几乎所有动力都用于克服流体的胫骨摩擦。在流体输送领域&#xff0c;船舶的蒙皮摩擦阻力占总…

css实现水平居中

代码示例 <div class"box"><div class"box1"></div> </div>1.弹性布局&#xff1a;&#xff08;推荐&#xff09; display:flex&#xff1b; 这些要添加在父级的&#xff0c;是父级的属性 //父级添加display:flex; //父级添加jus…

SpringCloud Gateway 在微服务架构下的最佳实践

作者&#xff1a;徐靖峰&#xff08;岛风&#xff09; 前言 本文整理自云原生技术实践营广州站 Meetup 的分享&#xff0c;其中的经验来自于我们团队开发的阿里云 CSB 2.0 这款产品&#xff0c;其基于开源 SpringCloud Gateway 开发&#xff0c;在完全兼容开源用法的前提下&a…

腾讯云TencentOS Server镜像系统常见问题解答

腾讯云TencentOS Server镜像是腾讯云推出的Linux操作系统&#xff0c;完全兼容CentOS生态和操作方式&#xff0c;TencentOS Server操作系统为云上运行的应用程序提供稳定、安全和高性能的执行环境&#xff0c;TencentOS可以运行在腾讯云CVM全规格实例上&#xff0c;包括黑石物理…

【波浪动态特效】基于jquery实现页面底部波浪动画效果(附完整源码下载)

文章目录 写在前面涉及知识点实现效果1、搭建页面1.1、创建两个片区1.2、创建波浪区域1.3、静态页面源码 2、JS实现波浪效果2.1 动画原理2.2 动画源码 3、源码分享3.1 百度网盘3.2 123云盘3.3 邮箱留言 总结 写在前面 想必搭建过企业官网的大多数对这个效果不陌生吧&#xff0…

Java之Map接口

文章目录 简述Map中key-value特点 Map接口的常用方法Map的主要实现类&#xff1a;HashMapHashMap概述 Map实现类之二&#xff1a;LinkedHashMapMap实现类之三&#xff1a;TreeMapMap实现类之四&#xff1a;Hashtable&#xff08;古老实现类&#xff09;Map实现类之五&#xff1…

AI 3D结构光技术加持,小米引领智能门锁新标准

一直以来&#xff0c;小米智能门锁系列产品让更多家庭走进了安全便捷的智能生活&#xff0c;安全至上的设计让很多家庭都轻松告别了随身钥匙。 7月27日&#xff0c;小米正式推出小米智能门锁M20 Pro&#xff0c;再一次引领智能门锁产品的发展潮流。该款门锁采用AI 3D结构光技术…

2023软件设计师中级备考经验分享(文中有资料链接分享)

先摊结论吧&#xff0c;软考中级设计师备考只是备考半个月&#xff08;期间还摆烂了几天&#xff09;&#xff0c;然而成绩如下&#xff1a; 我自己都没想到会这么好的成绩。。。 上午题&#xff1a;推荐把软考通APP里的历年真题刷3-4遍&#xff0c;直接刷真题&#xff0c;然后…

关于 Ubuntu 长按 shift 无效, 按 Esc 直接进入 grub 改密码的解决方法

本次长按shift没有反应&#xff0c;直接进入了系统界面&#xff0c;所以改用长按Esc键&#xff0c;步骤如下&#xff1a; 1. 长按esc&#xff0c;进入grub>提示 2.输入grub>normal &#xff0c;回车 3.上一步回车后&#xff0c;继续敲击Esc &#xff0c;出现grub界面 …

无法加载 DLL“xxxx.dll”: 找不到指定的模块。 (异常来自 HRESULT:0x8007007E)。

目录 1、DLL引用的问题 1、DLL引用的问题 这两篇文章说的很好&#xff0c;C# DllImport用法和路径问题和无法加载 DLL“xxxx.dll”: 找不到指定的模块 但我折腾了2天&#xff0c;还是没有解决。后来请同事帮忙&#xff0c;发现&#xff0c;服务器上少装东西了…下图的红框这个…

java学习路程之篇四、进阶知识、石头迷阵游戏、绘制界面、打乱石头方块、移动业务、游戏判定胜利、统计步数、重新游戏

文章目录 1、绘制界面2、打乱石头方块3、移动业务4、游戏判定胜利5、统计步数6、重新游戏7、完整代码 1、绘制界面 2、打乱石头方块 3、移动业务 4、游戏判定胜利 5、统计步数 6、重新游戏 7、完整代码 java之石头迷阵单击游戏、继承、接口、窗体、事件、组件、按钮、图片

深度学习——常见注意力机制

1.SENet SENet属于通道注意力机制。2017年提出&#xff0c;是imageNet最后的冠军 SENet采用的方法是对于特征层赋予权值。 重点在于如何赋权 1.将输入信息的所有通道平均池化。 2.平均池化后进行两次全连接&#xff0c;第一次全连接链接的神经元较少&#xff0c;第二次全连…

【HarmonyOS】键盘遮挡输入框时,实现输入框显示在键盘上方

【关键字】 harmonyOS、键盘遮挡input&#xff0c;键盘高度监听 【写在前面】 在使用API6、API7开发HarmonyOS应用时&#xff0c;常出现页面中需要输入input&#xff0c;但是若input位置在页面下方&#xff0c;在input获取焦点的时候&#xff0c;会出现软键盘挡住input情况&a…

数字图像处理-彩色图像处理

文章目录 一、彩色模型1.1RGB彩色模型1.2CMY和CMYK彩色模型1.3HSI彩色模型 二、伪彩色图像处理2.1灰度分层2.2灰度到彩色的变换 三、彩色图像的分割3.1RGB中的彩色图像分割3.2彩色边缘检测 一、彩色模型 1.1RGB彩色模型 RGB空间是生活中最常用的一个模型&#xff0c;电视机、…