Docker入门:介绍Docker的常用命令、镜像的加载原理、Dockerfile打包、Docker网络、Docker Compose容器编排+监控

news2024/11/16 9:40:25

Docker入门

1)从面向对象角度来看,Docker利用容器(Container)独立运行一个或一组应用,应用程序或服务运行在容器里面,容器就类似于一个虚拟化的运行环境,容器是用镜像创建出来的运行实例。就像是Java中的类和实例对象一样,容器是镜像运行的实体。容器为镜像提供了一个标准的和隔离的运行环境,它可以被启动、开始、停止、删除。每个容器都是相互隔离的、保证安全的平台。

2)从镜像角度来看,可以把容器看做是一个简易版的Linux环境(包括root用户权限、进程空间、用户空间和网络空间等)和运行在其中的应用程序。

3)实操:将本地SpringBoot微服务制作成Docker Image镜像包然后运行

文章目录

  • Docker入门
    • 一、Docker常用命令:
    • 二、Docker镜像加载原理
    • 三、Docker容器卷
    • 四、Docker安装常用软件说明
    • 五、Dockerfile
    • 六、Dockerfile打包SpringBoot项目
    • 七、Docker网络
    • 八、Docker Compose容器编排
    • 九、容器监控

一、Docker常用命令:

  • 帮助启动类命令
# 启动,停止,重启Mac中直接针对软件进行操作即可
# 查看docker概要信息
docker info
# 查看docker总体帮助文档
docker --help
# 查看docker命令帮助文档
docker <具体命令> --help
  • 镜像命令
# 展示机器上所有的镜像
docker images
	# 参数
	-a # 列出本地所有镜像(包括历史镜像)
	-q # 只显示镜像ID
		# 查询结果
		REPOSITORY	# 镜像的仓库源
		TAG	# 镜像的版本标签号,同一个仓库源可以有多个TAG版本,代表这个仓库源的不同个版本,我们使用REPOSITORY:TAG可以定义不同的镜像,如果不指定默认使用最新的
		IMAGE ID	# 镜像ID
		CREATED	# 镜像创建时间
		SIZE	# 镜像大小
# 查询某个镜像
docker search [镜像名称]
	# 参数,限制查询结果数量
	<search> --limit [数字] 
		# 查询结果
		NAME	# 镜像名称
		DESCRIPTION	# 镜像说明
		STARS	# 镜像点赞数量
		OFFICIAL	# 该镜像是否是官方的
		AUTOMATED	# 该镜像是否是自动构建的
# 拉取某个镜像到本地
docker pull [镜像名称]
	# 参数,指定拉取镜像版本
	:[TAG]
# 查看docker磁盘空间情况
docker system df
# 删除某个镜像
docker rmi [镜像名]/[镜像ID]
	# 参数,强制删除
	<rmi> -f
# docker虚悬镜像是什么?在构建或删除镜像的时候出现问题,导致REPOSITORY与TAG都为none的镜像,直接删除即可,查看所有的虚悬镜像
docker image ls -f dangline=true
# 删除所有虚悬镜像
docker image prune
  • 容器命令
# 有镜像才能创建容器,这是根本的前提,首先拉取一个ubuntu镜像
docker pull ubuntu
# 启动镜像
docker run [options] IMAGE [COMMAND][ARG...]
	# 参数,options说明
	--name	# 为容器启动后指定一个名称
	-d	# 后台运行容器并返回容器ID,也即守护式容器(守护进程)
	-i	 # 以交互式模式运行容器,通常与-t同时使用,也即启动交互式容器(前台有伪终端,等待交互)
	-t	 # 为容器重新分配一个伪输入终端,通常与-i同时使用
	-P	# 随机端口映射
	-p	# 指定端口映射,eg:-p 8080:80
# 交互式启动ubuntu镜像
docker run -it ubuntu /bin/bash
	# 参数
	<-it> --name=mycontainer1	# 指定容器名
# 显示所有正在运行的容器实例
docker ps [options]
	# 参数options
	-a	# 列出当前所有容器,包括启动和未启动的
	-I	 # 显示最近创建的容器
	-n	# 显示最近n个创建的容器
	-q	# 静默模式,只显示容器编号
		# 查询结果
		CONTAINER ID	# 容器ID
		IMAGE	# 镜像名
		COMMAND	# 命令
		CREATED	# 创建时间
		STATUS	# 状态
		PORTS	# 对外暴露的端口(ubuntu不需要暴露端口所以此处没有)
		NAMES	# 容器名,如果前面run的时候没有指定名称则会随机指定一个

image-20221231181558624

# 退出容器,以上述ubuntu容器为例,run进入的命令行
exit	# 容器停止
<ctrl> + <p> + <q>	# 容器不停止
# 启动已停止的容器
docker start [CONTAINER ID]/[NAMES]
# 重启容器
docker restart [CONTAINER ID]/[NAMES]
# 停止容器
docker stop [CONTAINER ID]/[NAMES]
# 强制停止容器
docker kill [CONTAINER ID]/[NAMES]
# 删除已停止的容器(一般是先停止容器,然后再删除)
docker rm [CONTAINER ID]/[NAMES]
	# 参数,强制删除
	<rm> -f

Docker守护式容器解决方案:

# 启动守护式容器(daemon后台服务器),通常情况下我们希望docker的服务是在后台运行的,就像在linux环境中许多软件设置后台启动那样,这里以redis为例
docker pull redis
# 前台交互式启动(复习),ctrl+c可以退出
docker run -it redis:latest
# 后台守护式启动
docker run -d redis:latest
# 查看容器日志
docker logs [CONTAINER ID]
# 查看容器内运行的进程
docker top [CONTAINER ID]
# 查看容器内部细节(配置信息)
docker inspect [CONTAINER ID]
# 进入正在运行的容器(守护式容器)并用命令行进行交互
docker exec -it [CONTAINER ID] bashShell	# exec是在容器中打开新的终端,并且新启动的进程可以用exit退出,不会导致源容器的停止,常用
docker attach [CONTAINER ID]	# 直接进入容器启动命令的终端,不会启动新的进程,用exit退出则会导致容器的停止

image-20221231210225137

# 从容器中拷贝文件到主机上
docker cp [CONTAINER ID]:[容器内的文件路径]  [目的端的拷贝路径]
# 导入和导出容器
	# export 导出容器的内容流作为一个tar归档文件[对应import命令]
	docker export [CONTAINER ID] > [文件名].tar
	# import 从tar包中的内容创建一个新的文件系统再导入为镜像[对应export]
	cat [文件名].tar | docker import - 镜像用户/镜像名:镜像版本号

image-20221231213239487

二、Docker镜像加载原理

​ docker镜像实际上是由一层一层的文件系统的文件系统组成,这种层级的文件系统称之为UnionFS联合文件系统。镜像分层的最大一个好处就是可以共享资源,方便复制迁移,就是为了复用。假如有多个镜像都从相同的base镜像构建而来,那么DockerHost只需要在磁盘上保存一份base镜像;同时内存中也只需要加载一份base镜像,就可以为所有容器服务了。而且镜像每一层都可以被共享。

​ 举个例子,假设现在拉取一个linux镜像,然后运行,Linux在刚启动时会加载bootfs文件系统,然后再加载rootfs。Linux镜像其实就是一层层文件系统组成,如果了解过该镜像,会镜像中是没有vim命令的,并没有加入非必须的文件系统,但你在本地添加了一些文件系统扩展了原有镜像,这很方便,就相当于原来的Linux镜像是base镜像,只需要在磁盘与内存中保存/加载一份即可。

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

​ 需要注意的是,**Docker镜像层都是只读的,容器层是可写的。**当容器启动时,一个新的可写层会被加载到镜像顶部,这一层通常被称为容器层,容器层之下的都叫镜像层(保证程序的复用)。

# 提交当前容器副本使之成为一个新的镜像(类似于Java中的继承,层层增强)
docker commit -m="[提交的描述信息]" -a="[作者]" [CONTAINER ID] [要创建的目标镜像名]:[标签名]

# ubuntu容器中安装vim举例,首先进入docker容器
docker run -it ubuntu:latest
apt-get update	# 更新包管理工具
apt-get install vim	# 安装vim
# 将当前添加了vim功能的ubuntu提交副本成为一个新的镜像
docker commit -m="vim cmd add ok" -a="shadowy" 39932b4d0bab heavyhead/myubuntu:1.1

image-20230101164659500

三、Docker容器卷

# 容器卷与主机互联互通,其实可以理解为将宿主机的某个路径共享给了Docker,VM里面的共享文件夹操作,如果宿主机路径下之前有文件,那Docker也可以查看
docker run -it --privileged=true -v [宿主机绝对路径目录]:/[容器内目录] [镜像名]
	# 参数,容器卷内文件只读,只有读权限
	<[容器内目录]>:ro
docker run -it --privileged=true -v /Users/zhangyong/Downloads:/tmp/docker_data --name=u1 ubuntu
	# 新建文件,会发现Docker目录与宿主机目录同时会有这个文件(文件互通)
	touch dockerin.txt
# 查看容器卷是否挂载成功
docker inspect [CONTAINER ID]
	# 查询结果
	"Mounts": [{
    	"Type": "bind",
    	"Source": "/Users/zhangyong/Downloads",
    	"Destination": "/tmp/docker_data",
    	"Mode": "",
    	"RW": true,
    	"Propagation": "rprivate"
	}]
# 容器卷2继承容器卷1的卷规则,--volumes-from就类似于Java中的继承
docker run -it --privileged=true -v --volumes-from [CONTAINER ID] [镜像名]

四、Docker安装常用软件说明

Docker中经常会安装一些常用的软件,这里记录一下常用工具的安装配置,持续补充

Tomcat、MySQL、Redis

  • Tomcat

​ 首先在https://hub.docker.com/dockerHub上寻找镜像,官网上有对应的镜像时,直接pull即可docker pull tomcat

image-20230107142226959

# Docker中拉取Tomcat镜像
docker pull tomcat
# Docker中启动Tomcat镜像
docker run -d -p 8080:8080 --name t1 tomcat
	# 复习docker各个指令的作用
	-d	# 后台运行
	-i	# 交互式运行
	-t	# 返回一个伪终端
	-p	# 指定端口,格式:[主机端口]:[docker容器端口]
# 查看Tomcat容器
docker ps
# 此时访问tomcat主页会发现404,因为在高版本的tomcat中,对目录结构做了更改,需要手动处理,首先进入容器
docker exec -it [CONTAINER ID] /bin/bash	# exec是在容器中打开新的终端,并且新启动的进程可以用exit退出,不会导致源容器的停止,常用
cd /usr/local/tomcat
rm -r webapps
mv webapps.dist webapps
# 访问 http://localhost:8080/

image-20221231210225137

  • MySQL
# 简单版Mysql容器启动
docker search mysql
# 拉取MySQL镜像,以5.7版本为例
docker pull mysql:5.7
# 启动MySQL镜像,注意启动前先判断3306端口是否已经被占用了
docker run -p [本机端口]:3306 -e MYSQL_ROOT_PASSWORD=123456 -d mysql
	# 举例,我本地有一个mysql了,所以用我本地的3307端口去映射了docker的3306端口,在datagrip中使用3307端口就可以链接到这个docker中的mysql了
	docker run -p 3307:3306 -e MYSQL_ROOT_PASSWORD=123456 -d mysql
# 进入Mysql命令行
docker exec -it [CONTAINER ID] /bin/bash
mysql -uroot -p
[MYSQL_ROOT_PASSWORD]
# 实战版Mysql容器启动,生产环境下需要使用容器卷,防止数据核心资产丢失
docker run -p [主机端口]:3306 --privileged=true 
-v /Users/zhangyong/Shadowy/log:/var/log/mysql 
-v /Users/zhangyong/Shadowy/data:/var/lib/mysql 
-v /Users/zhangyong/Shadowy/conf:/etc/mysql/conf.d
-e MYSQL_ROOT_PASSWORD=123456 -d --name mysql mysql
	# 复习docker容器卷各个指令的作用
	privileged	# 开启容器卷
	-v	# 可以映射多个容器卷目录
# 修改my.cnf配置文件
cd /Users/zhangyong/Shadowy/conf
vim my.cnf
	# 将下面内容粘贴进去,保证客户端和服务端的编码都是utf8
	[client]
	default_character_set=utf8
	[mysqld]
	collation_server=utf8_general_ci
	character_set_server=utf8
# 重新启动mysql容器
docker restart mysql

五、Dockerfile

Dockerfile:定义一个Dockerfile,它定义了进程中需要的一切东西。Dockerfile涉及的内容包括执行代码或者是文件、环境变量、依赖包、运行时环境、动态链接库、操作系统的发行版、服务进程和内核进程(当应用程序需要和系统服务和内核进程交互时,这时就需要考虑如何设计namespace的权限控制)等等;

Docker IMAGE:在Dockerfile定义一个文件之后,docker build时会产生一个Docker镜像,当运行docker镜像时会真正开始提供服务;

Docker CONTAINER:容器是直接提供服务的。

# Dockerfile关键字
FROM	# 基础镜像,当前镜像是基于哪个镜像的,指定一个已经存在的镜像作为模板,第一条必须是from命令
MAINTAINER	# 镜像维护者的姓名+邮箱
RUN	# 容器构建时需要运行的命令,RUN会在docker build时运行
	# 两种格式
	shell	# eg: yum install vim
	exec  # eg:	["./test.php", "dev", "offline"]
EXPOSE	# 当前容器对外暴露的端口
WORKDIR	# 指定在容器创建之后,终端默认登录进来的工作目录,落脚点
USER	# 指定该镜像以什么用户去执行,如果不指定默认root
ENV	# 用来在构建镜像中设置环境
ADD	# 将宿主机目录下的文件拷贝至镜像且会自动处理URL和解压tar压缩包
COPY	# 类似ADD,拷贝文件和目录到镜像中,将从构建上下文目录中<原路径>的文件/目录复制到新的一层的镜像内的<目标路径>位置
	COPY src dest
	COPY ["src", "dest"]
	<src源路径>: 源文件或者源目录
	<dest目标路径>: 容器内的指定路径,该路径不用事先建好,不存在会自动创建
VOLUME	# 容器数据卷,用于数据持久化和保存
CMD	# 指定容器启动之后要干的事情,类似与run,需要注意的是只有最后一个cmd生效且cmd命令会被docker run后面的命令覆盖
ENTRYPOINT	# 指定容器启动之后要干的事情,类似与run,但不会被docker run后面的命令覆盖
	# ENTRYPOINT可以和CMD一起使用,一般是变参才会使用CMD,此时这里的CMD等于就是在给ENTRYPOINT传参。当指定了ENTRYPOINT之后,CMD的含义就发生了变化,不再是直接运行其命令而是将CMD的内容作为参数传递给ENTRYPOINT指令
	<ENTRYPOINT> <CMD>
	ENTRYPOINT ["nginx", "-c"] CMD ["/etc/nginx/nging.conf"] -> nginx -c /etc/nginx/nginx.conf

image-20221231210225137

六、Dockerfile打包SpringBoot项目

  • shell命令打包

​ 首先通过maven clean package打一个jar包出来:

image-20221231210225137

# 进入一个目录,将jar包上传至该目录中,然后新建Dockerfile文件
vim Dockerfile
# Dockerfile内容
	# 基础镜像使用Java
    FROM openjdk:17
    # 作者
    MAINTAINER shadowy
    # VOLUME指定临时文件目录为/tmp,在主机目录下创建了一个临时文件并连接到容器的/tmp
    VOLUME /tmp
    # 将jar包添加到容器并更名为shadowy_docker_v1.0.jar
    ADD MySpringBoot-0.0.1-SNAPSHOT.jar /shadowy_docker_v1_0.jar
    # 运行jar包
    RUN bash -c 'touch /shadowy_docker_v1_0.jar' 
    ENTRYPOINT ["java", "-jar", "/shadowy_docker_v1_0.jar"]
    # 暴露2023端口出来作为微服务的端口
    EXPOSE 2023
# 通过Dockerfile文件生成一个镜像包
docker build -t shadowy_docker:1.1 .
# 运行该镜像包
docker run -d -p 2023:2023 [IMAGE ID]
	# 如果是MAC,带上如下参数
	<-d> --platform linux/amd64

七、Docker网络

​ 安装Docker后,默认会自动创建三个网络模式,输入docker network ls命令可以查看:

image-20230114142217696

  1. bridge:为每个容器分配、设置IP等,并将容器连接到一个docker0虚拟网桥中,默认为该模式(常用);
  2. host:容器不会虚拟出自己的网卡、配置自己的ip等,而是直接使用宿主机的IP和端口;
  3. none:容器有独立的Network namespace,但并没有对其进行任何的网络设置,如分配veth pair和网桥连接、IP等;
  4. container:新创建的容器不会创建自己的网卡和配置自己的IP,而是和一个指定的容器共享IP、端口范围等。
# 新建/删除一个自定义网络模式
docker network create [自定义网络模式名]
docker network rm [自定义网络模式名]	
# 指定镜像采用哪种网络模式启动 --network
docker run -d -p 8080:8080 --network [网络模式] --name mytomcat tomcat
	# 参数 [网络模式]
	bridge # 统一使用docker0来作为通信路由器,如下图所示
	host # 直接使用主机的ip和端口,此处的-p命令就无意义了,端口号会以主机端口号为主如果重复则递增
	none # 需要自己为Docker容器添加网卡与IP配置
	container:<CONTAINER ID> # 新创建的容器和已经存在的一个容器共享一个网络ip配置而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP、端口范围等。同样两个容器除了网络方面,其他如文件系统、进程列表还是隔离的
# 查看容器的(网络)配置
	<自定义网络模式名> # 使用自定义网络模式,解决了在集群环境下用容器名互相通信的问题,避免了ip浮动的问题
docker inspect [CONTAINER ID]
	# 参数,因为网络配置在容器详情信息的最后面,所以我们可以在该命令后面添加指定行参数
	| tail -n 20

image-20221231210225138

八、Docker Compose容器编排

​ Compose是Docker公式推出的一个工具软件,可以管理多个Docker容器组成一个应用。你需要定义一个YAML格式的配置文件docker-compose.yml,写好多个容器之间的调用关系。然后只要一个命令就能同时启动/关闭这些容器。

为什么会有Compose?

​ docker官方建议我们每个容器中都只运行一个服务,因为docker容器本身所占用的资源极少,最好是将每个服务单独的分割开来,但这样我们又面临了一个新的问题:

​ 如果我需要同事部署好多个服务,难道需要再每个微服务中都单独写Dockerfile,然后再构建镜像、构建容器?例如要实现一个web微服务项目,除了web本身的服务容器本身之外,往往还需要再加上后端的数据库mysql服务容器、redis服务器、注册中心eureka,甚至还包括负载均衡中间件等等。。。

​ Compose允许用户通过一个单独的docker-compose.yml模板文件来定义一组相关联的应用容器为一个总的项目,就类似与Spring中的SpringContext.xml文件去管理各个bean的生命周期一样。

​ 可以很容易地用一个配置文件就定义一个多容器的应用,然后使用一条指令安装这个应用的所有依赖,然后完成构建。Docker-Compose解决了容器与容器之间如何管理编排的问题。

下载地址:https://docs.docker.com/compose/install/

# Compose常用命令
docker-compose [arg]
	# 查看帮助
	-h
	# 启动所有的docker-compose服务
	up
	# 启动所有的docker-compose服务并后台运行
	up -d
	# 停止并删除容器、网络、卷、镜像
	down
	# 进入容器实例内部
	exec [yml文件中写的服务id]
	# 展示当前docker-compose编排过的运行的所有容器
	ps
	# 展示当前docker-compose编排过的容器进程
	top
	# 查看容器输出日志
	logs [yml文件中写的服务id]
	# 检查配置
	config
	# 检查配置,有问题才输出
	config -q
	# 重启/启动/停止 服务
	restart
	start
	stop

案例:myboot镜像启动需要依赖mysql与redis服务,编写docker-compose.yml文件:

# 设置版本号
version: "3"

# 编排服务
services:
 microService:
  image: myboot:1.9
  container_name: ms01
  ports:
   - "2023:2023"
  volumes:
   - /app/microService:/data
  networks:
   - mine_net
  depends_on:
   - redis
   - mysql

 redis:
  image: redis:6.0.8
  ports:
   - "6379:6379"
  volumes:
   - /app/redis/redis.conf:/etc/redis/redis.conf
   - /app/redis/data:/data
  networks:
   - mine_net
  command: redis-server /etc/redis/redis.conf
	
 mysql:
  image: mysql:8.0.31
  environment:
   MYSQL_ROOT_PASSWORD: '123456'
   MYSQL_ALLOW_EMPTY_PASSWORD: 'no'
   MYSQL_DATABASE: 'reggie'
   MYSQL_USER: 'shadowy'
   MYSQL_PASSWORD: 'f88b33a6e159f0ac'
  ports:
   - "3306:3306"
  volumes:
   - /app/mysql/db:/var/lib/mysql
   - /app/mysql/conf/my.cnf:/etc/my.cnf
   - /app/mysql/init:/docker-entrypoint-initdb.d
  networks:
   - mine_net
  command: --default-authentication-plugin=mysql_native_password	# 解决外部无法访问的问题

# 新建一个自定义网络
networks:
 mine_net:

九、容器监控

​ 对于docker中的容器,想要获取实时的状态信息,可以通过docker stats命令来完成:image-20230115144813801

但这个原生的命令同时也存在着一些局限性,比如只能查看宿主机的上的docker容器、状态信息不能持久化保存、无法做到实时监控等等,因此我们需要借助容器监控三剑客CIG:CAdvisor监控收集+InfluxDB存储数据+Granfana可视化展示

  • CAdvisor:是一个容器资源监控工具,包括容器的内存、CPU、网络IO、磁盘IO等监控,同时提供了一个WEB页面用于查看容器的实时运行状态。它默认只存储两分钟的数据,而且只针对单物理机,不过它同时也提供了很多数据集成接口,支持InfluxDB、Redis、Kafka、Elasticsearch等集成,可以加上对应的配置将监控数据发往这些数据库存储起来;
  • InfluxDB:是一个用GO语言编写的开源分布式时序、事件和指标的数据库,无需外部的依赖;
  • Granfana:是一个开源的数据监控分析可视化平台,支持多种数据源配置和丰富的插件及模板功能,支持图标权限控制和报警。

使用Docker Compose使用三剑客:

# 首先新建一个cig目录,进入其中
pwd -> /Users/zhangyong/Shadowy/mydocker/cig
# 新建docker-compose.yml文件,将以下内容写入其中
version: '3.1'

volumes:
  grafana_data: {}

services:
 influxdb:
  image: tutum/influxdb:0.9
  restart: always
  environment:
    - PRE_CREATE_DB=cadvisor
  ports:
    - "8083:8083"
    - "8086:8086"
  volumes:
    - ./data/influxdb:/data

 cadvisor:
  image: google/cadvisor # 目前该镜像有问题,运行不了,github上讨论用 gcr.io/cadvisor/cadvisor 可以解决,但是这个镜像拉取不下来 https://github.com/google/cadvisor/issues/1943
  links:
    - influxdb:influxsrv
  command: -storage_driver=influxdb -storage_driver_db=cadvisor -storage_driver_host=influxsrv:8086
  restart: always
  ports:
    - "8080:8080"
  volumes:
    - /:/rootfs:ro
    - /var/run:/var/run:rw
    - /sys:/sys:ro
    - /var/lib/docker/:/var/lib/docker:ro

 grafana:
  user: "104"
  image: grafana/grafana
  user: "104"
  restart: always
  links:
    - influxdb:influxsrv
  ports:
    - "3000:3000"
  volumes:
    - grafana_data:/var/lib/grafana
  environment:
    - HTTP_USER=admin
    - HTTP_PASS=admin
    - INFLUXDB_HOST=influxsrv
    - INFLUXDB_PORT=8086
    - INFLUXDB_NAME=cadvisor
    - INFLUXDB_USER=root
    - INFLUXDB_PASS=root
# 检查yml文件格式、语法是否有问题
docker-compose config -q
# 启动docker-compose文件
docker-compose up
# 查看一下容器启动状态
docker ps
# 各个监控指标访问地址
浏览CAdvsior收集服务:http://ip:8080
浏览influxdb存储服务:http://ip:8083
浏览grafana展现服务:http://ip:3000

image-20230115154654461

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

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

相关文章

区块链笔记4--BTC实现

1 UTXO &#xff1a;区块链是一个去中心化的账本&#xff0c;比特币采用了 基于交易的账本模式。然而&#xff0c;系统中并无显示记录账户包含BTC数&#xff0c;实际上其需要通过交易记录进行推算。在比特币系统中&#xff0c;全节点需要维护一个名为 UTXO(UnspentTransaction …

Java抽象类:案例、特点、模板方法模式

一.抽象类的案例 案例&#xff1a;加油站支付卡 系统需求&#xff1a; 某加油站推出了2种支付卡&#xff1a; 1、预存1万元的金卡&#xff0c;后续加油享受8折优惠&#xff1b; 2、预存5千元的银卡&#xff0c;后续加油享受8.5折优惠。 请分别实现2种卡片进入收银系统后的…

记录每日LeetCode 2293.极大极小游戏 Java实现

题目描述&#xff1a; 给你一个下标从 0 开始的整数数组 nums &#xff0c;其长度是 2 的幂。 对 nums 执行下述算法&#xff1a; 设 n 等于 nums 的长度&#xff0c;如果 n 1 &#xff0c;终止 算法过程。否则&#xff0c;创建 一个新的整数数组 newNums &#xff0c;新数组…

分享66个HTMLCSS源码,总有一款适合您

HTML&CSS源码 分享66个HTML&CSS源码&#xff0c;总有一款适合您 下面是文件的名字&#xff0c;我放了一些图片&#xff0c;文章里不是所有的图主要是放不下...&#xff0c;大家下载后可以看到。 源码下载链接&#xff1a;https://pan.baidu.com/s/1AeVqON7byvt-ngB_U…

位段与枚举

目录 1、位段 1、位段的声明 2、位段的内存分配特点 3、位段的跨平台问题 4、位段的应用 2、枚举 1、枚举类型的定义 2、枚举的优点 3、联合体&#xff08;共用体&#xff09; 1、联合类型的定义 2、联合体的特点即大小计算 1、位段 1、位段的声明 位段的位指的是…

Pr初识01

Pr初识1.关于Pr&#xff1a;2.项目序列3.PR工作界面4.导入素材5.制式与素材管理6.剪辑与工具7.剪辑与工具&#xff08;下&#xff09;8.工具面板与时间轴面板进阶9.关键帧动画10.视频特效11.视频特效&#xff08;下&#xff09;12.音频及结合AU去除噪音13.字幕运用1.关于Pr&…

微信小程序自定义组件、组件的生命周期和组件通信(插槽)

文章目录导航路线自定义组件组建的创建和使用1.创建组件2.引用组件3. 局部引用组件4. 全局引用组件5. 全局引用 VS 局部引用6. 组件和页面的区别样式1.组件样式隔离2. 组件样式隔离的注意点3. 修改组件的样式隔离选项4. styleIsolation 的可选值数据、方法和属性1. data 数据2.…

Arduino UNO驱动 AT24C256 EEPROM存储器模块

Arduino UNO驱动 AT24C256 EEPROM存储器模块 AT24C256模块简介模块引脚定义Arduino UNO与模块接线测试代码实验结果AT24C256模块简介 AT24C256是一个串行EEPROM存储器&#xff0c;提供了256k bit256*1024 bit262144 bit32768 Byte32K Byte大小的存储空间&#xff0c;在芯片内部…

Jmeter做数据构造步骤详解

Jmeter做数据构造步骤详解引入什么是数据构造数据构造的方式数据构造的意义一、JDBC请求执行SQL语句构造数据01 环境准备&#xff1a;添加Jmeter插件02 使用步骤二、HTTP请求调用接口构造数据01 使用步骤完善脚本01 运用函数02 使用逻辑控制器和定时器03 添加响应断言自动判断构…

拒绝平庸,张扬出彩——维乐VELO Angel Revo

在赛场上就要做那个万众瞩目的明星&#xff0c;闪耀自己&#xff0c;让自己的实力让所有人看到&#xff01;作为骑行运动员&#xff0c;骑行配件当然是最能够彰显自我个性的地方&#xff0c;维乐美学系列明星产品Angel Revo正如其名&#xff0c;全面革新&#xff0c;也给了所有…

【自学Python】Python拼接字符串

Python拼接字符串 Python拼接字符串教程 Python 拼接 字符串 有两种方法&#xff1a;一种是直接把两个字符串写在一起&#xff0c;即可实现拼接&#xff0c;另一种是使用 来实现字符串的拼接。 Python拼接字符串详解 写在一起 语法 str1str2参数 参数描述str1要拼接的字…

BERT 词向量理解及训练更新

1、BERT 词向量理解 在预训练阶段中&#xff0c;词向量是在不断更新的&#xff0c;而在fine-tuning阶段中&#xff0c;词向量是固定不变的。在fine-tuning阶段中&#xff0c;我们使用预训练好的模型参数来对新的数据进行训练。 BERT模型在预训练阶段中&#xff0c;会学习词表中…

win10开启自带的手机投屏功能方式

本篇文章主要讲解win10开启自带的手机投屏方式。 日期&#xff1a;2023年1月15日 作者&#xff1a;任聪聪 开启后效果 点击连接 打开连接或通过手机其他网络进行连接。 连接步骤&#xff1a; 步骤一、打开手机端的wifi网络设置&#xff0c;点击高级设置或其他网络设置&…

论文的正确打开方式—如何细读一篇论文分享

前段时间听了一个关于读论文的公开课&#xff0c;课上的老师讲的非常好&#xff0c;听完之后确实发现从以前看论文的没头没脑到现在的有了一些思绪的变化&#xff0c;所以特此整理了一下分享给大家&#xff0c;希望对大家有用。 在我们初次接触论文的时候&#xff0c;经常性的遇…

《后端技术面试 38 讲》学习笔记 Day 12

《后端技术面试 38 讲》学习笔记 Day 12 31 | 大数据架构&#xff1a;大数据技术架构的思想和原理是什么&#xff1f; 原文摘抄 大数据技术其实是分布式技术在数据处理领域的创新性应用&#xff0c;本质和我们此前讲到的分布式技术思路一脉相承&#xff1a;用更多的计算机组成…

smart-doc的使用

smart-doc的使用 目录 1. 什么是smart-doc 2. smart-doc的功能特性 3. smart-doc自定义注释tag 4. 通过引入依赖生成文档 5. 通过集成smart-doc的maven插件生成文档 6. 生成Postman json文件与导入Postman测试 1. 什么是smart-doc smart-doc是一款同时支持JAVA REST API和…

MySQL监控(二): Prometheus入门

1.官网 OpenTelemetry - CNCF Prometheus官方文档 安装包下载页 Prometheus安装官方文档指引 2.安装mysqld_exporter (1)下载 mysqld_exporter下载 (2)配置文件 my.cnf [client] hostxx.xx.xx.xx port31090 userroot passwordroot(3)启动 启动命令&#xff1a; nohup …

关于常见排序的一些细节的理解

最近复习了一下十种基本的排序算法&#xff0c;但是发现有很多的细节理解不到位&#xff0c;不是忘了而是根本没理解。就比如为啥有的排序是不稳定排序&#xff0c;而有的排序的时间复杂度高等等问题。一、不稳定排序的稳定性分析和复杂度常见排序算法中有4种排序是不稳定的。快…

详解最近公共祖先(LCA)

看本博客前建议先看一下ST算法解决BMQ问题详解一&#xff0c;LCA概念最近公共祖先(Lowest Common Ancestors, LCA)指有根树中距离两个节点最近的公共祖先。祖先指从当前节点到树根路径上的所有节点。u和v的公共祖先指一个节点既是u的祖先&#xff0c;又是v的祖先。u和v的最近公…

php网上书城|基于PHP实现网上书店商城藉项目

作者主页&#xff1a;编程指南针 作者简介&#xff1a;Java领域优质创作者、CSDN博客专家 、掘金特邀作者、多年架构师设计经验、腾讯课堂常驻讲师 主要内容&#xff1a;Java项目、毕业设计、简历模板、学习资料、面试题库、技术互助 收藏点赞不迷路 关注作者有好处 文末获取源…