近万字详解Docker常用功能合集(Docker系列第1章,共3章)

这篇具有很好参考价值的文章主要介绍了近万字详解Docker常用功能合集(Docker系列第1章,共3章)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

极简概括

官网:https://www.docker.com
利用比虚拟机更加轻量级的容器化虚拟技术,能够低成本的把当前环境快速打包或在新环境部署相同子环境的运维工具,基于Go语言实现,跨平台(支持Linux、Windows、MacOS)。
通俗类比:无论什么牌子什么价位的主机,都可以利用同一个的Windows镜像文件安装相同的系统,同时也支持对操作系统的不同进度进行打包,方便安装到另一台设备上。

解决问题

  • 环境统一:本地开发环境、测试环境、生产环境不一致,本地测试没问题,一到线上就出故障。Docker 可以打包应用程序及其所有依赖项,确保在任何环境中都能以相同的方式运行。
  • 降低运维成本: Docker 可以将应用程序及其所有依赖项打包到一个称为 Docker 镜像的容器中。这些镜像可以在秒级时间快速部署到任何支持 Docker 的主机上。
  • 微服务架构支持: Docker 容器可以用于构建和部署微服务架构中的各个组件,每个微服务可以打包为一个独立的容器。这样可以实现高度的可扩展性、灵活性和可维护性。

适用场景

  • 卷:为什么要学?很多人都会docker,不得不卷。
  • 微服务架构:Docker 被广泛用于微服务架构中,每个微服务可以打包为一个 Docker 容器,使得应用程序模块化、可扩展和易于管理。
  • 持续集成/持续部署(CI/CD):Docker 可以用于构建 CI/CD 管道,通过容器化应用程序,可以实现自动化的构建、测试和部署流程,提高开发团队的效率和交付速度。
  • 开发环境一致性:开发团队可以使用 Docker 来创建一致的开发环境,确保开发、测试和生产环境之间的一致性,减少因环境差异导致的问题。
  • 混合云和跨平台部署:由于 Docker 容器具有高度可移植性,可以在不同的云平台和操作系统上运行,适用于混合云环境和跨平台部署。

优点

  • 轻量级: Docker 容器比传统的虚拟机更轻量级,因为它们共享主机系统的内核,并且不需要运行完整的操作系统。
  • 快速操作: 由于 Docker 容器与宿主机共享内核,并且容器中的应用程序直接运行在主机的操作系统上,因此它们的安装、部署、启动速度非常快。
  • 可移植: Docker 容器可以在不同的环境中轻松移植和部署,一次打包处处运行。
  • 一致性: Docker 容器提供了一个一致的运行环境,确保应用程序在开发、测试和生产环境中的行为一致。
  • 易于管理: Docker 提供了强大的命令,使得可以完成度容器、镜像、仓库的各种操作。
  • 资源隔离: Docker 容器提供了一定程度的资源隔离,使得不同的容器可以在同一台主机上并行运行而不会相互干扰。
  • 生态系统支持: Docker 拥有庞大的生态系统,意味着有成熟的解决方案,不容易遇见死胡同。

缺点

  • 学习成本: Docker 拥有自己的一套规则,需要运维或者开发者做功课。
  • 沙箱逃逸:docker不比虚拟机有更好的隔离性,可能引发沙箱逃逸漏洞,(虚拟机也有沙箱逃逸漏洞)。
  • 系统兼容:32位的CentOS系统不支持安装Docker。
  • 像是MySQL、等需要高可用和高IO的组件,docker能部署,但有缺点(文末有详解)。

Docker三板斧

  • 容器:是一个独立、轻量级的运行环境,一些组件在容器里运行,(类比装好的Windows系统)。
  • 镜像:是一个只读的模板,存放了应用程序的各种配置,可以被分享、复制,(类比Windows的ISO镜像文件)。
  • 仓库:类似GitHub,做镜像的共享与托管,可见其流行程度和重要性,(类比各版本Windows的ISO镜像文件下载网站)。

理解虚拟化中的虚拟

  • 从软硬件交互角度讲:操作系统的运行离不开计算机硬件(CPU、内存、硬盘),然而容器却依附于宿主机又建立的子系统,再和硬件交互,从上帝视角看,容器就像虚拟出来的真实系统一样。
  • 从软硬件数据角度讲:docker中的数据,对于磁盘硬件实体而言,也只是一块实体的二进制数据,所谓的镜像、系统、容器都存在于软体,像虚拟出来的世界一样。

对比与虚拟机

  • 量级不同:虚拟机是运行一整个系统,而docker是利用宿主机的内核部分。
  • 隔离性:Docker 提供了进程级别的隔离,虚拟机提供了更高级的隔离策略。
  • 部署难度:docker几个命令轻松部署,而虚拟机需要手动安装镜像。

为什么Docker会比虚拟机快

docker利用的是宿主机的内核,不需要像虚拟机一样重新加载操作系统进行各种初始化环节。
多个docker实例共享宿主机内核资源,而多个虚拟机是重新运行一套操作系统。

安装(CentOS7.6环境)

yum install -y yum-utils
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
yum -y install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
systemctl start docker

systemctl enable docker

#测试运行,如果出现版本号,则说明安装成功
docker -v
Docker version 26.0.0, build 2ae903e

配置阿里云镜像加速

登录阿里云之后,搜索容器镜像服务,进入专题页面后到控制台,点击个人版,点击镜像工具,然后点击镜像加速器。
复制上面的bash shell,然后执行它。
/etc/docker/daemon.json 文件是 Docker 使用的配置文件,用于指定 Docker 守护进程的各种选项和设置。

mkdir -p /etc/docker
tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://xxxx.mirror.aliyuncs.com"]
}
EOF
systemctl daemon-reload
systemctl restart docker

卸载(CentOS7.6环境)

yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine

存储在中的映像、容器、卷和网络/var/lib/docker/卸载Docker时不会自动删除,所以需要
rm -rf /var/lib/docker /var/lib/containerd

虚悬镜像

  • 概念:虚悬镜像又叫做dangling image。仓库名,标签名都是none的镜像,是虚悬镜像。
  • 原因:docker import或者docker build时没有设置名字和版本号。
  • 删除:可以使用rmi命令删除,也可以使用docker image prune删除所有虚悬镜像。

基础命令

启动、停止、重启
systemctl start/stop/restart docker
开机自启动
systemctl enable docker
命令帮助文档
docker --help
某个命令帮助文档
docker 命令 --help
查看状态
systemctl status docker
docker概要
docker info


docker system df
TYPE(类型)            TOTAL(资源总数)     ACTIVE(当前运行的资源总数)    SIZE(占空间大小)      RECLAIMABLE(可回收空间大小)
Images(镜像)          0                         0                                 0B                        0B
Containers(容器)      0                         0                                 0B                        0B
Local Volumes(本地卷) 0                         0                                 0B                        0B
Build Cache(构建缓存) 0                         0                                 0B                        0B

容器命令

docker run 镜像名称 [-it] [shell类型] [/bin/bash]

docker会在本机中寻找该镜像,如果本机存在则直接运行,如果不存在,则会去阿里云 docker hub上找,如果能找到下载后运行,找不到则报错。

注意同一个镜像可以启多个容器,每个容器之间,默认不互通。

--name 为容器指定一个名字,如果不指定,系统随机分配
-d 后台守护进程运行并返回容器id。
-i 以交互模式运行容器。
-t 为容器分配一个终端。
-P 随机端口映射。
-p 指定端口映射 -p 外部端口:容器端口。
-it会经常配合使用,因为运行的组件,可能需要进入这个容器去做一些操作。
例如要运行一个Ubuntu,进入Ubuntu,要输入docker run -it ubuntu /bin/bash
/bin/bash表示用什么shell启动一个终端。

docker ps [-qa]

类比宿主机的ps,docker 只是针对容器的ps
CONTAINER ID(容器id)   IMAGE(镜像id)    COMMAND(终端)  CREATED(创建时间)     STATUS(状态)  PORTS(端口)  NAMES(容器名,docker run --name时会显示自定义的用户名)
162cdb700348            ba6acccedd29       "/bin/bash"     13 seconds ago         Up 12 seconds                romantic_kare

-a 显示全部的容器,默认只显示正在运行的容器
-q 只显示容器id

docker ps中的STATUS字段,如果显示UP字样,说明已经启动,如果显示Exited字样,说明已经停止运行。

退出容器

方式一:exit 容器停止。
方式二:Ctrl p q 容器不会停止。

docker exec [-it] [-d] 容器id [/bin/bash]

用例:docker exec -it 5e66cda41f9a /bin/bash
重新进入容器,再容器内部的命令行执行exit,不会导致容器停止。
-d 后台守护进程运行并返回容器id。
-i 以交互模式运行容器。
-t 为容器分配一个终端。

docker attach 容器id

用例:docker attach 容器id
重新进入容器,再容器内部的命令行执行exit,会导致容器停止。

docker start/stop/restart 容器id或容器名

启动、关闭、重启容器。
注意开启容器,不等于进入这个容器。

docker rm [-f] 容器id或容器名

删除容器。

docker rm $(docker ps -aq)可删除所有容器。

docker logs 容器id

查看某个容器的日志。

docker top 容器id

类比top命令,查看容器的资源占用情况
UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
root                27931               27910               0                   00:00               ?                   00:00:00            nginx: master process nginx -g daemon off;

UID: 进程的用户标识符(User ID),表示进程所属的用户。
PID: 进程标识符(Process ID),是内核为每个进程分配的唯一标识符。
PPID: 父进程标识符(Parent Process ID),表示启动当前进程的父进程的PID。
C: 进程的CPU利用率,表示进程正在使用的CPU核心数量。
STIME: 进程的启动时间,表示进程启动的时间戳。
TTY: 进程所关联的终端设备(如果有)。
TIME: 进程已经使用的CPU时间。
CMD: 进程的命令行,表示正在运行的进程的命令。

docker inspect 容器id

会返回一个大json,用来显示容器的信息

docker cp

容器复制到宿主机:docker cp 容器id:/路径 /路径
宿主机复制到容器:docker cp /路径 容器id:/路径
文件复制与容器的开始与结束无关。

镜像命令

docker images [-a] [-q]

列出本机上的所有镜像
REPOSITORY(镜像仓库源)    TAG(标签版本号)       IMAGE ID(镜像ID)       CREATED(创建时间)        SIZE(大小)
同一个REPOSITORY有多个TAG,好比CentOS,以后6、7、8的版本一样。
如果不指定一个镜像的版本标签,docker将默认使用latest镜像。

-a 表示列列举本地的所有惊喜那个
-q 表示只显示镜像id

docker rmi [-f] [镜像id或镜像名] [...]

删除某镜像
-f 强制删除,不加-f,正在运行的容器将无法删除,不推荐使用。

docker rmi -f $(docker images -qa) 删除全部,极不推荐用。

docker export 容器id > 文件名

导出容器
docker export 容器id > 容器名.dat

docker import 备份容器文件 容器名[:tag]

通过文件导入容器,如果不写tag,那默认是latest。

docker commit -m 注释 -a 作者 容器id 镜像名[:版本号]

提交容器副本,使其成为一个新的镜像

docker tag old_name:old_tag new_name:new_tag

相当于在原有的基础上复制出来一份镜像并改名,用docker images查看,old,和new是两条数据。

仓库命令

docker search 组件名 [--limit n]

NAME            DESCRIPTION                   STARS(星星)     OFFICIAL(是否官方)   AUTOMATED(是否自动构建)
作者/包名        Official build of Nginx.      18879            [OK]

--limit n,可进行数量筛选前几个

docker pull 镜像名[:版本]

类比git pull,向共有仓库拉取镜像。

docker push [OPTIONS] NAME[:TAG]

将镜像推送到远程仓库,例如推送到阿里云。
 docker push registry.cn-hangzhou.aliyuncs.com/xxx/xxx:[镜像版本号]

本地镜像发布到阿里云

  1. 请免费开启容器镜像服务,然后选择一个地区的节点,我选的是杭州。
  2. 在访问凭证页面先设置密码,对docker login命令的密码做铺垫。https://cr.console.aliyun.com/cn-hangzhou/instance/credentials
  3. 新建命名空间,然后新建镜像仓库,创建镜像仓库的最后一步选择,本地仓库。https://cr.console.aliyun.com/cn-hangzhou/instance/namespaces
  4. 创建完成之后,跟随阿里云的操作指南第3步,然后去执行它
docker login --username=xxx registry.cn-hangzhou.aliyuncs.com
docker tag [ImageId] registry.cn-hangzhou.aliyuncs.com/xxx/xxx:[镜像版本号]
docker push registry.cn-hangzhou.aliyuncs.com/xxx/xxx:[镜像版本号]


可使用以下命令去从远程仓库拉取镜像到本地
docker pull registry.cn-hangzhou.aliyuncs.com/xxx/xxx:[镜像版本号]

本地镜像发布到公司或个人的私有云(Docker Registry)

当前测试的机器局域网IP是192.168.0.180,需要再来一台机器模拟Docker Registry,IP为192.168.0.160,首先按照上文所述安装docker,不然docker命令不存在。

在160机器上,安装registry,执行docker images 查看是否安装成功。
docker pull registry

在160机器上,创建一个容器卷映射地址
mkdir /docker

在160机器上,后台运行这个registry
docker run --name docker_registry -d  -v /docker:/docker --privileged=true -p 5000:5000 registry

在160机器上,查看是否成功运行
docker ps

再180机器上,vim /etc/docker/daemon.json,指定Docker客户端可以连接的不安全的Registry地址,
避免报错Get "https://192.168.0.160:5000/v2/": http: server gave HTTP response to HTTPS client
,
"insecure-registries":["192.168.0.160:5000"]

在180机器上,重启docker。
systemctl daemon-reload
systemctl restart docker

在180机器上,使用docker tag 命令做个镜像复制和更名。
注意这个名字192.168.0.160:5000/zs_ubuntu:0.0.1,要和docker push后面跟的保持一致
docker tag zs_ubuntu:0.0.1 192.168.0.160:5000/zs_ubuntu:0.0.1


在180机器上,执行推送,注意这个192.168.0.160:5000/zs_ubuntu:0.0.1,要与docker tag的对应上。
docker push 192.168.0.160:5000/zs_ubuntu:0.0.1

在180机器上,验证是否push成功(除了IP和端口,其余都是固定路径):
curl 192.168.0.160:5000/v2/_catalog
{"repositories":["zs_ubuntu"]}

168.0.160:5000/v2/_catalog能看见镜像名,但是看不见镜像版本号,到时候拉取会存在困难,此时就需要其它命令的参与:
curl http://192.168.0.160:5000/v2/镜像名称/tags/list
curl http://192.168.0.160:5000/v2/zs_ubuntu/tags/list


在其它机器上,其它人拉取镜像:
docker pull 192.168.0.160:5000/zs_ubuntu:0.0.1

在160机器上,对私有仓库存放镜像的增操作:
如上所讲。

在160机器上,对私有仓库存放镜像的删操作:
docker exec -it registry容器id sh
镜像文件是被放到 目录下的,/var/lib/registry/docker/registry/v2/repositories,在这里直接删除指定目录即可。

在160机器上,对私有仓库存放镜像的改操作:
不常用。

在160机器上,对私有仓库存放镜像的查操作:
curl 192.168.0.160:5000/v2/_catalog

为什么不建议在docker中使用MySQL

  • 数据高可用问题:数据库存储的是公司的各项核心数据,求的是稳定,而不是一时候的部署方便。使用容器卷可以持久化数据。但是如果容器不小心停止,或者配置出错,造成的事故影响高可用,为了保证MySQL数据的高可用,下足了功夫,引入了redo log和不同的刷盘机制来应对性能与高可用之间的权衡,而docker的Union FS 镜像层提供持久存储,但是高可用缺乏保证。
  • 性能问题:MySQL最大的性能瓶颈在于IO,原本是刷盘后就可以了,若使用了docker,如果没有容器卷很不保险,如果使用了容器卷,读写问题又多了一个流程。
  • 使用受限:整个业务所使用的技术组件中,压力最大的往往就是数据库,MySQL包了一层容器,相当于多了一个环节,CPU、内存、磁盘IO、网络等,可能会受到一些限制。

Portainer:轻量级容器监控工具

  • 官方文档:https://docs.portainer.io
  • 极简概括:Portainer是一个轻量级的容器管理工具,它提供了用户界面用于管理Docker容器和集群,常用的Docker命令行操作,都可以通过这个组件在图形化界面完成。
  • 注意:默认的9000端口,如果宿主机对内占用或者其它容器对外开放了9000端口,Nginx与PHP进行TCP方式的通信(还有一种UNIX的Socket通信),PHP-FPM进程会占用9000端口,所以需要修改portainer的端口为非9000。
  • 安装并初始化:
安装
docker run --name portainer --restart=always -d -p 8000:8000 -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock portainer/portainer
若端口冲突,可以这样改
docker run --name portainer --restart=always -d -p 8000:8000 -p 9001:9001 -v /var/run/docker.sock:/var/run/docker.sock portainer/portainer

使用docker ps查看是否运行
docker ps
CONTAINER ID   IMAGE                 COMMAND        CREATED          STATUS          PORTS                                                                                  NAMES
073537d3fb66   portainer/portainer   "/portainer"   30 seconds ago   Up 29 seconds   0.0.0.0:8000->8000/tcp, :::8000->8000/tcp, 0.0.0.0:9000->9000/tcp, :::9000->9000/tcp   portainer

访问相关页面并注册用户:
http://192.168.0.180:9000/#/init/admin

注册成功后点击local,再次点击local,就会看到Dashboard仪表盘页面。
http://192.168.0.180:9000/#/dashboard

之后进行各种查看和操作……

CAdvisor+InfluxDB+Granfana(CIG重量级容器监控工具)

这种对于个人开发者或小公司跟本用不上,个人开发者和小公司不需要太复杂的管理工具,而大公司有专门的运维,不需要开发者关注,仅做了解。文章来源地址https://www.toymoban.com/news/detail-850828.html

  • 极简概括:简称CIG(C负责监控收集,I负责存储数据,G负责展示图表),是对docker进行重量级的监控工具。
  • CAdvisor(Container Advisor)是一个用于监控容器性能的工具。它能够收集关于运行中的容器的信息,例如 CPU 使用率、内存使用量、网络统计等,并将这些数据提供给其他监控或可视化工具。
  • InfluxDB 是一个时间序列数据库,特别适用于处理和存储监控数据。InfluxDB 允许将收集到的数据存储起来,并提供灵活的查询功能,以便进行数据分析和可视化。
  • Grafana 则是一个开源的监控和数据可视化平台。它能够与各种数据源集成,包括 InfluxDB,用于创建丰富的监控仪表盘和报表,展示监控数据的实时和历史变化,以及执行定制化的数据分析。

到了这里,关于近万字详解Docker常用功能合集(Docker系列第1章,共3章)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【docker常用命令系列】Docker Build语法用法示例详解

    Docker Build是Docker提供的一个命令,用于根据Dockerfile构建自定义的镜像。通过Docker Build,可以将应用程序、环境和依赖项打包到一个可移植的容器中,使得应用在不同环境下都能以相同的方式运行。 docker build [OPTIONS] PATH | URL | - 是 docker build 命令的语法说明。下面解释每个部分

    2024年04月14日
    浏览(36)
  • 【前端】常用功能合集

    将每个中文字符变为两个字符,比如“中文”替换成“中文” 匹配任意每9个字符或9个字符加,在匹配的字符串后加一个换行符 将所有的去除 xnn 匹配ASCII代码中十六进制代码为nn的字符 [^x00-xff] 表示匹配非单字节的字符,例如 汉字,汉字符号 ,单字节字符包括 英文字母,

    2024年02月10日
    浏览(44)
  • 功能测试合集:弹出窗口的常用测试点,全程满满干豁

    前言 手机 App 弹窗是目前流行的一种内容展示形式,根据内容性质可以划分为消息、通知、广告、营销等等,展现形式也比较多变,刚上手 测试 特容易手忙脚乱,为了帮助新人能够快速入门,笔者在此将弹窗常见的测试点一一进行罗列,如果有所遗漏也请不吝指教,非常感

    2023年04月18日
    浏览(39)
  • 【C++入门】string类常用方法(万字详解)

    1.STL简介 1.1什么是STL STL(standard template libaray-标准模板库):是C++标准库的重要组成部分,不仅是一个可复用的组件库,而且是一个包罗数据结构与算法的软件框架 。 1.2STL的版本 原始版本 Alexander Stepanov、Meng Lee 在惠普实验室完成的原始版本,本着开源精神,他们声明允许任何

    2024年02月10日
    浏览(37)
  • 新电脑的正确打开方式——(近万字图文并茂详细分步骤讲解)【万一那天你就有新电脑了呢】包括个性化·等你来解锁哦

    新电脑买回来如何让配置?新电脑买回来如何装饰?新电脑买回来如何让电脑更干净?等等,这些问题都在困惑着大家,那么接下来我急来告诉大家——新电脑的正确打开方式吧!🎊 建议收藏此博客,万一那天你也有属于自己的新机了呢😁 似此星辰非昨夜,为谁风露立中宵

    2024年02月09日
    浏览(51)
  • 【Unity自制手册】unity常用API大全——一篇文章足以(万字详解)

    👨‍💻个人主页 :@元宇宙-秩沅 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 本文由 秩沅 原创 收录于专栏 unity 实战系列 ⭐相关文章⭐ ⭐【软件设计师高频考点暴击】 -本站最全-unity常用API大全(万字详解),不信你不收藏 -关于游戏剧情模式中用到的基础简单API -控制游

    2024年02月12日
    浏览(47)
  • 万字长文深入理解Docker镜像分层原理、容器数据卷、网络通信架构(Docker系列第2章,共3章)

    在执行docker pull时,会发现多个Pull complete 字样,就能体现分层,如果是一个文件,只会有一个Pull complete 。 概念:文件系统是计算机系统中用于组织和管理数据存储的一种方式。它定义了数据如何存储、命名、访问和修改的方式。 举例:如Windows自带的NTFS、FAT32、EXFAT,和L

    2024年04月14日
    浏览(34)
  • 工具系列(九) 本文(2万字) | 在ubuntu中安装docker教程 | 在Linux下Docker将镜像导出 | 上传至服务器 | 部署并创建容器 |

    点击进入专栏: 《人工智能专栏》 Python与Python | 机器学习 | 深度学习 | 目标检测 | YOLOv5及其改进 | YOLOv8及其改进 | 关键知识点 | 各种工具教程

    2024年01月19日
    浏览(74)
  • 深入理解高并发超卖一系列问题与解决方案(近7万字详解,跳槽涨薪必备宝藏珍藏级分享)

    能遇上高并发的,基本都是有点规模的公司,小公司基本都是CRUD。 想去一线城市跳槽,想去有高并发的公司,但是没有高并发经验,没有高并发的经验,就去不了高并发的公司,去不了这样的公司,就没有高并发经验,前狼后虎两头堵的困境,干就完了。 超卖问题是属于并

    2024年04月22日
    浏览(29)
  • docker基本教程(基本包括所有常用功能)

    1、安装教程 docker安装地址: https://docs.docker.com/engine/install/ubuntu/ 2、docker使用 下载镜像: 查看镜像: 从镜像生成容器: 容器查看: 关闭容器: 开启容器: 进入容器: 3、镜像与容器的保存 容器保存为镜像: 镜像保存为本地文件: 4、镜像加载 5、空间 查看空间: 全盘清理: build cache

    2024年02月17日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包