当前位置: 首页 > news >正文

Docker使用教程

Docker

名词解释

  • 镜像(image):Docker镜像就是一个模板,可以通过这个模板来创建容器服务。
  • 容器(container):Docker利用容器技术,独立运行一个或者一组应用,通过镜像创建。
  • 仓库(repository):仓库就是存放镜像的地方,仓库分为公有仓库和私有仓库,Docker Hub(默认是国外的),阿里云有容器服务器(配置镜像加速)。

安装Docker

# 卸载旧版本命令
yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate \docker-engine
# 安装yum-utils包
yum install -y yum-utils
# 设置阿里云镜像
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# 更新yum软件包索引到最新
yum makecache fast
# 安装Docker docker-ce 社区版 ee 企业版
yum install docker-ce docker-ce-cli containerd.io
# 启动Docker
systemctl start docker
# 查看是否安装成功
docker version

卸载Docker

# 卸载Docker
yum remove docker-ce docker-ce-cli containerd.io
# 主机上的映像、容器、卷或自定义配置文件不会自动删除。要删除所有映像、容器和卷
rm -rf /var/lib/docker
rm -rf /var/lib/containerd

镜像加速器

在这里插入图片描述

常用命令

帮助命令

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

帮助文档地址 https://docs.docker.com/engine/reference/commandline/docker/

镜像命令

docker search mysql # 搜索镜像
docker pull mysql # 下载镜像
docker rmi -f 镜像id # 删除指定镜像
docker rmi -f 镜像id 镜像id 镜像id # 删除多个镜像
docker rmi -f $(docker images -aq) # 删除全部的镜像

容器命令

docker run [可选参数] image
# 参数说明
--name="Name" 容器名字
-d 后台方式运行
-it 使用交互方式运行,进入容器查看内容
-p 指定容器端口
-P 随机指定端口
# 列出所有运行的容器
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 start 容器id # 启动容器
docker restart 容器id # 重启容器
docker stop 容器id # 停止当前正在运行的容器
docker kill 容器id # 强制停止当前正在运行的容器
# 查看日志
docker logs
-tf # 显示日志
--tail number # 要显示的日志条数
docker logs -tf --tail 10 容器id
# 查看容器中进程信息
docker top 容器id
# 查看镜像的元数据
docker inspect 容器id
# 进入当前正在运行的容器
docker exec -it 容器id /bin/bash
docker attach 容器id
# docker exec 和 docker attach 的区别
docker attach 进入容器,再退出会导致容器停止;docker exec 进入容器,再退出不会导致容器停止
# 从容器内拷贝文件到主机上
docker cp 容器id:容器内路径 目的地主机路径

部署ES

docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms512m -Xmx512m" elasticsearch:7.6.2

可视化

portainer

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

Rancher

commit镜像

docker commit -m="提交的描述信息" -a="作者" 容器id 目标镜像名:[TAG]

容器数据卷

什么是容器数据卷

Docker 是将应用和环境打包成一个镜像。

这样,数据就不应该保存在容器中,否则容器删除,数据就会丢失,有着非常大的风险。

为此,容器和主机之间需要有一个数据共享技术,使得在 Docker 容器中产生的数据能够同步到本地。

这就是数据卷技术。其本质上是一个目录挂载,将容器内的目录挂载到主机上。

使用数据卷

docker run -it -v 主机目录:容器内目录
MySQL容器数据持久化
# 拉取MySQL镜像
docker pull mysql:5.7
# 启动MySQL容器
docker run -d -p 3306:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=sunhui0805 --name mysql mysql:5.7

具名和匿名挂载

匿名挂载,-v只写了容器内路径,没有写容器外路径

具名挂载,-v指定卷名:容器内路径

所有docker容器内的卷,没有指定目录的情况下都是在/var/lib/docker/volumes/xxx/_data

通过具名挂载可以方便的找到数据卷

-v 容器内路径 # 匿名挂载
-v 卷名:容器内路径 # 具名挂载
-v /宿主机路径::容器内路径 # 指定路径挂载
# 通过-v 容器内路径:ro rw 改变读写权限
ro readonly # 只读
rw readwrite # 读写
# ro说明这个路径只能通过宿主机来操作,容器内部无法操作

数据卷容器

# docker02公用docker01的数据卷
docker run -it --name docker02 --volumes-from docker01 sonki/centos:1.0
# 数据卷容器的生命周期会一直持续到没有容器使用为止,但是一旦持久化到本地,本地的数据是不会删除的

Dockerfile

Dockerfile是用来构建Docker镜像的文件,可以理解为命令参数脚本

规则

在这里插入图片描述

创建镜像仓库

在这里插入图片描述

提交镜像

在这里插入图片描述

Docker网络

在Docker安装后,主机会为Docker分配一个网卡,名为docker0。
该网卡使用桥接模式,使用的是veth-pair技术。

启动两个容器

[root@sail ~]# docker run -d -p 8081:8080 --name=tomcat01 tomcat
29a06eab16e73f34458b77a520081083fe536d8eb34eb67dbb9c6632fc720687
[root@sail ~]# docker run -d -p 8082:8080 --name=tomcat02 tomcat
442add0d94cef631e0f531dff9d8f55b7e2f1aaeb088f742c3d8e240d4f9cc7d
[root@sail ~]# docker ps
CONTAINER ID   IMAGE     COMMAND             CREATED          STATUS          PORTS                    NAMES
442add0d94ce   tomcat    "catalina.sh run"   4 seconds ago    Up 3 seconds    0.0.0.0:8082->8080/tcp   tomcat02
29a06eab16e7   tomcat    "catalina.sh run"   15 seconds ago   Up 14 seconds   0.0.0.0:8081->8080/tcp   tomcat01

查看Linux网络

[root@sail tomcat]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000link/ether 00:16:3e:30:01:20 brd ff:ff:ff:ff:ff:ffinet 172.24.19.94/18 brd 172.24.63.255 scope global dynamic eth0valid_lft 310199524sec preferred_lft 310199524sec
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group defaultlink/ether 02:42:23:ae:ac:24 brd ff:ff:ff:ff:ff:ffinet 172.17.0.1/16 brd 172.17.255.255 scope global docker0valid_lft forever preferred_lft forever
7: veth4a18f1b@if110: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default link/ether 52:69:3c:bc:83:4a brd ff:ff:ff:ff:ff:ff link-netnsid 0
9: veth296fd0d@if112: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default link/ether 76:3c:34:e8:c4:90 brd ff:ff:ff:ff:ff:ff link-netnsid 1

Docker每启动一个容器,就会分配一个IP。

查看容器的内部网络

[root@sail ~]# docker exec -it tomcat01 ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft forever
6: eth0@if7: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0valid_lft forever preferred_lft forever
[root@sail ~]# docker exec -it tomcat02 ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft forever
8: eth0@if9: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0valid_lft forever preferred_lft forever

可以看到容器内IP与本机IP成对出现,这就是veth-pair技术。

容器访问docker0测试

[root@sail ~]# docker exec -it tomcat01 ping 172.17.0.1
PING 172.17.0.1 (172.17.0.1) 56(84) bytes of data.
64 bytes from 172.17.0.1: icmp_seq=1 ttl=64 time=0.845 ms
64 bytes from 172.17.0.1: icmp_seq=2 ttl=64 time=0.139 ms
64 bytes from 172.17.0.1: icmp_seq=3 ttl=64 time=0.130 ms
64 bytes from 172.17.0.1: icmp_seq=4 ttl=64 time=0.134 ms
64 bytes from 172.17.0.1: icmp_seq=5 ttl=64 time=0.119 ms
64 bytes from 172.17.0.1: icmp_seq=6 ttl=64 time=0.082 ms

容器与docker0之间是可以访问的。

容器与容器之间访问

docker0相当于一个路由器,各个容器都与docker0相连,容器之间的通信通过路由器来转发。

在这里插入图片描述

Docker中的所有网络接口都是虚拟的,相当于内网传递。
只要删除容器,对应网络就会删除。

容器间网络连接

docker run --link

—link本质就是修改host映射。

自定义网络

创建自定义网络
[root@sail ~]# docker network create -d bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
801fbbe1b38c81b12ce90aa9139561b5843dca64b4b17718b6e2622369f9be67
- -d:网络模式
- -subnet:子网
- -gateway:网关
查看创建的网络
[root@sail ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
f3eeb014197a   bridge    bridge    local
28d77e958643   host      host      local
801fbbe1b38c   mynet     bridge    local
c3ff850e96f0   none      null      local
[root@sail ~]# docker network inspect 801fbbe1b38c
[{"Name": "mynet","Id": "801fbbe1b38c81b12ce90aa9139561b5843dca64b4b17718b6e2622369f9be67","Created": "2021-12-30T17:39:43.100705632+08:00","Scope": "local","Driver": "bridge","EnableIPv6": false,"IPAM": {"Driver": "default","Options": {},"Config": [{"Subnet": "192.168.0.0/16","Gateway": "192.168.0.1"}]},"Internal": false,"Attachable": false,"Ingress": false,"ConfigFrom": {"Network": ""},"ConfigOnly": false,"Containers": {},"Options": {},"Labels": {}}
]
启动镜像
[root@sail ~]# docker run -d -P --net=mynet --name=tomcat01 tomcat 
f3fad0c65fc3eb9a39b1189a25f5a7f664a0b9415df05cca5ee6edb6b7cc1915
[root@sail ~]# docker run -d -P --net=mynet --name=tomcat02 tomcat
68a78759663854c6d83a14fcc0cf45515e61c5e81d10799e96b22ef79c0d478f
连接测试
[root@sail ~]# docker exec -it tomcat01 ping tomcat02
64 bytes from tomcat02.mynet (192.168.0.3): icmp_seq=1 ttl=64 time=0.187 ms
64 bytes from tomcat02.mynet (192.168.0.3): icmp_seq=2 ttl=64 time=0.147 ms
^C
--- tomcat02 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 4ms
rtt min/avg/max/mdev = 0.147/0.167/0.187/0.020 ms

这种方式可以实现不同集群使用不同的网络,保证集群网络的安全。
如Redis集群在192.160.0.0/16网段下,MySQL集群在192.161.0.0/16网段下

网络连通

docker network connect
建立连接
[root@sail ~]# docker run -d -P --name=tomcat02-net tomcat
5a02cd4172daccc5073907ee6b063560687db5ffdd5041b18fd3ff1055a8984c
[root@sail ~]# docker network connect mynet tomcat02-net
[root@sail ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
f3eeb014197a   bridge    bridge    local
28d77e958643   host      host      local
801fbbe1b38c   mynet     bridge    local
c3ff850e96f0   none      null      local
[root@sail ~]# docker network inspect 801fbbe1b38c
[{"Name": "mynet","Id": "801fbbe1b38c81b12ce90aa9139561b5843dca64b4b17718b6e2622369f9be67","Created": "2021-12-30T17:39:43.100705632+08:00","Scope": "local","Driver": "bridge","EnableIPv6": false,"IPAM": {"Driver": "default","Options": {},"Config": [{"Subnet": "192.168.0.0/16","Gateway": "192.168.0.1"}]},"Internal": false,"Attachable": false,"Ingress": false,"ConfigFrom": {"Network": ""},"ConfigOnly": false,"Containers": {"5a02cd4172daccc5073907ee6b063560687db5ffdd5041b18fd3ff1055a8984c": {"Name": "tomcat02-net","EndpointID": "e6503138bcb91a7693576e324df75d1dff594f1c5aa3e08397802c38133eb0e9","MacAddress": "02:42:c0:a8:00:05","IPv4Address": "192.168.0.5/16","IPv6Address": ""}},"Options": {},"Labels": {}}
]

这样也可以实现容器连接到自定义网络。

Docker Compose

使用Docker的时候,定义Dockerfile文件,然后使用docker build、docker run等命令操作容器。
然而微服务架构的应用系统一般包含若干个微服务,每个微服务一般都会部署多个实例,如果每个微服务都要手动启停,这样效率很低,也不方便管理。
使用Docker Compose可以轻松、高效的管理容器,它是一个用于定义和运行多容器Docker的应用程序工具。

yaml官方示例

https://docs.docker.com/compose/compose-file/compose-file-v3/#compose-file-structure-and-examples

version: '' # 版本
services: # 服务服务1: webimagesbuildnetwoerk服务2: redis...
# 其他配置 网络/卷、全局规则
volumes:
networks:
config:

安装Docker Compose

安装

Docker Compose是Docker的一个开源项目,目前托管到了GitHub,需要前往GitHub下载。

sudo curl -L "https://github.com/docker/compose/releases/download/2.2.3/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

推荐使用道客提供的Docker极速下载进行安装。

curl -L https://get.daocloud.io/docker/compose/releases/download/v2.2.3/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
授权
chmod +x /usr/local/bin/docker-compose
查看版本
[root@sail bin]# docker-compose version
Docker Compose version v2.2.3
卸载
rm /usr/local/bin/docker-compose
启动
# 在项目目录中,运行docker-compose up来启动应用程序
docker-compose up
停止
[root@sail docker-compose]# docker-compose stop
[+] Running 2/2
⠿ Container docker-compose-redis-1  Stopped                                                                                                                    0.2s
⠿ Container docker-compose-web-1    Stopped
停止并删除容器和网络
[root@sail docker-compose]# docker-compose down
[+] Running 3/3
⠿ Container docker-compose-web-1    Removed                                                                                                                              10.2s
⠿ Container docker-compose-redis-1  Removed                                                                                                                               0.2s
⠿ Network docker-compose_default    Removed

Docker Swarm

swarm 可以简单理解为简单版k8s,采用管理节点+工作节点的方式

初始化一个swarm集群

[root@localhost ~]# docker swarm init --advertise-addr 192.168.106.131
Swarm initialized: current node (uuak4q55jejkbj654yhry6vvh) is now a manager.To add a worker to this swarm, run the following command:docker swarm join --token SWMTKN-1-0itq4kr7g74p1lk90syomkp7duqg040eli9stpuxscno1q8ben-a88didzcmnbfzi5pi020bjzia 192.168.106.131:2377To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.

生成增加manager节点的命令

 [root@localhost ~]# docker swarm join-token manager
To add a manager to this swarm, run the following command:docker swarm join --token SWMTKN-1-0itq4kr7g74p1lk90syomkp7duqg040eli9stpuxscno1q8ben-3l2s23nmszm5u8cvdi9kql9eo 192.168.106.131:2377[root@localhost ~]# 

生成增加work节点的命令

[root@localhost ~]# docker swarm join-token worker
To add a worker to this swarm, run the following command:docker swarm join --token SWMTKN-1-0itq4kr7g74p1lk90syomkp7duqg040eli9stpuxscno1q8ben-a88didzcmnbfzi5pi020bjzia 192.168.106.131:2377[root@localhost ~]# 

然后在需要加入集群的机器执行上述对应命令即可

查看当前swarm集群节点状态

[root@localhost ~]# docker node ls
ID                            HOSTNAME                STATUS    AVAILABILITY   MANAGER STATUS   ENGINE VERSION
uuak4q55jejkbj654yhry6vvh *   localhost.localdomain   Ready     Active         Leader           20.10.7
[root@localhost ~]# 

双主双从集群时:节点宕机时,如果只存在一个manager节点,则整个集群不可用
需大多数节点存活,整个集群才可用,节点数 >= 3;

节点离开集群

如果离开的是manager节点,会有警告,可使用 -f 强制离开

docker swarm leave

Swarm 部署应用,动态扩缩容
docker启动应用方式

1.docker run: 启动一个容器

2.docker-compose up : 启动一组由 docker-compose.yml 编排的容器

3.docker swarm :docker service run : 启动应用集群

服务:集群提供一个服务;可以是一个容器,也可以是一组相同的容器
集群中节点的分布:可能在不同机器上,也可能在一个机器上的不同容器

docker run -> 启动一个容器,不具有扩缩容
docker service create -> 启动一个服务,可以是一个容器,也可以是多个容器,具有扩缩容特性;即集群的概念

docker service

1.启动一个服务

[root@swarm01 ~]# docker service create --helpUsage:  docker service create [OPTIONS] IMAGE [COMMAND] [ARG...]Create a new serviceeg: docker service create --name my-nginx -p 18080:80 nginx在当前节点启动容器,不一定会分布到当前节点,可能是集群中的任何节点

2.查看服务列表

[root@swarm01 ~]# docker service ls
ID             NAME       MODE         REPLICAS   IMAGE          PORTS
pl07nc4j4jpp   my-nginx   replicated   1/1        nginx:latest   *:18080->80/tcp

3.查看服务运行状态

[root@swarm01 ~]# docker service ps my-nginx
ID             NAME         IMAGE          NODE      DESIRED STATE   CURRENT STATE           ERROR     PORTS
navzuz169o9g   my-nginx.1   nginx:latest   swarm03   Running         Running 2 minutes ago 

4.更新现有服务

docker service update [OPTIONS] SERVICE扩容为3个副本(原有那个不变,新增两个)
[root@swarm01 ~]# docker service update --replicas 3 my-nginx
my-nginx
overall progress: 3 out of 3 tasks 
1/3: running   [==================================================>] 
2/3: running   [==================================================>] 
3/3: running   [==================================================>] 
verify: Service converged

查看扩容后的状态

[root@swarm01 ~]# docker service ls
ID             NAME       MODE         REPLICAS   IMAGE          PORTS
pl07nc4j4jpp   my-nginx   replicated   3/3        nginx:latest   *:18080->80/tcp
[root@swarm01 ~]# docker service ps my-nginx
ID             NAME         IMAGE          NODE      DESIRED STATE   CURRENT STATE                ERROR     PORTS
navzuz169o9g   my-nginx.1   nginx:latest   swarm03   Running         Running about an hour ago              
ganoswo1p7tq   my-nginx.2   nginx:latest   swarm04   Running         Running about a minute ago             
mt0gjzwqa7o5   my-nginx.3   nginx:latest   swarm02   Running         Running about a minute ago 

可以看到,扩容之后,新增的两个节点分布在02 04 上面,此时通过集群内所有节点都可以访问 my-nginx 服务。因为我们访问的是集群,而集群内部的路由转发这些都是由docker-swarm 去完成的;
看到这里,对于普通的 docker run ,可能会存在 端口冲突的问题,但是这里,采用的是以服务方式启动,单个容器是不会暴露服务端口的,端口是由docker swarm 集群去暴露的,也就不存在端口冲突的问题
此时的容器是这样的

[root@swarm01 ~]# docker ps
CONTAINER ID   IMAGE          COMMAND                  CREATED              STATUS              PORTS     NAMES
943072cfc92d   nginx:latest   "/docker-entrypoint.…"   About a minute ago   Up About a minute   80/tcp    my-nginx.6.8qu4v48614zb9h00koi45jb9b
58ce7df6d2d7   nginx:latest   "/docker-entrypoint.…"   About a minute ago   Up About a minute   80/tcp    my-nginx.5.w73pj7s2ad9bu8n9qdft9ofj1

扩容和缩容是一个相对的概念,docker service update --replicas 增加/减少都可以

5.其他命令参考

docker service --help

6.专门扩缩容的命令(update 本意是更新服务,顺带可以扩缩容)

docker service scale --helpUsage:  docker service scale SERVICE=REPLICAS [SERVICE=REPLICAS...]Scale one or multiple replicated servicesOptions:-d, --detach   Exit immediately instead of waiting for the service to converge

eg:设置副本数为 5

[root@swarm01 ~]# docker service scale my-nginx=5
my-nginx scaled to 5
overall progress: 5 out of 5 tasks 
1/5: running   [==================================================>] 
2/5: running   [==================================================>] 
3/5: running   [==================================================>] 
4/5: running   [==================================================>] 
5/5: running   [==================================================>] 
verify: Service converged

集群内任意节点都可以访问服务,服务副本可以动态扩缩容,非常方便,达到高可用

7.移除一个服务

[root@swarm01 ~]# docker service rm my-nginx
my-nginx

移除后整个集群内服务下的所有容器及整个服务全部移除

[root@swarm01 ~]# docker service ls
ID        NAME      MODE      REPLICAS   IMAGE     PORTS
[root@swarm01 ~]# [root@swarm01 ~]# docker ps -a
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
[root@swarm01 ~]# 

Docker Swarm 基本使用
搭建集群;启停服务;动态扩缩容

相关文章:

Docker使用教程

Docker 名词解释 镜像&#xff08;image&#xff09;&#xff1a;Docker镜像就是一个模板&#xff0c;可以通过这个模板来创建容器服务。容器&#xff08;container&#xff09;&#xff1a;Docker利用容器技术&#xff0c;独立运行一个或者一组应用&#xff0c;通过镜像创建…...

poi-tl循环放图片+文字说明

这几天有个任务&#xff0c;服务端导出word要求从数据库取到多张图片&#xff0c;然后输出到word中&#xff0c;并且说明一共几张&#xff0c;当前是第几张。 网上翻了很久也没有找到示例&#xff0c;不过最终难题还是得到了攻克。 因为之前的代码是有一个导出的map&#xff0c…...

数据结构之树的存储结构

一、顺序存储结构 顺序存储结构通常用于表示完全二叉树。在这种存储方式中&#xff0c;树中的节点被存储在一个连续的数组中。对于完全二叉树&#xff0c;如果父节点的索引是i&#xff08;假设从0开始计数&#xff09;&#xff0c;那么它的左子节点的索引是2i1&#xff0c;右子…...

Zotero 常用插件介绍

1. Zotero 插件安装方法 下载以 .xpi 结尾的插件&#xff1b;打开 Zotero → 工具 → 插件 → 右上小齿轮图标 → Install Add-on From File ... → 选择下载好的 .xpi 插件安装 → 重启 Zotero 2. 常用插件介绍 2.1. Scholaread - 靠岸学术 Zotero 英文文献相关插件&#xf…...

WebSocket协议解析

文章目录 一、HTTP协议与HTTPS协议1.HTTP协议的用处2.HTTP协议的特点3.HTTP协议的工作流程4.HTTPS协议的用处5.HTTPS协议的特点6.HTTPS协议的工作流程 二、WebSocket协议出现的原因1. 传统的HTTP请求-响应模型2. 轮询&#xff08;Polling&#xff09;3. 长轮询&#xff08;Long…...

ES6 (一)——ES6 简介及环境搭建

目录 简介 环境搭建 可以在 Node.js 环境中运行 ES6 webpack 入口 (entry) loader 插件 (plugins) 利用 webpack 搭建应用 gulp 如何使用&#xff1f; 简介 ES6&#xff0c; 全称 ECMAScript 6.0 &#xff0c;是 JavaScript 的下一个版本标准&#xff0c;2015.06 发版…...

HarmonyOS开发案例:列表场景实例-TaskPool

介绍 本实例通过列表场景实例讲解&#xff0c;介绍在TaskPool线程中操作关系型数据库的方法&#xff0c;涵盖单条插入、批量插入、删除和查询操作。 效果图预览 使用说明 进入页面有insert(单条数据插入)、batch insert(批量数据插入)、query(查询操作)三个按钮&#xff0c;…...

谷歌浏览器如何隐藏书签

谷歌浏览器的书签栏是一个极为方便的功能&#xff0c;它能够帮助用户快速访问自己频繁使用的网页。然而&#xff0c;有些时候为了保护个人隐私或使浏览界面更为简洁&#xff0c;我们可能需要隐藏书签栏。接下来就为大家分享如何隐藏谷歌浏览器的书签栏&#xff0c;一起来看看吧…...

SQL - 视图

我们可以把查询或子查询存到视图里&#xff0c;视图的作用就像一张虚拟表&#xff0c;再次查询时&#xff0c;就不需要再写一次复杂的查询。创建视图 create view 视图名 as (查询); create or replace view clients_balance as (查询); create or replace view clients_balanc…...

centos7环境升级默认的gcc 4.8.5到gcc 8.2.0, 并且升级glibc到glibc 2.28

这里写目录标题 makegccglibc make #下载 wget http://ftp.gnu.org/gnu/make/make-4.2.tar.gz tar -xf make-4.2.tar.gz cd make-4.2 ./configure make -j4 make install mv /usr/bin/make /usr/bin/make_bak cp ./make /usr/bin/make -v GNU Make 4.2 Built for x86_64-pc-li…...

FastHTML:使用 Python 彻底改变 Web 开发

什么是 FastHTML&#xff1f;&#x1f310; FastHTML 是一个现代 Python Web 应用程序框架&#xff0c;其真正目的是让 Python 开发人员轻松进行 Web 开发。它大大减少了对 JavaScript 和 CSS 构建交互式和可扩展 Web 应用程序的依赖。FastHTML 通过使用 Python 对象来表示 HTM…...

快速排序的深入优化探讨

快排性能的关键点分析 决定快排性能的关键点是每次单趟排序后&#xff0c;key对数组的分割&#xff0c;如果每次选key基本⼆分居中&#xff0c;那么快排的递归树就是颗均匀的满⼆叉树&#xff0c;性能最佳。但是实践中虽然不可能每次都是⼆分居中&#xff0c;但是性能也还是可…...

c语言杂谈系列:模拟虚函数

从整体来看&#xff0c;笔者的做法与之前的模拟多态十分相似&#xff0c;毕竟c多态的实现与虚函数密切相关 废话少说&#xff0c;see my code&#xff1a; kernel.c#include "kernel.h" #include <stdio.h>void shape_draw(struct shape_t* obj) {/* Call dr…...

短视频推广App不再难!Xinstall来帮忙

在短视频风靡的今天&#xff0c;如何利用这一热门媒介有效推广App&#xff0c;成为了许多推广者关注的焦点。而Xinstall&#xff0c;作为国内专业的App全渠道统计服务商&#xff0c;正是你解决这一难题的得力助手。 首先&#xff0c;Xinstall在数据维度上的优势无可比拟。它能…...

打靶记录13——doubletrouble

靶机&#xff1a; https://www.vulnhub.com/entry/doubletrouble-1,743/ 难度&#xff1a; 中 目标&#xff1a; 取得两台靶机 root 权限 涉及攻击方法&#xff1a; 主机发现端口扫描Web信息收集开源CMS漏洞利用隐写术密码爆破GTFObins提权SQL盲注脏牛提权 学习记录&am…...

awk文本处理工具

awk 是一个强大的文本处理工具&#xff0c;在Shell编程中常用于处理和分析文本数据。它可以按列处理数据&#xff0c;进行模式匹配&#xff0c;生成报告&#xff0c;执行计算等。以下是一些 awk 的主要功能和使用场景&#xff1a; 期待您的关注 美好的观念较美人尤为可爱 目录 …...

计算机毕业设计选题推荐-学院网站系统-Java/Python项目实战

✨作者主页&#xff1a;IT毕设梦工厂✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Py…...

Spring模块详解Ⅰ

目录 SpringSpring框架的主要功能模块1. Core Container&#xff08;核心容器&#xff09;2. Data Access/Integration&#xff08;数据访问与集成&#xff09;3. Web4. AOP (Aspect-Oriented Programming&#xff0c;面向切面编程)5. Instrumentation&#xff08;工具集&#…...

C语言程序设计-练习篇

山海自有归期&#xff0c;风雨自有相逢。 一 下面代码的结果是什么&#xff1f; int main() { int i 0; for (i 0; i < 10; i) { if (i 5) //此处为赋值&#xff0c;i 5表达式结果为5 printf("%d ", i); //表达式为真&a…...

【Oracle篇】统计信息和动态采样的深度剖析(第一篇,总共六篇)

&#x1f4ab;《博主介绍》&#xff1a;✨又是一天没白过&#xff0c;我是奈斯&#xff0c;DBA一名✨ &#x1f4ab;《擅长领域》&#xff1a;✌️擅长Oracle、MySQL、SQLserver、阿里云AnalyticDB for MySQL(分布式数据仓库)、Linux&#xff0c;也在扩展大数据方向的知识面✌️…...

Spark 之 入门讲解详细版(1)

1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室&#xff08;Algorithms, Machines, and People Lab&#xff09;开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目&#xff0c;8个月后成为Apache顶级项目&#xff0c;速度之快足见过人之处&…...

mongodb源码分析session执行handleRequest命令find过程

mongo/transport/service_state_machine.cpp已经分析startSession创建ASIOSession过程&#xff0c;并且验证connection是否超过限制ASIOSession和connection是循环接受客户端命令&#xff0c;把数据流转换成Message&#xff0c;状态转变流程是&#xff1a;State::Created 》 St…...

成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战

在现代战争中&#xff0c;电磁频谱已成为继陆、海、空、天之后的 “第五维战场”&#xff0c;雷达作为电磁频谱领域的关键装备&#xff0c;其干扰与抗干扰能力的较量&#xff0c;直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器&#xff0c;凭借数字射…...

图表类系列各种样式PPT模版分享

图标图表系列PPT模版&#xff0c;柱状图PPT模版&#xff0c;线状图PPT模版&#xff0c;折线图PPT模版&#xff0c;饼状图PPT模版&#xff0c;雷达图PPT模版&#xff0c;树状图PPT模版 图表类系列各种样式PPT模版分享&#xff1a;图表系列PPT模板https://pan.quark.cn/s/20d40aa…...

佰力博科技与您探讨热释电测量的几种方法

热释电的测量主要涉及热释电系数的测定&#xff0c;这是表征热释电材料性能的重要参数。热释电系数的测量方法主要包括静态法、动态法和积分电荷法。其中&#xff0c;积分电荷法最为常用&#xff0c;其原理是通过测量在电容器上积累的热释电电荷&#xff0c;从而确定热释电系数…...

C++:多态机制详解

目录 一. 多态的概念 1.静态多态&#xff08;编译时多态&#xff09; 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1&#xff09;.协变 2&#xff09;.析构函数的重写 5.override 和 final关键字 1&#…...

三分算法与DeepSeek辅助证明是单峰函数

前置 单峰函数有唯一的最大值&#xff0c;最大值左侧的数值严格单调递增&#xff0c;最大值右侧的数值严格单调递减。 单谷函数有唯一的最小值&#xff0c;最小值左侧的数值严格单调递减&#xff0c;最小值右侧的数值严格单调递增。 三分的本质 三分和二分一样都是通过不断缩…...

Caliper 负载(Workload)详细解析

Caliper 负载(Workload)详细解析 负载(Workload)是 Caliper 性能测试的核心部分,它定义了测试期间要执行的具体合约调用行为和交易模式。下面我将全面深入地讲解负载的各个方面。 一、负载模块基本结构 一个典型的负载模块(如 workload.js)包含以下基本结构: use strict;/…...

LangFlow技术架构分析

&#x1f527; LangFlow 的可视化技术栈 前端节点编辑器 底层框架&#xff1a;基于 &#xff08;一个现代化的 React 节点绘图库&#xff09; 功能&#xff1a; 拖拽式构建 LangGraph 状态机 实时连线定义节点依赖关系 可视化调试循环和分支逻辑 与 LangGraph 的深…...

Python训练营-Day26-函数专题1:函数定义与参数

题目1&#xff1a;计算圆的面积 任务&#xff1a; 编写一个名为 calculate_circle_area 的函数&#xff0c;该函数接收圆的半径 radius 作为参数&#xff0c;并返回圆的面积。圆的面积 π * radius (可以使用 math.pi 作为 π 的值)要求&#xff1a;函数接收一个位置参数 radi…...