镜像制作和管理

文章目录

  • 一、Docker镜像说明
    • Docker镜像中没有内核
    • 为什么没有内核
    • 容器中的程序后台运行会导致此容器启动后立即退出
    • 镜像的生命周期和制作方式
  • 二、手动构建镜像
    • 基于容器手动制作镜像步骤
    • 实际操作
      • 基于 busybox 制作httpd镜像
      • 制作tomcat镜像
      • 基于ubuntu的基础镜像手动安装nginx镜像
      • 基于Centos的基础镜像利用yum安装手动制作nginx的镜像
  • 三、利用DockerFile文件执行docker build自动构建镜像
    • Dockerfile使用介绍
    • FROM指定基础镜像
    • LABAL指定镜像元数据
    • RUN: 执行shell命令
    • COPY:复制文本
    • ADD:制作和解压缩文件
    • CMD:容器启动命令
    • ENTRYPOINT
    • ARG: 构建参数
    • ENV
    • VOLUME:匿名卷
    • EXPOSE: 暴露端口
    • WORKDIR: 指定工作目录
    • Dockerfile构建过程和指令总结


一、Docker镜像说明

Docker镜像中没有内核

从镜像大小上面来说,一个比较小的镜像只有1MB多点或几MB,而内核文件需要几十MB, 因此镜像里面是没有内核的,镜像在被启动为容器后将直接使用宿主机的内核,而镜像本身则只提供相应的rootfs,即系统正常运行所必须的用户空间的文件系统,比如: /dev/,/proc,/bin,/etc等目录,容器当中/boot目录是空的,而/boot当中保存的就是与内核相关的文件和目录。

为什么没有内核

由于容器启动和运行过程中是直接使用了宿主机的内核,不会直接调用物理硬件,所以也不会涉及到硬件驱动,因此也无需容器内拥有自已的内核和驱动。而如果使用虚拟机技术,对应每个虚拟机都有自已独立的内核。

容器中的程序后台运行会导致此容器启动后立即退出

Docker容器如果希望启动后能持续运行,就必须有一个能前台持续运行的进程,如果在容器中启动传统的服务,如:httpd,php-fpm等均为后台进程模式运行,就导致 docker 在前台没有运行的应用,这样的容器启动后会立即退出。所以一般会将服务程序以前台方式运行,对于有一些可能不知道怎么实现前台运行的程序,只需要在你启动的该程序之后添加类似于 tail ,top 这种可以前台运行的程序即可。比较常用的方法,如 tail -f /etc/hosts 。

镜像的生命周期和制作方式

在这里插入图片描述
制作方式:
Docker 镜像制作类似于虚拟机的镜像(模版)制作,即按照公司的实际业务需求将需要安装的软件、相关配置等基础环境配置完成,然后将其做成镜像,最后再批量从镜像批量生成容器实例,这样可以极大的简化相同环境的部署工作。
Docker的镜像制作分为手动制作(基于容器)和自动制作(基于DockerFile),企业通常都是基于Dockerfile制作镜像。

总结:

  1. 下载官方或者别人制作好的镜像进行修改。
  2. 利用dockerfile生成自己的镜像。
docker commit 
通过修改现有容器,将之手动构建为镜像
docker build  
通过Dockerfile文件,批量构建为镜像

二、手动构建镜像

基于容器手动制作镜像步骤

  1. 下载一个系统的官方基础镜像,如: CentOS 或 Ubuntu 。
  2. 基于基础镜像启动一个容器,并进入到容器 。
  3. 在容器里面做配置操作。
    • 安装基础命令
    • 配置运行环境
    • 安装服务和配置服务
    • 放业务程序代码
  4. 提交为一个新镜像 docker commit。
  5. 基于自己的的镜像创建容器并测试访问。
docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]REPOSITORY  软件名
TAG         版本号
选项含义
-a, --author string设置新创建镜像的作者信息。-a “John Doe john@example.com”
-c, --change list在创建新镜像时应用 Dockerfile 指令。允许在提交时修改容器配置。-c “EXPOSE 8080”
-m, --message string为提交操作添加说明信息。
-p, --pause在提交过程中暂停容器。暂停容器可以确保在创建镜像时数据状态的一致性。如果设置为 false,容器会在运行状态下被提交,可能导致数据不一致。

实际操作

基于 busybox 制作httpd镜像

docker run -it --name b1  busybox
启动  busybox 容器
hostname   -i
mkdir /data/html -p
新建主站点目录
echo testpage  > /data/html/index.html
新建站点目录
httpd -f  -h  /data/html/
-f 前台启动  -h 指定主站点

docker commit -a “cxk” -c ‘CMD /bin/httpd -fv -h /data/html’ -c “EXPOSE 80” b1 httpd-busybox:v1.0
-a作者 -c执行的命令 +暴露端口 b1镜像 打上标签。

在这里插入图片描述
在这里插入图片描述
启动制作好的容器

docker run -d --name web1 -P httpd-busybox:v1.0
启动容器
docker port  web1
查找真机端口号
curl 192.168.232.10:32768
测试

在这里插入图片描述

制作tomcat镜像

docker pull tomcat
拉取最新最新镜像
docker run -d -p 8080:8080 tomcat
后台启动并暴露端口

在这里插入图片描述
注意需要将默认的文件复制进去。

打包成镜像

docker commit -m "add webapps" -a "cxk" af153509d0c0 tomcat:10

在这里插入图片描述
启动容器:
在这里插入图片描述
使用真机访问。注意需要开启路由转发功能。在这里插入图片描述

基于ubuntu的基础镜像手动安装nginx镜像

docker pull ubuntu
下载ubuntu镜像并启动
docker run -it -p 80 --name ub_nginx ubuntu bash
启动基础镜像
sed -ri.bak  's#\/\/.*.ubuntu.com#\/\/mirrors.aliyun.com#' /etc/apt/sources.list
修改apt源
apt update
更新源
apt install  nginx -y
安装nginx

安装时需要选择时区。在这里插入图片描述

echo nginx web in docker  > /var/www/html/index.html
更改主页面
docker commit -a "cxk" -m "ubuntu-nginx" b8bbe4192623 u-nginx:v1.0
制作镜像docker commit -a "cxk" -m "ubuntu-nginx" b8bbe4192623 u-nginx:v1.0
测试容器
docker run -d -p 80 --name web u-nginx:v1.0 nginx -g "daemon off;"
注意daemon off后面要加分号

在这里插入图片描述
在这里插入图片描述

基于Centos的基础镜像利用yum安装手动制作nginx的镜像

修正时区和yum源ls -l /etc/localtime rm -rf /etc/localtime ln -s /usr/share/zoneinfo/Asia/Shanghai  /etc/localtime   

在这里插入图片描述

在宿主机中下载yum文件,并传递到容器中。
wget http://mirrors.aliyun.com/repo/Centos-8.repo
docker cp   Centos-8.repo 346366e54a31:/
建议删除其他源
安装nginx,修改配置文件。
yum install  nginx  net-tools安装nginx,修改配置文件。
daemon off;
前台执行。
生成页面
echo "nginx page in docker"  > /usr/share/nginx/html/index.html

打包成镜像

docker commit -a "cxk" -m 'yum nginx' -c "EXPOSE 80 443" c1 centos-nginx:v1.0
注意还需要暴露80和443端口

在这里插入图片描述
启动容器

docker run -d -p 80:80  --name  n2    centos-nginx:v1.0  nginx

在这里插入图片描述

在这里插入图片描述

三、利用DockerFile文件执行docker build自动构建镜像

Dockerfile使用介绍

介绍
DockerFile 是一种被Docker程序解释执行的脚本,由一条条的命令组成的,每条命令对应linux下面的一条命令,Docker程序将这些DockerFile指令再翻译成真正的linux命令,其有自己的书写方式和支持的命令,Docker程序读取DockerFile并根据指令生成Docker镜像,相比手动制作镜像的方式,DockerFile更能直观的展示镜像是怎么产生的,有了DockerFile,当后期有额外的需求时,只要在之前的DockerFile添加或者修改响应的命令即可重新生成新的Docker镜像,避免了重复手动制作镜像的麻烦,类似与shell脚本一样,可以方便高效的制作镜像Docker守护程序 Dockerfile 逐一运行指令,如有必要,将每个指令的结果提交到新镜像,然后最终输出新镜像的ID。Docker守护程序将自动清理之前发送的上下文。
请注意,每条指令都是独立运行的,并会导致创建新镜像,比如 RUN cd /tmp 对下一条指令不会有任何影响。
Docker将尽可能重用中间镜像层(缓存),以显著加速 docker build 命令的执行过程,这由 Using cache 控制台输出中的消息指示。

镜像制作和使用流程
在这里插入图片描述
制作镜像的分层结构
在这里插入图片描述
Dockerfile文件格式
Dockerfile 是一个有特定语法格式的文本文件。
官方说明:

https://docs.docker.com/engine/reference/builder/

Dockerfile文件说明

  • 每一行以Dockerfile的指令开头,指令不区分大小写,但是惯例使用大写。
  • 使用 # 开始作为注释。
  • 每一行只支持一条指令,每条指令可以携带多个参数
  • 指令按文件的顺序从上至下进行执行。
  • 每个指令的执行会生成一个新的镜像层,为了减少分层和镜像大小,尽可能将多条指令合并成一条指令。
  • 制作镜像一般可能需要反复多次,每次执行dockfile都按顺序执行,从头开始,已经执行过的指令已经缓存,不需要再执行,如果后续有一行新的指令没执行过,其往后的指令将会重新执行,所以为加速镜像制作,将最常变化的内容放下dockerfile的文件的后面。

Dockerfile 相关指令

ADD
COPY
ENV
EXPOSE
FROM
LABEL
STOPSIGNAL
USER
VOLUME
WORKDIR

FROM指定基础镜像

定制镜像,需要先有一个基础镜像,在这个基础镜像上进行定制。
FROM 就是指定基础镜像,此指令通常必需放在Dockerfile文件第一个非注释行。后续的指令都是运行于此基准镜像所提供的运行环境。
基础镜像可以是任何可用镜像文件,默认情况下,docker build会在docker主机上查找指定的镜像文件,在其不存在时,则会从Docker Hub Registry上拉取所需的镜像文件.如果找不到指定的镜像文件,docker build会返回一个错误信息。
如何选择合适的镜像?
对于不同的软件官方都提供了相关的docker镜像,比如: nginx、redis、mysql、httpd、tomcat等服务类的镜像,也有操作系统类,如: centos、ubuntu、debian等。建议使用官方镜像,比较安全。

FROM [--platform=<platform>] <image> [AS <name>]
FROM [--platform=<platform>] <image>[:<tag>] [AS <name>]
FROM [--platform=<platform>] <image>[@<digest>] [AS <name>]--platform 指定镜像的平台,比如: linux/amd64, linux/arm64, or windows/amd64
tag 和 digest是可选项,如果不指定,默认为latest
mkdir /data/dockerfile/system/centos/centos7 -p
方便管理和维护
vim Dockerfile
FROM  centos:7.9.2009
LABEL author="CXK cloud"  \version="1.0"       \description="test"
RUN   rm -rf /etc/yum.repos.d/*
RUN   mkdir /app && cd  /app
RUN   echo "hello" > test.txt
ENV   version="1.0" user=mysql\name=CXK 
RUN   touch $name.txt

在这里插入图片描述
在这里插入图片描述

LABAL指定镜像元数据

LABAL:说明信息
可以指定镜像元数据,如:镜像作者等。

LABEL <key>=<value> <key>=<value> <key>=<value> 反斜杠可以换行
#一行格式
LABEL multi.label1="value1" multi.label2="value2" other="value3"#多行格式
LABEL multi.label1="value1" \multi.label2="value2" \other="value3"

docker inspect命令可以查看LABEL。
在这里插入图片描述

RUN: 执行shell命令

RUN 指令用来在构建镜像阶段需要执行 FROM 指定镜像所支持的Shell命令。通常各种基础镜像一般都支持丰富的shell命令。
注意: RUN 可以写多个,每一个RUN指令都会建立一个镜像层,所以尽可能合并成一条指令,比如将多个shell命令通过 && 连接一起成为在一条指令。每个RUN都是独立运行的,和前一个RUN无关。

shell 格式: 相当于 /bin/sh -c <命令> 此种形式支持环境变量
RUN <命令> 
exec 格式: 此种形式不支持环境变量,注意:是双引号,不能是单引号
RUN ["可执行文件", "参数1", "参数2"]
exec格式可以指定其它shell
RUN ["/bin/bash","-c","echo hello wang"]

注意:多个前后RUN命令独立无关和shell命令不同

RUN cd /app
RUN echo "hello" > world.txt
world.txt并不存放在/app内。

COPY:复制文本

复制本地宿主机的到容器内部。

COPY [--chown=<user>:<group>] <src>... <dest>
COPY [--chown=<user>:<group>] ["<src>",... "<dest>"] #路径中有空白字符时,建议使用此格式

说明:

  • 可以是多个,可以使用通配符,通配符规则满足Go的filepath.Match 。 参考链接: https://golang.org/pkg/path/filepath/#Match

  • 必须是build上下文中的路径(为 Dockerfile 所在目录的相对路径),不能是其父目录中的文件

  • 如果是目录,则其内部文件或子目录会被递归复制,但目录自身不会被复制

  • 如果指定了多个, 或在中使用了通配符,则必须是一个目 录,且必须以 / 结尾

  • 可以是绝对路径或者是 WORKDIR 指定的相对路径。

  • 使用 COPY 指令,源文件的各种元数据都会保留。比如读、写、执行权限、文件变更时间等。

  • 如果事先不存在,它将会被自动创建,这包括其父目录路径,即递归创建目录。

COPY hom* /mydir/    
COPY hom?.txt /mydir/

ADD:制作和解压缩文件

该命令可以认为是增强版的COPY,不仅支持COPY,还支持自动解缩。可以将复制指定的到容器中的目录。

ADD [--chown=<user>:<group>] <src>... <dest>
ADD [--chown=<user>:<group>] ["<src>",... "<dest>"]

说明:

  • 可以是Dockerfile所在目录的一个相对路径;也可是一个 URL;还可是一个 tar 文件(自动解压)

  • 可以是绝对路径或者是 WORKDIR 指定的相对路径

  • 如果是目录,只复制目录中的内容,而非目录本身

  • 如果是一个 URL ,下载后的文件权限自动设置为 600

  • 如果为URL且不以/结尾,则指定的文件将被下载并直接被创建为,如果以 / 结尾,则文件名URL指定的文件将被直接下载并保存为/< filename>

  • 如果是一个本地文件系统上的打包文件,如: gz, bz2 ,xz ,它将被解包 ,其行为类似于"tar -x"命令,但是通过URL获取到的tar文件将不会自动展开

  • 如果有多个,或其间接或直接使用了通配符,则必须是一个以/结尾的目录路径;如果不以/结尾,则其被视作一个普通文件,的内容将被直接写入到

CMD:容器启动命令

一个容器中需要持续运行的进程一般只有一个,CMD 用来指定启动容器时默认执行的一个命令,且其运行结束后,容器也会停止,所以一般CMD 指定的命令为持续运行且为前台命令。

  • 如果docker run没有指定任何的执行命令或者dockerfile里面也没有ENTRYPOINT,那么开启容器时就会使用执行CMD指定的默认的命令。
  • 前面介绍过的 RUN 命令是在构建镜像进执行的命令,注意二者的不同之处。
  • 每个 Dockerfile 只能有一条 CMD 命令。如指定了多条,只有最后一条被执行
  • 如果用户启动容器时用 docker run xxx 指定运行的命令,则会覆盖 CMD 指定的命令。
 使用 exec 执行,推荐方式,第一个参数必须是命令的全路径,此种形式不支持环境变量
CMD ["executable","param1","param2"] 
CMD ["nginx", "-g", "daemon off;"]
注意要做软连接。
CMD   tail  -f  /etc/hosts
cmd的另一种写法。

编译安装nginx镜像

FROM  centos:7.9.2009
RUN   rm -rf /etc/yum.repos.d/*
COPY  *.repo /etc/yum.repos.d/
RUN   yum -y install gcc gcc-c++ make automake pcre pcre-devel zlib  zlib-devel openssl openssl-devel wget vim
ADD   nginx-1.18.0.tar.gz   /usr/local/src
RUN   cd  /usr/local/src/nginx-1.18.0  && ./configure  --prefix=/apps/nginx  && make   &&  make install
COPY  index.html    /apps/nginx/html
CMD   ["/apps/nginx/sbin/nginx","-g","daemon off;"]

在这里插入图片描述

ENTRYPOINT

ENTRYPOINT 指定的命令将成为容器启动时默认要执行的主命令。这个命令通常是容器的主要功能所需的可执行程序,例如 web 服务器、数据库等。

ENTRYPOINT ["executable", "param1", "param2"]
  • ENTRYPOINT 不能被 docker run 提供的参数覆盖,而是追加,即如果docker run 命令有参数,那么参数全部都会作为ENTRYPOINT的参数。
  • 如果docker run 后面没有额外参数,但是dockerfile中的CMD里有(即上面CMD的第三种用法),即Dockerfile中即有CMD也有ENTRYPOINT,那么CMD的全部内容会作为ENTRYPOINT的参数。
  • 如果docker run 后面有额外参数,同时Dockerfile中即有CMD也有ENTRYPOINT,那么docker run后面的参数覆盖掉CMD参数内容,最终作为ENTRYPOINT的参数。
  • 可以通过docker run --entrypoint string 参数在运行时替换,注意string不要加空格。
  • 使用CMD要在运行时重新写命令本身,然后在后面才能追加运行参数,ENTRYPOINT则可以运行时无需重写命令就可以直接接受新参数。
  • 每个 Dockerfile 中只能有一个 ENTRYPOINT,当指定多个时,只有最后一个生效。

示例:

FROM  centos:7.9.2009
RUN   yum -y install gcc gcc-c++ make automake pcre pcre-devel zlib  zlib-devel openssl openssl-devel wget
ADD   nginx-1.18.0.tar.gz   /usr/local/src
RUN   cd  /usr/local/src/nginx-1.18.0  && ./configure  --prefix=/apps/nginx  && make   &&  make install
COPY  index.html    /apps/nginx/html
CMD   [-g","daemon off;"]
ENTRYPOINT   ["/apps/nginx/sbin/nginx"]

会将CMD后面的参数,移植到ENTRYPOINT上。

ARG: 构建参数

ARG指令在build 阶段指定变量,和ENV不同的是,容器运行时不会存在这些环境变量。

ARG <name>[=<default value>]

如果和ENV同名,ENV覆盖ARG变量。
FROM指令支持由第一个FROM之前的任何ARG指令声明的变量。
示例:

ARG  CODE_VERSION=latest
FROM base:${CODE_VERSION}
CMD /code/run-app
FROM extras:${CODE_VERSION}
CMD /code/run-extras

在FROM之前声明的ARG在构建阶段之外,所以它不能在FROM之后的任何指令中使用。要使用在第一个FROM之前声明的ARG的默认值,请在构建阶段内使用没有值的ARG指令。

自我理解:相当于这是单纯为构建镜像所产生的变量。

ENV

用于设置环境变量

ENV MYSQL_ROOT_PASSWORD password
这会设置一个名为 MYSQL_ROOT_PASSWORD 的环境变量,值为 password。ENV <key1>=<value1> <key2>=<value2> 
一次性设置多个变量

如果在 Dockerfile 中多次设置同一个环境变量,则后面的设置会覆盖前面的。
在 docker run 命令中,可以使用 -e 或 --env 选项来覆盖容器内部的环境变量。
其中-e选项的级别最高。

VOLUME:匿名卷

在容器中创建一个可以从本地主机或其他容器挂载的挂载点,一般用来存放数据库和需要保持的数据等,一般会将宿主机上的目录挂载至VOLUME 指令指定的容器目录。即使容器后期被删除,此宿主机的目录仍会保留,从而实现容器数据的持久保存。

宿主机目录为

/var/lib/docker/volumes/<volume_id>/_data

语法:

vOLUME <容器内路径>
VOLUME ["<容器内路径1>", "<容器内路径2>"...]

注意:

  • Dockerfile中的VOLUME实现的是匿名数据卷,无法指定宿主机路径和容器目录的挂载关系。
  • 通过docker rm -fv <容器ID> 可以删除容器的同时删除VOLUME指定的卷。

范例: 在容器创建两个/data/ ,/data2的挂载点

vim Dockerfile 
FROM   ubuntu
VOLUME [ "/data1","/data2" ]

在这里插入图片描述
在这里插入图片描述

EXPOSE: 暴露端口

指定服务端的容器需要对外暴露(监听)的端口号,以实现容器与外部通信。EXPOSE 仅仅是声明容器打算使用什么端口而已,并不会真正暴露端口,即不会自动在宿主进行端口映射因此,在启动容器时需要通过 -P 或-p ,Docker 主机才会真正分配一个端口转发到指定暴露的端口才可使用
注意:即使Dockerfile没有EXPOSE 端口指令,也可以通过docker run -p临时暴露容器内程序真正监听的端口,所以EXPOSE 相当于指定默认的暴露端口,可以通过docker run -P 进行真正暴露。

EXPOSE <port>[/ <protocol>] [<port>[/ <protocol>] ..]
<protocol>用于指定传输层协议,可为tcp或udp二者之一,默认为TCP协议

WORKDIR: 指定工作目录

为后续的 RUN、CMD、ENTRYPOINT 指令配置工作目录,当容器运行后,进入容器内WORKDIR指定的默认目录,WORKDIR 指定工作目录(或称当前目录),以后各层的当前目录就被改为指定的目录,如该目录不存在,WORKDIR 会自行创建。

例子:

#两次RUN独立运行,不在同一个目录,
RUN cd /app
RUN echo "hello" > world.txt#如果想实现相同目录可以使用WORKDIR
WORKDIR /app
RUN echo "hello" > world.txt

可以使用多个 WORKDIR 指令,后续命令如果参数是相对路径,则会基于之前命令指定的路径。

WORKDIR /a
WORKDIR b
WORKDIR c
最终路径为/a/b/c

Dockerfile构建过程和指令总结

Dockerfile 构建过程

  • 从基础镜像运行一个容器

  • 执行一条指令,对容器做出修改

  • 执行类似docker commit的操作,提交一个新的中间镜像层(可以利用中间层镜像创建容器进行调试和排错)

  • 再基于刚提交的镜像运行一个新容器

  • 执行Dockerfile中的下一条指令,直至所有指令执行完毕

构建镜docker build 命令

docker build [OPTIONS] PATH | URL | -
说明:  
PATH | URL | -     #可以使是本地路径,也可以是URL路径。若设置为 - ,则从标准输入获取Dockerfile的内容
选项含义
-f, --file stringDockerfile文件名,默认为 PATH/Dockerfile
–force-rm总是删除中间层容器,创建镜像失败时,删除临时容器
–no-cache不使用之前构建中创建的缓存
-q --quiet=false不显示Dockerfile的RUN运行的输出结果
–rm=true创建镜像成功时,删除临时容器
-t --tag list#设置注册名称、镜像名称、标签。格式为 <注册名称>/<镜像名称>:<标签>(标签默认为latest)

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

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

相关文章

Python基础教程(三)类和对象、异常处理和模块

8.类与对象 8.1 面向对象 面向对象的三大基本特征: 封装、继承、多态。 在面向对象编程中&#xff0c;封装&#xff08;Encapsulation&#xff09;是一种将数据和操作&#xff08;方法&#xff09;组合在一起的机制。通过封装&#xff0c;我们可以隐藏数据的具体实现细节&am…

RuoYi-Vue-Plus (多数据源注解使用、【手动、拦截器】切换数据源)

接上文多数据源配置&#xff1a; RuoYi-Vue-Plus (多数据源配置)-CSDN博客 一、功能演示 代码生成菜单页面&#xff0c; 展示数据源切换 查询主库 查询从库 二、前端传参切换数据源 页面路径&#xff1a; src/views/tool/gen/index.vue 搜索框如下&#xff1a;下面4发送请求时…

技术分享| 前端性能优化——虚拟滚动(Virtual Scroll)

前端遇到大量数据&#xff08;尤其是大数据表&#xff09;的DOM 渲染时&#xff0c;通常会卡顿&#xff0c;需要考虑优化性能问题&#xff0c;这里针对DOM 渲染引出“虚拟滚动”方案&#xff0c; 详细请在以下各文章中详细了解&#xff1a; vue插件 vue-virtual-scroll-list解决…

干货满满,从零到一:编程小白如何在大学成为编程大神?

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…

ClickHouse 24.6 版本发布说明

本文字数&#xff1a;14127&#xff1b;估计阅读时间&#xff1a;36 分钟 作者&#xff1a;ClickHouse team 本文在公众号【ClickHouseInc】首发 又到了发布新版本的时间&#xff01; 发布概要 本次ClickHouse 24.6 版本包含了23个新功能&#x1f381;、24项性能优化&#x1f6…

嵌入式人工智能(39-基于树莓派4B的震动传感器和霍尔传感器)

这两个传感器实验比较简单&#xff0c;也都属于力传感器&#xff0c;就放一起做了。 1、震动传感器 震动传感器是一种用于检测和测量物体震动、振动和冲击的设备。它通常由一个敏感元件和一个信号处理单元组成。敏感元件可以是压电材料、光电材料、加速度传感器等。当物体发生…

【Git】git 从入门到实战系列(一)—— Git 的诞生,Linus 如何在 14 天内编写出 Git?

<> 博客简介&#xff1a;Linux、rtos系统&#xff0c;arm、stm32等芯片&#xff0c;嵌入式高级工程师、面试官、架构师&#xff0c;日常技术干货、个人总结、职场经验分享   <> 公众号&#xff1a;嵌入式技术部落   <> 系列专栏&#xff1a;C/C、Linux、rt…

golang JSON序列化

JSON JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。 易于人阅读和编写。同时也易于机器解析和生成。 它基于JavaScript Programming Language, Standard ECMA-262 3rd Edition - December 1999的一个子集。 json历史 [外链图片转存失败,源站可能有防盗链机…

看不见的硝烟:中国网络安全三十年沉浮史

2022 年 5 月 16 日&#xff0c;俄罗斯黑客组织 KillNet 向包括美国、英国、德国在内 10 个国家的政府正式 “宣战”。 2022 年 4 月 28 日&#xff0c;一则消息刷屏&#xff0c;北京健康宝在使用高峰期间&#xff0c;遭受到境外网络攻击。北京健康宝保障团队进行了及时有效应…

4G/5G无线视频采集设备如何通过国标28181接入到视频监控接入平台(视频统一接入平台)

目录 一、国标GB/T 28181介绍 1、国标GB/T28181 2、内容和特点 二、4G/5G无线视频采集设备 1、定义 2、主要功能&#xff1a; 3、技术特点 4、应用场景 二、接入准备工作 1、确定网络环境 &#xff08;1&#xff09;公网接入 &#xff08;2&#xff09;专网传输 2、…

一款功能强大的免费开源卸载工具

BCUninstaller&#xff0c;也称为Bulk Crap Uninstaller&#xff08;简称BCU&#xff09;&#xff0c;是一款免费且开源的Windows平台专用程序卸载工具。它的主要功能是帮助用户高效地批量卸载不需要的应用程序和组件&#xff0c;从而优化系统性能。 BCUninstaller功能特点 批…

这本vue3编译原理开源电子书,初中级前端竟然都能看懂

前言 众所周知vue提供了很多黑魔法&#xff0c;比如单文件组件(SFC)、指令、宏函数、css scoped等。这些都是vue提供的开箱即用的功能&#xff0c;大家平时用这些黑魔法的时候有没有疑惑过一些疑问呢。 我们每天写的vue代码一般都是写在*.vue文件中&#xff0c;但是浏览器却只…

【大厂笔试】翻转、平衡、对称二叉树,最大深度、判断两棵树是否相等、另一棵树的子树

检查两棵树是否相同 100. 相同的树 - 力扣&#xff08;LeetCode&#xff09; 思路解透 两个根节点一个为空一个不为空的话&#xff0c;这两棵树就一定不一样了若两个跟节点都为空&#xff0c;则这两棵树一样当两个节点都不为空时&#xff1a; 若两个根节点的值不相同&#xff…

【数据结构】了解哈希表,解决哈希冲突,用Java模拟实现哈希桶

哈希表的概念 哈希表&#xff08;Hash Table&#xff09;是一种高效的数据结构&#xff0c;用于实现快速的数据存储和检索。它通过将数据映射到一个数组的索引位置&#xff0c;从而能够在平均情况下实现O(1)的时间复杂度进行查找、插入和删除操作。 哈希表的基本概念包括以下…

java面向对象重点总结

文章目录 java面向对象重点总结类与实例构造方法方法重载属性与修饰符封装继承多态重构抽象类接口抽象类和接口的区别&#xff1a;集合泛型 java面向对象重点总结 对象是一个自包含的实体&#xff0c;用一组可识别的特性和行为来标识。 面向对象编程&#xff0c;英文叫Object…

flink 1.17 测试

1、配置 2、测试&#xff1a; ./bin/flink run-application -t yarn-application -Dyarn.application.namewordcount -c org.apache.flink.streaming.examples.wordcount.WordCount ./examples/streaming/WordCount.jar --input hdfs://jy/tmp/input --output hdfs://jy/tmp/o…

C++学习:C++是如何运行的

C 是一种强类型的编程语言&#xff0c;支持面向对象、泛型和低级内存操作。它的工作机制包括从编写源代码到生成可执行文件的一系列步骤。C与文件无关&#xff0c;文件只是容纳运行内容的载体&#xff0c;需要对文件以目标系统的规则编译后&#xff0c;才能在目标系统中运行。 …

java算法递归算法练习-数组之和

简单找个题目练习一下递归算法&#xff0c;输入一组数组&#xff0c;使用递归的方法计算数组之和。其实这个题目&#xff0c;用循环的方式也很简单就能解决&#xff0c;直接循环遍历一下相加就行了&#xff0c;但是我们用来练习一下递归。 先来找基线条件和递归条件 基线条件…

springboot+webSocket对接chatgpt

webSocket对接参考 话不多说直接上代码 WebSocket package com.student.config;import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONObject; import lombok.extern.slf4j.Slf4j; import org.springframework.http.MediaType; import org.springfram…

matplotLib在图中标出最后一个点的值

import matplotlib.pyplot as plt import numpy as np# 生成100个随机数据 data np.random.rand(100)# 绘制数据 plt.plot(data, labelData Points)# 获取最后一个数据点的位置和值 last_x len(data) - 1 last_y data[-1]# 用红圈标出最后一个点 plt.plot(last_x, last_y, r…