docker

Docker的使用

1、安装与卸载

阿里云查看系统版本 cat /etc/os-release

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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"

安装

帮助文档:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#1、卸载旧的版本
yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine

#2、需要的安装包
yum install -y yum-utils

#3、设置镜像的仓库
yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo #默认国外

yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

#清空 yum 缓存更新软件包的索引
yum makecache fast

#4、安装docker
yum install docker-ce docker-ce-cli containerd.io

#5、启动 docker
systemctl start docker

#6、测试是否安装成功
docker version

#7、测试 hello-world
docker run hello-world

#8、查看下载的镜像
docker images

卸载docker

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

2、阿里云镜像加速

  1. 找到阿里云容器镜像服务

  2. 镜像加速器

  3. 配置使用

    1
    2
    3
    4
    5
    6
    7
    8
    sudo mkdir -p /etc/docker
    sudo tee /etc/docker/daemon.json <<-'EOF'
    {
    "registry-mirrors": ["https://r9elbpdx.mirror.aliyuncs.com"]
    }
    EOF
    sudo systemctl daemon-reload
    sudo systemctl restart docker

3、docker 底层原理

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

dockerServer 接受到 Docker-Client 的指令就会执行这个命令。

docker为什么比VM快?

  1. docker 有着比虚拟机更少的抽象层

  2. docker 利用的是宿主机的内核,VM 需要的是 Guest OS。

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

4、docker的常用命令

帮助命令

1
2
3
docker version #显示 docker 的版本信息
docker info # 显示 docker 更详细的信息
docker 命令 --help # 万能命令,列出所有的命令

镜像命令

1
2
3
4
5
6
7
8
9
10
11
12
13
docker images #查看所有本地的主机上的镜像
#解释
REPOSITORY 镜像的仓库源

docker search 镜像仓库名 # 搜索镜像

docker pull 镜像仓库名[:tag] # 下载镜像 docker pull mysql:5.7

docker rmi -f $(docker images -aq) #删除全部镜像

docker rmi -f 镜像id # 根据镜像id删除镜像,加上空格 删除多个镜像

docker rmi $(docker images | grep "none" | awk '{print $3}') # 删除名称为 none 镜像

容器命令

有了镜像才可以创建容器,linux,下载一个centos镜像来测试学习

1
docker pull centos

新建容器并启动

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
docker run [可选参数] image
# 参数说明
--name="Name" 容器名字,用来区分容器
-d 后台方式运行
-it 使用交互方式运行,进入容器查看内容
-p 指定容器端口 -p 8080:8080
-p 主机端口:容器端口(常用)
-P 随机指定端口

# docker run -it centos /bin/bash 运行 centos容器并进入

# 列出所有的运行容器
docker ps
参数: -a # 列出当前正在运行的容器+历史运行过的容器
-n=? # 显示最近创建的容器
-q #只显示容器的编号

退出容器
exit # 容器停止并退出
ctrl + p + q # 容器不停止。退出

删除容器
docker rm 容器id # 删除指定的容器,不能删除正在运行的容器,如果要强制删除 rm -f
docker rm -f $(docker ps -aq) # 删除所有的容器
docker ps -a -q|xargs docker rm # 删除所有的容器
docker stop $(docker ps -aq) #停止所有容器

启动和停止容器的操作
docker start 容器id
docker restart 容器id
docker stop 容器id
docker kill 容器id

常用的其它命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 后台启动容器
docker run -d centos
# 问题 docker ps,发现 cnetos 停止了
# 常见的坑:docker 容器使用后台运行就必须要有一个前台进程,docker 发现没有应用,就会自动停止
# nginx,容器启动后,发现自己没有提供服务,就会立刻停止,就是没有程序了

#往容器中输入命令
docker run -d centos /bin/sh -c "while true;do echo hqz;sleep 1;done"
# 查看日志 -tf 显示日志
docker logs -tf --tail [显示行数] 容器id

# 查看容器中进程信息 ps top命令
docker top 容器id

# 查看镜像的元数据
docker inspect 容器id

# 进入当前正在运行的容器
docker exec -it 容器id bashShell #进入容器后开启一个新的终端,可以在里面操作(常用)
docker attach 容器id # 进入容器正在执行的终端,不会启动新的进程

#从容器内拷贝文件到主机上,从主机到容器就是反过来
docker cp 容器id:容器内路径 目的地主机路径

5、docker使用镜像实例

docker部署nginx

  1. 搜索:在 dockerhub上搜索镜像

  2. 拉取镜像

  3. 启动镜像

    1
    2
    3
    4
    5
    6
    7
    docker run -d --name nginx01 -p 1314:80 nginx
    # -d:后台运行
    # --name:命名
    # -p:通过服务器的1314端口去访问容器内的nginx的80端口

    # 进入 nginx
    docker exec -it nginx01 /bin/bash

docker部署tomcat

1
2
3
docker run -it --rm tomcat:9.0 # 官方使用 --rm 用完即删
docker exec -it tomcat01 /bin/bash
docker run -it -p 8080:8080 --name mytomcat -v /home/webapps:/usr/local/apache-tomcat-9.0.52/webapps -v /home/logs:/usr/local/apache-tomcat-9.0.52/logs d1f14679a750

docker部署es+kibana

1
2
3
4
5
6
7
8
9
10
11
# es 
# 1、暴露的端口很多
# 2、占用内存大
# 3、es的数据需要放置到安全目录挂载
# --net somenetwork : 网络配置
docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:tag

docker stats # 查看cpu的状态

# 增加内存的限制,修改配置文件 -e 环境配置修改
docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx512m" elasticsearch:tag

6、可视化管理界面

  1. portainer

    Docker的图形化界面管理工具,提供一个后台面板进行操作

    1
    2
    docker run -d -p 8088:9000 \
    --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer

7、commit镜像

保存当前容器的状态,就可以通过commit提交来获取一个镜像

1
2
# docker commit 提交容器成为一个新的版本
docker commit -m="提交的描述消息" -a="作者" 容器id 目标镜像名:版本号

8、容器数据卷

容器之间数据共享的技术,docker容器中产生的数据同步到本地。

将容器内的目录挂载到linux上面。

容器的持久化和同步操作,容器间也是可以数据共享的

数据卷的使用

直接使用命令来挂载 -v

1
2
3
4
docker run -it -v /home/ceshi:/home centos /bin/bash
# 宿主机路径:容器路径
# 可以通过 docker inspect 容器id 查看挂载情况
# 好处:目录挂载之后修改配置文件只需要在本地修改即可,容器内会自动同步。

mysql实战

  1. 下载镜像

    1
    docker pull mysql:5.7
  2. 运行mysql容器,启动mysql要设置密码

    1
    2
    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=123456 --name mysql01 mysql:5.7
    # 启动成功之后可以使用 navicat 连接数据库

具名和匿名挂载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 匿名挂载:只写容器内路径,不写容器外路径
# -v 容器内路径
docker run -d -p --name nginx01 -v /etc/nginx

# 查看所有卷 volume 的情况
docker volume ls

# 具名挂载 juming-nginx:命名
docker run -d -p --name nginx02 -v juming-nginx:/etc/nginx nginx
# 通过 docker volume inspect juming-nginx 查看挂载的目录
# 没有指定目录的情况下都是在 /var/lib/docker/volumes/xxxx/_data

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

9、Dockerfile 挂载目录

用来构建docker镜像的构建文件,命令脚本

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

1
2
3
4
5
6
7
8
9
# 文件内容 指令(大写)
FROM centos

VOLUME ["volume01","volume02"] # 挂载目录,匿名挂载

CMD echo "...end..."
CMD /bin/bash

# 这里的每个命令都是一层

启动 dockerfile 命令

1
2
docker build -f /home/docker-test-volume/dockerfile01 -t hqz/centos:1.0 .
# dockerfile文件路径 镜像名及版本

查看挂载目录

1
docker inspect 容器id	# 找 mounts

10、数据卷容器

容器之间同步数据,如:多个mysql同步数据

1
2
docker run -it --name docker02 --volume-from docker01 镜像id
# 容器名 父容器名

容器之间配置信息的传递,数据卷容器的生命周期一直持续到没有容器使用为止。

容器删除本地数据不会删除。

11、docker 镜像导出与加载

1
2
3
4
5
6
7
8
# 加载
docker load -i xxx.tar

# 导入
docker save -o xxx.tar aaa:tag

# 修改进行名称
docker tag 【镜像ID】【镜像名称】:【tag版本信息】

12、Dockerfile

命令参数脚本

构建步骤:

  1. 编写一个 dockerfile 脚本
  2. docker build 构建成为一个镜像
  3. docker run 运行镜像
  4. docker push 发布镜像(dockerHub、阿里云镜像仓库)

dockerfile构建过程

基础知识:

  1. 每个保留关键字(指令)都必须是大写字母
  2. 以从上到下的顺序执行
  3. # 表示注释
  4. 每个指令都会创建提交一个新的镜像层,并提交

步骤:开发、部署、运维

Dockerfile:构建文件,定义了一切的步骤,源代码

DockerImages:通过 DockerFile 构建生成的镜像,最终发布和运行的产品

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

DockerFile指令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
FROM			# 基础镜像,一切从这里开始构建 centos
MAINTAINER # 镜像的作者,姓名 + 邮箱
RUN # 镜像构建的时候需要运行的命令
ADD # 步骤:tomcat镜像,这个tomcat压缩包,添加内容
WORKDIR # 镜像的工作目录
VOLUME # 挂载的目录
EXPOSE # 暴露端口配置
CMD # 指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT # 指定这个容器启动的时候要运行的命令,可以追加命令
ONBUILD # 当构建一个被继承 Dockerfile 这个时候就会运行ONBUILD 的指令,触发指令
COPY # 类似 ADD 将文件拷贝到镜像中
ENV # 构建的时候设置环境变量
ARG # 参数变量,构建时生效
LABEL # 指定元数据信息,一些

实战测试

构建自己的 centos

1
2
3
4
5
6
7
8
9
10
11
12
13
14
FROM centos
MAINTAINER hqz<1161028135@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

docker history 镜像id 可以查看镜像的构建过程

CMD 与 ENTRYPOINT

1
2
3
4
5
6
FROM centos
CMD ["ls","-a"]

# 执行这个 Dockerfile 在运行镜像时会执行 ls -a 命令列出文件列表
# 只会执行最后一个 CMD
# 运行镜像时不可追加命令,会替换
1
2
3
4
FROM centos
ENTRYPOINT ["ls","-a"]

# 运行镜像时可以追加命令

实战:Tomcat镜像

  1. 准备镜像文件 tomcat 压缩包,jdk 压缩包
  2. 编写 Dockerfile 文件

如果文件命名为 Dockerfile 就不需要 -f 指令了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
FROM centos
MAINTAINER hqz<1161028135@qq.com>

COPY readme.txt /usr/local/readme.txt # 将 readme.txt 拷贝到容器内部

ADD jdk-8u11-linux-x64.tar.gz /usr/local/ # 压缩包会自动解压
ADD apache-tomcat-9.0.22.tar.gz /usr/local/

RUN yum -y install vim

ENV MYPATH /usr/local # 镜像启动之后就会进入到这个目录
WORKDIR $MYPATH

ENV JAVA_HOME /usr/local/jdk1.8.0_11
ENV CLASSPATH $JAVA_HOME/lib/dt.jar;$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.22
ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.22
ENV PATH $PATH;$JAVA_HOME/bin;$CATALINA_HOME/lib;$CATALINA_HOME/bin # 把目录放入总的 PATH 中

EXPOSE 8080

CMD /usr/local/apache-tomcat-9.0.22/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.22/bin/logs/catalina.out
1
docker build Dockerfile -t diytomcat:1.0 .
1
2
# 执行命令启动
docker run -d -p 9090:8080 --name mytomcat -v /home/hqz/build/tomcat/test:/usr/local/apache-tomcat-9.0.22/webapps/test -v /home/hqz/build/tomcat/tomcatlogs/:/usr/local/apache-tomcat-9.0.22/logs diytomcat:1.0

13、发布镜像

DockerHub

  1. 注册账号
  2. 确定这个账号可以登录
  3. 在服务器上提交自己的镜像
1
2
# docker login --help
docker login -u -p
  1. 登录完毕后就可以提交镜像了,docker push

    1
    2
    docker tag 原镜像名 用户名/镜像名:版本号
    docker push 作者/镜像名:版本号

阿里云镜像服务

  1. 登录阿里云
  2. 找到容器镜像服务
  3. 创建命名空间
  4. 创建容器镜像
  5. 镜像页面中有详细的拉取上传过程

14、SpringBoot微服务打包Docker镜像

  1. 构建springboot项目
  2. 打包应用
  3. 编写dockerfile
  4. 构建镜像
  5. 发布运行

15、docker 网络模式详解及容器间网络通信

安装 docker 之后会默认创建三种网络,通过 docker netword ls 查看

1
2
3
4
5
[root@izbp1btjqbqb2cvsfklp0yz ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
3c96e315279b bridge bridge local
962cd40d899a host host local
c08aa62ab73b none null local
网络模式 简介
bridge 为每一个容器分配、设置 IP 等,并将容器连接到一个 docker0 虚拟网桥,默认为该模式
host 容器将不会虚拟出自己的网卡,配置自己的 IP 等,而是使用宿主机的 IP 和端口
none 容器有独立的 Network namespace,但并没有对其进行任何网络设置,如分配 veth pair 和网络桥接,IP 等
container 新创建的容器不会创建自己的网卡和配置自己的 IP,而是和一个指定的容器共享 IP、端口范围

15.1、bridge 网络模式

​ 在该模式中,Docker 守护进程创建了一个虚拟的以太网桥 docker0,新建的容器会自动桥接到这个接口,附加在其上的任何网卡之间都能自动转发数据包。

​ 默认情况下,守护进程会创建一对对等虚拟设备接口 veth pair,将其中一个接口设置为容器的 eth0接口(容器的网卡),另一个接口放置在宿主机的命名空间中,以类似 vethxxx 这样的名字命名,从而将宿主机上所有的容器连接到这个内部网络上

dokcer-bridge

bridge 网络模式的使用,只需要在创建容器的时通过参数 --net bridge 或者 --network bridge 指定即可,当然这也是创建容器默认使用的网络模式,也就是说这个参数是可以省略的

bridge 桥接模式的实现步骤主要如下:

  • Docker Daemon 利用 veth pair 技术,在宿主机上创建一对对等虚拟网络接口设备,假设为 veth0 和 veth1。而 veth pair 技术的特性可以保证无论哪一个 veth 接收到网络报文,都会将报文传输给另一方
  • Docker Daemon 将 veth0 附加到 Docker Daemon 创建的 docker0 网桥上,保证宿主机的网络报文可以发往 veth0
  • Docker Daemon 将 veth1 添加到 Docker Container 所属的 namespace 下,并改名为 eth0,如此一来,宿主机的网络报文若发往 veth0,则立即会被 Container 的 eth0 接收,实现宿主机到 Docker Container 网络的联通性,同时,也保证 Docker Container 单独使用 eth0,实现容器网络环境的隔离性

15.2、host 网络模式

  • host 网络模式需要在创建容器时通过参数 --net host 或者 --network host 指定
  • 采用 host 网络模式的 Docker Container,可以直接使用宿主机的 IP 地址与外界进行通信,若宿主机的 eth0 是一个公有 IP,那么容器也拥有这个公有 IP。同时容器内服务的端口也可以使用宿主机的端口,无需额外进行 NAT 转换
  • host 网络模式可以让容器共享宿主机网络栈,这样的好处是外部主机与容器直接通信,但是容器的网络缺少隔离性

host网络模式

15.3、none 网络模式

  • none 网络模式是指禁用网络功能,只有 lo 接口 local 的简写,代表 127.0.0.1,即 localhost 本地环回接口。在创建容器时通过参数 --net none 或者 --network none 指定
  • none 网络模式即不为 Docker Container 创建任何的网络环境,容器内部就只能使用 loopback 网络设备,不会再有其它的网络资源

15.4、Container 网络模式

  • Container 网络模式是 Docker 中一种较为特别的网络模式,在创建容器时通过参数 --net container:已运行的容器名称|ID 或者 --network container:已运行的容器名称|ID 指定
  • 处于这个模式下的 Docker 容器会共享一个网络栈,这样两个容器之间就可以通过 localhost 高效快速通信
  • Container 网络模式即新创建的容器不会创建自己的网卡,配置自己的 IP,而是和一个指定的容器共享 IP、端口范围等。同样两个容器除了网络方面相同之外,其他的如文件系统、进程列表还是隔离的

Container网络模式

16、自定义网络

  • 在实际开发中更推荐使用自定义的网络进行容器管理,以及启用容器名称到 IP 地址的自动 DNS 解析
  • 通过 docker network create + 网络名 命令可以创建自定义网络模式,默认时 bridge 模式
  • 使用自定义的网络,容器之间启用了容器名称到 IP 地址的自动 DNS 解析,前提是创建容器时需要使用 --name 指定容器名称

docker 安装 mysql

1
docker run --name mysql -p 3307:3306 -e MYSQL_ROOT_PASSWORD=sqlserver -d mysql:5.7 --character -set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci

docker 安装 redis

1
2
3
4
5
6
docker run --name redis -p 6380:6379 -d redis
# 设置密码
cd /usr/local/bin/
./redis-cli
CONFIG get requirepass
CONFIG set requirepass x

常用镜像的配置

17、nacos

1
2
3
4
5
6
7
8
9
10
11
12
# nacos 镜像的拉取
docker pull nacos/nacos-server

# nacos 的启动
docker run --env MODE=standalone --name nacos -d -p 8848:8848 nacos/nacos-server

# 重新启动
docker ps -a
docker start [name]
docker star

# 配置数据库,进入容器,修改 config/application.properties 配置 host、dbName、username、password,也可挂载出配置文件

18、mysql

1
2
3
docker pull mysql:5.7

docker run --name mysql5.7 --character-set-server=utf8mb4 --collation-server=utf8mb4_general_ci -e MYSQL_ROOT_PASSWORD=sqlserver -v /e/docker-data/mysql/data:/var/lib/mysql -p 3306:3306 -d mysql:5.7

19、postgresql

1
2
3
docker pull postgresql:12.0

docker run --name postgresql -e POSTGRES_PASSWORD=123456#789 -v /e/docker-data/postgresql/data:/var/lib/postgresql/data -p 5433:5432 -d postgres:12.0

20、redis

1
2
3
4
docker pull redis

# 运行
docker run -p 6379:6379 --name redis -v /e/docker-data/redis/docker-redis-config/redis.conf:/etc/redis/redis.conf -v /e/docker-data/redis/docker-redis-data:/data -d redis redis-server /etc/redis/redis.conf --appendonly yes

21、rabbitmq

1
2
3
4
5
docker pull rabbitmq

docker run --hostname my_rabbit --name local_mq -p 15672:15672 -p 5672:5672 -v /e/docker-data/rabbitmq/data:/var/lib/rabbitmq/mnesia/ -d rabbitmq

docker run -d --name QcRabbitmq -e RABBITMQ_DEFAULT_USER=qcsys -e RABBITMQ_DEFAULT_PASS=qcsys -p 15672:15672 -p 5672:5672 rabbitmq:management

22、zookeeper

1
2
3
4
5
6
7
docker pull zookeeper

docker run -d -e TZ="Asia/Shanghai" -p 2181:2181 -v :/data --name zookeeper --restart always zookeeper

docker run -it --rm --link zookeeper:zookeeper zookeeper zkCli.sh -server zookeeper

docker run -it --rm --link zoo1:zk1 --link zoo2:zk2 --link zoo3:zk3 --net zookeeper_default zookeeper:3.4.11 zkCli.sh -server zk1:2181,zk2:2181,zk3:2181

23、Nginx

1
2
3
4
5
6
7
8
9
10
docker run --name zhengzhou-nginx -p 22000:80 -v /data/docker/nginx/html:/usr/share/nginx/html -v /data/docker/nginx/conf/nginx.conf:/etc/nginx/nginx.conf  -v /data/docker/nginx/logs:/var/log/nginx -v /data/docker/nginx/conf.d:/etc/nginx/conf.d -v /data/docker/nginx/static: -d --restart=always nginx:latest

location / {
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://127.0.0.1:8888;
# index index.html index.htm;
}

docker maven

1
2
3
4
5
6
7
8
9
# 安装docker的注册服务器(windows 上 docker 开启 Expose daemon on tcp://localhost:2375 without TLS)
docker run -d -p 5000:5000 --restart=always --name registry registry:2
# 开启docker远程api,原来文件描述符fd方式改为tcp,指定端口2375
vi /usr/lib/systemd/system/docker.service
# 让docker支持http上传镜像文件
echo '{ "insecure-registries":["ip:5000"] }' > /etc/docker/daemon.json
# 重启docker
systemctl daemon-reload && systemctl restart docker
# 本地jar包的pom文件引入docker插件
  • Copyrights © 2022-2023 hqz

请我喝杯咖啡吧~

支付宝
微信