Docker五部曲之三:镜像构建

文章目录

  • 前言
  • Docker构建架构
  • 构建指令
  • 构建上下文
    • 本地目录
    • Git存储库
    • 压缩文件
    • 纯文本文件
    • .dockerignore文件
  • Dockerfile
    • 解析器指令
    • 环境变量
    • 命令执行格式
      • exec格式
      • shell格式
    • FROM
    • RUN
    • CMD
    • LABEL
    • EXPOSE
    • ENV
    • ADD
    • COPY
    • ENTRYPOINT
    • VOLUME
    • USER
    • WORKDIR
    • ARG
    • ONBUILD
    • SHELL
  • 多级构建

前言

本文均翻译自官网文档

Docker构建架构

Docker构建实现了CS架构:

  • Buildx是用于运行和管理构建的客户端
  • BuildKit是处理构建执行的服务器或构建器

在这里插入图片描述

构建指令

docker build命令从Dockerfile和上下文中构建镜像。构建的上下文是位于指定PATH或URL中的文件集。构建过程可以引用上下文中的任何文件。如果Docker客户端失去与守护进程的连接,构建将被取消(包括远程上下文的获取)。

docker build [OPTIONS] PATH | URL | -

常用的OPTIONS如下:

  • --tag | -t:为构建的镜像添加标签
  • --file | -f :指定Dockerfile
  • --build-arg:可以在Dockerfile中使用ENV指令来定义变量。这些值在构建的映像中持续存在。该指令可以创建并传递构建时变量,这些变量可以像在Dockerfile的RUN指令中访问常规环境变量一样访问。但是这些变量不会保存在中间或最终镜像中。
docker build --build-arg HTTP_PROXY=http://10.20.30.2:1234 --build-arg FTP_PROXY=http://40.50.60.5:4567 .
#也可以使用不带值的,在这种情况下,本地环境的值将被传播到正在构建的Docker容器中
docker build --build-arg HTTP_PROXY --build-arg FTP_PROXY .
  • --target:当构建具有多个构建阶段的Dockerfile时,可以使用该标志指定一个中间构建阶段作为最终映像的最终阶段。目标阶段之后的命令将被跳过。

构建上下文

docker build命令中的构建上下文参数对应如下:

  • PATH:本地目录
  • URL:Git仓库、压缩文件、纯文本文件
  • -(管道) :压缩文件、纯文本文件

从内容分类上可以将构建上下文分为两类:

  • 文件系统上下文:如果构建上下文是本地目录、远程Git存储库和压缩文件,那么它将成为构建器在构建期间可以访问的文件集。
  • 纯文本文件上下文:当构建上下文是纯文本文件时,构建器将该文件解释为Dockerfile。使用这种方法,构建不使用文件系统上下文。

本地目录

当指定一个本地目录路径时,本地目录中的所有文件都将被格式化并发送给Docker守护进程。

docker build .

Git存储库

当URL参数指向Git存储库的位置时,系统首先将存储库拉入本地主机上的临时目录。操作成功后,将该目录作为上下文发送给Docker守护进程。Git URL在其片段部分接受上下文配置,以冒号分隔。第一部分表示Git将检出的引用,可以是分支、标记或远程引用。第二部分表示存储库中的子目录,该子目录将用作构建上下文。

docker build myrepo.git#mybranch:myfolder

压缩文件

当URL参数是一个压缩文件时,会将该URL发给Docker守护进程,下载操作将在运行Docker守护进程的主机上执行,而该主机不一定是发出构建命令的主机。Docker守护进程将获取压缩文件并使用它作为构建上下文。Tarball上下文必须是符合标准tar UNIX格式的压缩文件。

docker build http://server/context.tar.gz

纯文本文件

可以在URL中传递单个Dockerfile,或者通过STDIN将文件导入管道。从STDIN管道一个Dockerfile:

docker build - < Dockerfile

如果使用STDIN或指定指向纯文本文件的URL,则系统将内容放入名为Dockerfile的文件中,并且忽略任何-f选项,换句话说此时不使用文件构建上下文。

.dockerignore文件

文件构建上下文中的文件无论在Dockerfile中是否包含,都会打包发给Docker守护进程,可以使用.dockerignore文件从构建上下文中排除文件或目录。这有助于避免向构建器发送不需要的文件和目录,从而提高构建速度,特别是在使用远程构建器时。当运行构建命令时,构建客户机将在上下文的根目录中查找一个名为.dockerignore的文件。如果此文件存在,则在将其发送给构建器之前,将与文件中的模式匹配的文件和目录从构建上下文中删除。当使用多个Dockerfile时,可以通过将.dockerignore文件放在与Dockerfile相同的目录下,并在.dockerignore文件前面加上Dockerfile的名字的方式为每个Dockerfile使用不同的.dockerignore文件。

├── docker
│   ├── build.Dockerfile
│   ├── build.Dockerfile.dockerignore
│   ├── lint.Dockerfile
│   ├── lint.Dockerfile.dockerignore
│   ├── test.Dockerfile
│   └── test.Dockerfile.dockerignore

.dockerignore文件是一个以换行符分隔的模式列表,类似于Unix shell的文件globs。出于匹配的目的,构建上下文的根被认为是工作目录和根目录。如果您有兴趣了解.dockerignore模式匹配逻辑的精确细节,请查看GitHub上的moby/patternmatcher存储库。

规则行为
# comment注释
*/temp*在根的任何直接子目录中排除名称以temp开头的文件和目录
*/*/temp*从根目录下面两层的任何子目录中排除以temp开头的文件和目录。
temp?排除根目录中名称为一个字符扩展名temp的文件和目录
**匹配任意数量的目录包括零
以!开头的行(感叹号)可以用来对排除的内容作出例外

Dockerfile

Docker通过按顺序读取并运行Dockerfile中的指令来构建镜像。Dockerfile是一个文本文件,包含构建源代码的说明。Docker镜像由层组成。每一层都是Dockerfile中构建指令的结果。层按顺序堆叠,每一层都表示应用于前一层的更改。

解析器指令

解析器指令是可选的,会影响Dockerfile中后续行的处理方式。解析器指令不向构建中添加层,也不显示为构建步骤。解析器指令被写成一种特殊类型的注释,格式为

# directive=value

解析器指令必须出现在Dockerfile第一行,且一个Dockerfile中的解析器指令只会被处理第一个,其它的都会被当作注释。

# syntax=docker/dockerfile:1 //最新版本

解析器指令包含以下两条指令:

  • escape:用于指定Dockerfile中的转义字符,没指定默认为\。这在Win系统上非常有用,因为Win的路径分隔符为\。转义字符既用于转义行中的字符,也用于转义换行。注意,无论Dockerfile中是否包含转义解析器指令,在RUN命令中都不会执行转义,除非在一行的末尾。
  • syntax:用于指定Dockerfile的文件版本

环境变量

环境变量(包括ENV指令声明的)可以用于以下指令中:

  • ADD
  • COPY
  • ENV
  • EXPOSE
  • FROM
  • LABEL
  • STOPSIGNAL
  • USER
  • VOLUME
  • WORKDIR
  • ONBUILD(与上述指令结合使用时)

环境变量在Dockerfile中用${variable_name}表示,${variable_name}语法还支持以下指定的一些标准bash修饰符:

  • ${variable:-word}表示如果设置了变量,那么结果将是该值。如果变量未设置,则结果为word
  • ${variable:+word}表示如果设置了变量,则结果为word,否则结果为空字符串。

注意,环境变量替换在整个指令中对每个变量使用相同的值。修改变量的值只在后续指令中生效。

命令执行格式

RUN、CMD和ENTRYPOINT指令可以有两种执行命令的格式:

  • exec form:RUN|CMD|ENTERPOINT ["executable","param1","param2"]
  • shell form:RUN|CMD|ENTERPOINT command param1 param2

exec格式

exec格式可以避免shell字符串修改,并且可以使用特定的命令shell或任何其他可执行文件调用命令。它使用JSON数组语法,其中数组中的每个元素是一个命令、标志或参数。它最适合用于指定ENTRYPOINT指令,并与CMD结合以设置可在运行时覆盖的默认参数。

  • 使用exec格式不会自动调用命令shell。这意味着正常的shell处理(例如变量替换)不会发生。
  • 使用exec格式必须转义反斜杠

shell格式

shell格式更加轻松,强调易用性、灵活性和可读性。shell格式会自动使用命令shell。可以使用SHELL命令更改默认shell:

SHELL ["/bin/bash", "-c"]

FROM

FROM指令初始化一个新的构建阶段,并为后续指令设置基本映像。因此,一个有效的Dockerfile必须以FROM指令开始。

FROM [--platform=<platform>] <image> [AS <name>]
FROM [--platform=<platform>] <image>[:<tag>] [AS <name>]
FROM [--platform=<platform>] <image>[@<digest>] [AS <name>]
  • FROM之前可以有一个或多个ARG指令,这些指令声明了FROM指令中使用的参数。FROM指令支持由任何出现在第一个FROM之前的ARG指令声明的变量。在FROM之前声明的ARG在构建阶段之外,因此它不能在FROM之后的任何指令中使用。要使用在第一个FROM之前声明的ARG,可以在构建阶段中使用不带值的ARG指令再次声明。
  • FROM指令可以在单个Dockerfile中出现多次,以创建多个镜像,或者将一个构建阶段用作另一个构建阶段的依赖。只需在每个新的FROM指令之前记录提交操作输出的最后一个镜像ID。每个FROM指令清除由前一个指令创建的任何状态。
  • 通过向FROM指令添加AS别名,可以为新的构建阶段指定一个可选的名称。该名称可以在后续的FROMCOPY --from =<name>指令中使用,以引用在此阶段构建的镜像。
  • tagdigest是可选的。如果省略其中任何一个,则构建器默认使用最新标记。如果构建器找不到标记值,则返回一个错误。
  • FROM引用多平台映像的情况下,可选的--platform标志可用于指定映像的平台。默认情况下,使用构建请求的目标平台。

RUN

RUN指令将执行任何命令,在当前镜像之上创建一个新层。添加的层在Dockerfile的下一步中使用。

RUN ["executable","param1","param2"]
RUN command param1 param2
  • --mount=[type=<TYPE>][,option=<value>[,option=<value>]...]:用于指定挂载
  • --network=<TYPE>:用于控制指令在哪个网络环境中执行
类型说明
default(默认)相当于根本不提供标志,该命令在构建的默认网络中运行。
none在没有网络访问的情况下运行
host载容器主机网路环境下运行

CMD

CMD指令用于设置从镜像运行容器时的指令。

CMD ["executable","param1","param2"]
CMD command param1 param2
CMD ["param1","param2"]
  • 一个Dockerfile中只能有一个CMD指令。如果您列出了多个CMD命令,则只有最后一个生效。
  • CMD的目的是为执行容器提供默认值。这些默认值可以包含可执行文件,也可以省略可执行文件,在这种情况下,您还必须指定ENTRYPOINT指令。
  • 如果您希望您的容器每次都运行相同的可执行文件,那么您应该考虑将ENTRYPOINTCMD结合使用。
  • 如果用户为docker run指定了参数,那么它们将覆盖CMD中指定的默认值,但仍然使用默认的ENTRYPOINT
  • 如果CMD用于为ENTRYPOINT指令提供默认参数,则CMDENTRYPOINT指令都因该使用exec格式。

LABEL

LABEL指令将元数据添加到映像中。LABEL是一个键值对。一个镜像可以有多个标签。并且可以在一行上指定多个标签。

LABEL <key>=<value> <key>=<value> <key>=<value> ...

包含在基镜像或父镜像中的标签由镜像继承。如果标签已经存在,但具有不同的值,则最近应用的值将覆盖以前设置的任何值。

EXPOSE

EXPOSE指令通知Docker容器在运行时监听指定的网络端口。您可以指定端口是侦听TCP还是UDP,如果不指定协议,则默认为TCP。

EXPOSE <port> [<port>/<protocol>...]

EXPOSE指令实际上并不发布端口。它的作用是作为构建镜像的人员和运行容器的人员之间的一种文档,说明打算发布哪些端口。

ENV

ENV指令将环境变量<key>设置为值<value>。该值将存在于构建阶段所有后续指令的环境中,也可以在许多环境中内联替换。

ENV <key>=<value> ...
  • 当从生成的镜像运行容器时,使用ENV设置的环境变量将持续存在。并可以使用docker run --env <key>=<value>更改它们。
  • 一个构建阶段继承由它的父阶段或任何祖先阶段使用ENV设置的任何环境变量。
  • 环境变量持久性可能导致意想不到的副作用,如果环境变量只在构建过程中需要,而不是在最终映像中需要,可以使用ARG,它不会保留在最终镜像中。

ADD

ADD指令从<src>复制新的文件、目录或远程文件URL,并将它们添加到路径<dest>的镜像文件系统中。

ADD [--chown=<user>:<group>] [--chmod=<perms>] [--checksum=<checksum>] <src>... <dest>
ADD [--chown=<user>:<group>] [--chmod=<perms>] ["<src>",... "<dest>"]
  • 每个<src>可以包含通配符,匹配将使用Go的文件路径匹配规则。
  • <dest>是一个绝对路径,或者一个相对于WORKDIR的路径,源文件将被复制到目标容器中的这个路径中。
  • <src>路径必须在构建上下文中,因为构建器只能从上下文访问文件。
  • 如果<src>是一个目录,则复制该目录的全部内容,包括文件系统元数据。
  • 如果<src>是以可识别的压缩格式生成的本地tar压缩文件,则将其解压缩为目录,但来自远程URL的资源没有解压缩。
  • 如果直接或使用通配符指定了多个<src>资源,则<dest>必须是一个目录,并且必须以斜杠结尾。
  • 如果<dest>没有以斜杠结尾,它将被认为是一个常规文件,并且<src>的内容将被写在<dest>
  • 如果<dest>不存在,则创建它,以及其路径中所有缺失的目录。

COPY

COPY指令从和ADD指令功能几乎一样,唯一的区别在于COPY只能拷贝工作目录下的文件到容器的文件系统。

COPY [--chown=<user>:<group>] [--chmod=<perms>] <src>... <dest>
COPY [--chown=<user>:<group>] [--chmod=<perms>] ["<src>",... "<dest>"]
  • --from=<name>:该标志可用于将源位置设置为以前的构建阶段(FROM ... AS <name>)。如果找不到具有指定名称的构建阶段,则尝试使用具有相同名称的镜像。

ENTRYPOINT

ENTRYPOINT用于配置作为可执行文件而运行的容器。

ENTRYPOINT ["executable", "param1", "param2"]
ENTRYPOINT command param1 param2
  • docker run <image>的命令行参数将附加在exec格式下ENTRYPOINT中所有元素之后,并且将覆盖使用CMD指定的所有元素。比如docker run <image> -d将传递参数-dENTRYPOINT,你可以使用docker run --ENTRYPOINT标志覆盖ENTRYPOINT指令。
  • ENTRYPOINT的shell格式防止使用任何CMD命令行参数。该子命令不传递信号。这意味着可执行文件不会是容器的PID 1,也不会接收Unix信号。在这种情况下,您的可执行文件不会从docker stop <container>接收SIGTERM。
  • 只有Dockerfile中最后一个ENTRYPOINT指令才会生效。

ENTRYPOINTCMD的区别与联系如下:

  • Dockerfile应该至少指定CMDENTRYPOINT命令中的一个
  • 当将容器用作可执行文件时,应该定义ENTRYPOINT
  • CMD应该用作定义ENTRYPOINT命令的默认参数或在容器中执行临时命令的一种方式。
  • 当使用可选参数运行容器时,CMD将被覆盖

VOLUME

VOLUME指令创建具有指定名称的挂载点,并将其标记为保存来自本机主机或其他容器的外部挂载卷。取值为JSON数组。

VOLUME ["/data"]

在Dockerfile内创建卷应注意以下事项:

  • 基于windows的容器中的卷:当使用基于windows的容器时,容器内的卷的目标必须是:
    • 不存在的目录或空目录
    • C以外的驱动器
  • 在Dockerfile中更改卷:如果任何构建步骤在声明后更改了卷中的数据,这些更改将被丢弃。
  • 主机目录是在容器运行时声明的:主机目录(挂载点)本质上依赖于容器主机。这是为了保持镜像的可移植性,因为不能保证给定的主机目录在所有主机上都可用。由于这个原因,您不能从Dockerfile中挂载主机目录。

USER

USER指令设置用户名和可选的用户组,作为当前阶段剩余时间的默认用户和组。指定的用户用于RUN指令,并在运行时运行相关的ENTRYPOINTCMD命令

USER <user>[:<group>]
USER <UID>[:<GID>]

WORKDIR

WORKDIR指令为Dockerfile中跟随它的RUNCMDENTRYPOINTCOPYADD指令设置工作目录。如果WORKDIR不存在,即使在后续的Dockerfile指令中没有使用它,它也会被创建。如果未指定,则默认工作目录为/,或从父镜像上继承。

WORKDIR /path/to/workdir
  • WORKDIR指令可以在Dockerfile中多次使用。如果提供了一个相对路径,它将相对于之前的WORKDIR指令的路径。
  • WORKDIR指令可以解析以前使用ENV设置的环境变量。

ARG

ARG指令定义了一个变量,用户可以在构建时使用docker build --build- arg <varname>=<value>标志将该变量传递给构建器。如果用户指定的构建参数没有在Dockerfile中定义,那么构建将输出一个警告。

ARG <name>[=<default value>]
  • Dockerfile可以包含一个或多个ARG指令。
  • ARG指令可以选择包含一个默认值,如果ARG指令有默认值,并且在构建时没有传递值,则构建器使用默认值。
  • ARG变量定义从Dockerfile中定义它的那一行开始生效。并只作用于它所属的构建阶段。
  • 可以使用ARGENV指令来指定可供RUN指令使用的变量。使用ENV指令定义的环境变量总是覆盖同名的ARG指令。
  • 有一些预定义的ARG变量,具体可看官方文档。

ONBUILD

ONBUILD指令将一个触发指令添加到映像中,以便稍后在映像用作另一个构建的基础时执行。触发器将在下游构建的上下文中执行,就像它被插入到下游Dockerfile中的FROM指令之后一样。

ONBUILD <INSTRUCTION>

任何构建指令都可以注册为触发器。

SHELL

SHELL指令允许覆盖用于SHELL形式命令的默认SHELL

SHELL ["executable", "parameters"]

SHELL指令可以出现多次。每个SHELL指令覆盖之前的所有SHELL指令,并影响所有后续指令

多级构建

在多阶段构建中,您可以在Dockerfile中使用多个FROM语句。每个FROM指令可以使用不同的基,并且每个FROM指令都开始构建的新阶段。您可以选择性地将工件从一个阶段复制到另一个阶段,在最终镜像中抛弃您不想要的所有内容。

# syntax=docker/dockerfile:1FROM eclipse-temurin:17-jdk-jammy as base
WORKDIR /app
COPY .mvn/ .mvn
COPY mvnw pom.xml ./
RUN ./mvnw dependency:resolve
COPY src ./srcFROM base as development
CMD ["./mvnw", "spring-boot:run", "-Dspring-boot.run.profiles=mysql", "-Dspring-boot.run.jvmArguments='-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:8000'"]FROM base as build
RUN ./mvnw packageFROM eclipse-temurin:17-jre-jammy as production
EXPOSE 8080
COPY --from=build /app/target/spring-petclinic-*.jar /spring-petclinic.jar
CMD ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/spring-petclinic.jar"]

当使用FROM指令时,可以通过引用它来拾取上一个阶段停止的地方:

FROM base as development

在执行构建指令时,可以指定构建哪个阶段:

docker build --target development .

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

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

相关文章

对快速排序思想的进一步理解,分而治之,欧几里得算法(常用求最大公约数的方法)

自己找到的最优的快排的代码 快速排序 思想 分而治之使用欧几里得算法&#xff08;辗转相除法&#xff09;来求解一个应用题 假设有一块地&#xff0c;现在用这个同样大小的正方形来铺满&#xff0c;求所可用的最大的正方形地砖的面积 这两个方法放在一起是因为这个欧几里得要…

Linux环境之Ubuntu安装Docker流程

今天分享Linux环境之Ubuntu安装docker流程&#xff0c;Docker 是目前非常流行的容器&#xff0c;对其基本掌握很有必要。下面我们通过阿里云镜像的方式安装&#xff1a; 本来今天准备用清华大学镜像安装呢&#xff0c;好像有点问题&#xff0c;于是改成阿里云安装了。清华安装…

抓交通肇事犯(python)

问题描述&#xff1a; 一辆卡车违反交通规则&#xff0c;撞人后逃跑。现场有三人目击该事件&#xff0c;但都没有记住车号&#xff0c;只记下了车号的一些特征。甲说&#xff1a;牌照的前两位数字是相同的&#xff1b;乙说&#xff1a;牌照的后两位数字是相同的&#xff0c;但…

GVM垃圾收集器

Serial收集器&#xff08;新生代&#xff09; Serial&#xff08;串行&#xff09;收集器是最基本、历史最悠久的垃圾收集器&#xff0c;采用“标记-复制”算法负责新生代的垃圾收集。它是Hotspot虚拟机运行在客户端模式下的默认新生代收集器。 它是一个单线程收集器。它会使用…

软件测试学到这个程度,面试轻松拿下20K

很多人认为&#xff0c;软件测试是一个简单的职位&#xff0c;职业生涯走向也不会太好&#xff0c;但是随着时间的推移&#xff0c;软件测试行业的变化&#xff0c;人们开始对软件测试行业的认知有了新的高度&#xff0c;越来越多的人开始关注这个行业&#xff0c;开始重视这个…

v-if控制div内容显示,克隆这个div但是v-if没有效果

问题描述&#xff1a; 我的子页面打印的时候通过isPdf来隐藏“选择参加人员”按钮。 我子页面有个el-dialog&#xff0c;el-dialog里面有个大的div它的id为app-pre-meet-add&#xff0c;在子页面我通过isPdf来显示我想要的内容。现在我在父页面先通过this.$refs.child.control…

分布式缓存

分布式缓存 缓存雪崩 缓存雪崩我们可以简单的理解为&#xff1a;由于原有缓存失效&#xff0c;新缓存未到期间所有原本应该访问缓存的请求都去查询数据库了&#xff0c;而对数据库 CPU 和内存造成巨大压力&#xff0c;严重的会造成数据库宕机。从而形成一系列连锁反应&#xf…

C++与Typescript的区别

目录 一、C类模板和函数模板 1.类模板 2.函数模板 二&#xff0c;Typescript 的泛型声明 1.泛型函数 2.泛型类 为什么C和Typescript语言中主张模板和泛型 一、C类模板和函数模板 在C中&#xff0c;类模板和函数模板允许你为多种数据类型编写通用的代码。这就像每个人都有…

山西电力市场日前价格预测【2024-01-14】

日前价格预测 预测说明&#xff1a; 如上图所示&#xff0c;预测明日&#xff08;2024-01-14&#xff09;山西电力市场全天平均日前电价为415.13元/MWh。其中&#xff0c;最高日前电价为851.84元/MWh&#xff0c;预计出现在18:15。最低日前电价为198.87元/MWh&#xff0c;预计…

使用 C++/WinRT 创作 API

如果 API 位于 Windows 命名空间中 这是你使用 Windows 运行时 API 最常见的情况。 对于元数据中定义的 Windows 命名空间中的每个类型&#xff0c;C/WinRT 都定义了 C 友好等效项&#xff08;称为投影类型 &#xff09;。 投影类型具有与 Windows 类型相同的完全限定名称&…

【LabVIEW FPGA入门】使用CompactRIO进行SPI和I2C通信

NI提供了 SPI and I2C Driver API&#xff1a;下载SPI and I2C Driver API - NI 该API使用FPGA数字I / O线与SPI或I2C设备进行通信。 选择数字硬件时&#xff0c;要考虑三个选项&#xff1a; NI Single-Board RIO硬件可同时使用SPI和I2C驱动程序。NI 9401 C系列模块与SPI驱动程…

大型语言模型,用最少的数学和行话进行解释

本文来自于《Large language models, explained with a minimum of math and jargon》&#xff0c;不嵌入任何笔者的个人理解&#xff0c;只是对原文的总结与记录。 文章作者是Tim Lee和Sean Trott&#xff0c;Tim Lee是一位拥有计算机科学硕士学位的记者&#xff0c;Sean Trot…

【二十】【动态规划】879. 盈利计划、377. 组合总和 Ⅳ、96. 不同的二叉搜索树 ,三道题目深度解析

动态规划 动态规划就像是解决问题的一种策略&#xff0c;它可以帮助我们更高效地找到问题的解决方案。这个策略的核心思想就是将问题分解为一系列的小问题&#xff0c;并将每个小问题的解保存起来。这样&#xff0c;当我们需要解决原始问题的时候&#xff0c;我们就可以直接利…

关于jupyter突然打不开的问题

好久没有用python了&#xff0c;我的电脑环境是安装过anaconda和pycharm&#xff0c;但是有些简单的东西就希望在jupyter中测试一下&#xff0c;但是最近发现jupyter打不开了。 具体是&#xff1a; 在这里打开jupyter是可以的&#xff0c;但是在命令行就不行&#xff0c;表现为…

计算机毕业设计 | SpringBoot+vue的家庭理财 财务管理系统(附源码)

1&#xff0c;绪论 1.1 项目背景 网络的发展已经过去了七十多年&#xff0c;网络技术的发展&#xff0c;将会影响到人类的方方面面&#xff0c;网络的出现让各行各业都得到了极大的发展&#xff0c;为整个社会带来了巨大的生机。 现在许多的产业都与因特网息息相关&#xff…

Python实现华容道问题详解

概要 华容道是一种古老的中国益智游戏&#xff0c;最早出现在中国的《千古文馆》中。这个游戏的目标是将一块特殊的方块从一个方形的棋盘中移出&#xff0c;通过滑动其他的方块来达到这个目标。本文将介绍如何使用Python来实现华容道问题&#xff0c;并提供详细的代码示例。 游…

飞鱼CRM接入第三方系统 飞鱼API对接详细教程

场景描述 在白码低代码开发平台中&#xff0c;是支持外部crm系统的线索通过接口流入到白码系统里面&#xff0c;换而言之&#xff0c;只要外部的系统有线索api接口&#xff0c;白码系统可以接收线索并在白码系统上进行后续操作。本文以飞鱼crm系统为例&#xff0c;讲解如何接收…

学习就要从简单的开始嘛,开始学一个个人博客吧

做一个个人博客第一步该怎么做&#xff1f; 好多零基础的同学们不知道怎么迈出第一步。 那么&#xff0c;就找一个现成的模板学一学呗&#xff0c;毕竟我们是高贵的Ctrl c v 工程师。 但是这样也有个问题&#xff0c;那就是&#xff0c;那些模板都&#xff0c;太&#xff01;…

Linux/Haystack

Enumeration nmap 还是先看看端口对外开放情况&#xff0c;对外开放了22,80,9200 22应该是ssh&#xff0c;80是web&#xff0c;9200不知道是什么 TCP/80 访问web&#xff0c;没有什么链接&#xff0c;只有一张图片 有可能图片中有些东西&#xff0c;但还是尝试扫描一下网站…

ptaR7-6/zzuli2106 有去有回

题目 输入n个整数&#xff0c;第一趟按从左到右间隔k个数取数据&#xff0c;然后第二趟再从右到左间隔k-1个数取余下的数&#xff0c;如果数据没有取完&#xff0c;下一趟再间隔k-2个从左到右取数据&#xff0c;如此反复&#xff0c;直到所有的数据取完为止。注意&#xff1a;…