【Docker深入浅出】Docker镜像

news2024/12/23 19:53:45

文章目录

  • 一. Docker镜像简介
  • 二. Docker镜像详解
    • 1. 镜像和容器的关系
    • 2. 镜像通常比较小
    • 3. 拉取镜像
    • 4. 镜像命名
      • 4.1. 镜像仓库服务
      • 4.2. 官方和非官方镜像仓库
      • 4.3. 镜像的命名和标签
    • 5. 为镜像打多个标签
    • 6. 过滤镜像内容
      • 6.1. 虚空镜像
      • 6.2. 删除虚空镜像
      • 6.3. 过滤器与格式化输出
    • 7. 搜索Docker Hub中的仓库
    • 8. 镜像分层
      • 8.1. 镜像和分层
      • 8.2. 共享镜像层
    • 9. 镜像散列值
      • 9.1. 根据摘要拉取镜像
      • 9.2. 镜像散列值(摘要)
      • 9.3. 压缩散列值
    • 10. 删除镜像
  • 三. 多架构镜像:支持多架构和多平台
  • 四. 镜像:命令

一. Docker镜像简介

Docker镜像就像停止运行的容器;我们可以将镜像理解为类(Class)​。镜像需要从镜像仓库服务中拉取镜像。常见的镜像仓库服务是DockerHub,但是也存在其他镜像仓库服务。拉取操作会将镜像下载到本地 Docker主机。

镜像是多层的:

镜像由多个层组成,每层叠加之后,从外部看来就如一个独立的对象。镜像内部是一个精简的操作系统(OS)​,同时还包含应用运行所必须的文件和依赖包。因为容器的设计初衷就是快速和小巧,所以镜像通常都比较小。

构建时结构

我们可以停止某个容器的运行,并从中创建新的镜像(会保存当前执行的环境状况)。在该前提下,镜像可以理解为一种构建时(build-time)结构,而容器可以理解为一种运行时(run-time)结构,如图:
 
在这里插入图片描述

 

 

二. Docker镜像详解

1. 镜像和容器的关系

我们可以使用docker container run命令从某个镜像启动一个或多个容器。一旦容器从镜像启动后,二者之间就变成了互相依赖的关系,并且在镜像上启动的容器全部停止之前,镜像是无法被删除的。

尝试删除镜像而不停止或销毁使用它的容器,会导致下面的错误。

$ docker image rm 

Error response from daemon: conflict: unable to remove repository reference \ "" (must force) - container is using its referenc\ ed image

 

2. 镜像通常比较小

容器追求快速和小巧,这意味着构建镜像的时候通常需要裁剪掉不必要的部分,保持较小的体积,比如:

  1. Docker镜像通常不会包含6个不同的Shell让读者选择:通常Docker镜像中只有一个精简的Shell,甚至没有Shell。
  2. 镜像不包含内核:容器都是共享所在Docker主机的内核(如cgroups和namespaces)。所以容器仅包含必要的操作系统(通常只有操作系统文件和文件系统对象)​。

 

3. 拉取镜像

查看主机镜像列表
Docker主机安装之后,本地并没有镜像。使用以下命令检查Docker主机的本地仓库中是否包含镜像。

% docker image ls 

REPOSITORY                  TAG         IMAGE ID       CREATED         SIZE
langgenius/dify-web         0.6.11      03ed4f2b51ea   8 weeks ago     229MB
langgenius/dify-api         0.6.11      38532784de04   8 weeks ago     2.55GB
...

通过下面的命令可以将镜像拉取到本地。

$ docker image pull ubuntu:latest

latest: Pulling from library/ubuntu

 

4. 镜像命名

4.1. 镜像仓库服务

Docker镜像存储在镜像仓库服务(Image Registry)当中。Docker客户端的镜像仓库服务是可配置的,默认使用Docker Hub。

镜像仓库服务包含多个镜像仓库(Image Repository)​。同样,一个镜像仓库中可以包含多个镜像。如下图展示了包含3个镜像仓库的镜像仓库服务,其中每个镜像仓库都包含一个或多个镜像。

 

4.2. 官方和非官方镜像仓库

Docker Hub也分为官方仓库(Official Repository)和非官方仓库(Unofficial Repository)​。

在这里插入图片描述

官方仓库中的镜像是由Docker公司审查的。这意味着其中的镜像会及时更新,由高质量的代码构成​。这些代码是安全的,有完善的文档和最佳实践。

大部分流行的操作系统和应用在Docker Hub的官方仓库中都有其对应镜像。这些镜像很容易找到,基本都在Docker Hub命名空间的顶层。

 

4.3. 镜像的命名和标签

只需要给出镜像的名字和标签,就能在官方仓库中定位一个镜像(采用“:”分隔)​。docker image pull命令的格式如下。

docker image pull <repository>:<tag>

$ docker image pull mongo:3.3.11 //该命令会从官方Mongo库拉取标签为3.3.11的镜像 
$ docker image pull redis:latest //该命令会从官方Redis库拉取标签为latest的镜像 
$ docker image pull alpine //该命令会从官方Alpine库拉取标签为latest的镜像
$ docker image pull nigelpoulton/tu-demo:v2 
//该命令会从以我自己的Docker Hub账号为命名空间的tu-demo库中下载标签为v2的镜像

注意:如果没有指定镜像标签,则Docker会拉取标签为latest的镜像。但标有latest标签的镜像不保证这是仓库中最新的镜像!例如,Alpine仓库中最新的镜像通常标签是edge。通常来讲,使用latest标签时需要谨慎!

 

5. 为镜像打多个标签

一个镜像可以根据用户需要设置多个标签,如下

# 指定 -a 参数来拉取仓库中的全部镜像。
$ docker image pull -a nigelpoulton/tu-demo

...

$ docker image ls
REPOSITORY              TAG     IMAGE ID       CREATED     SIZE
nigelpoulton/tu-demo     v2     6ac21e..bead   1 yr ago    211.6 MB
nigelpoulton/tu-demo     latest 9b915a..1e29   1 yr ago    211.6 MB
nigelpoulton/tu-demo     v1     9b915a..1e29   1 yr ago    211.6 MB

# 该命令从nigelpoulton/tu-demo仓库拉取了3个镜像:latest、v1以及v2。

注意看IMAGE ID这一列。只有两个不同的Image ID。这里实际只下载了两个镜像,其中有两个标签指向了相同的镜像。换句话说,其中一个镜像拥有两个标签。

 

6. 过滤镜像内容

Docker提供–filter参数过滤镜像内容。如下只会返回悬虚(dangling)镜像。

docker image ls --filter dangling=true

REPOSITORY    TAG       IMAGE ID       CREATED      SIZE
<none>        <none>    4fd34165afe0   7 days ago   14.5MB

 

6.1. 虚空镜像

那些没有标签的镜像被称为悬虚镜像,在列表中展示为<none>:<none>。通常出现这种情况,是因为构建了一个新镜像,然后为该镜像打了一个已经存在的标签。当此情况出现,Docker会构建新的镜像,接着移除旧镜像上面的标签,将该标签标在新的镜像之上。

例如

  1. 基于alpine:3.4构建一个新的镜像,并打上dodge:challenger标签。
  2. 更新Dockerfile,并构建一个新的镜像,并且标签为dodge:challenger,这时docker会移除旧镜像上面对应的标签,旧镜像就变成了悬虚镜像。

 

6.2. 删除虚空镜像

可以通过docker image prune命令移除全部的悬虚镜像。如果添加了-a参数,Docker会额外移除没有被使用的镜像(那些没有被任何容器使用的镜像)​。

 

6.3. 过滤器与格式化输出

  • dangling:可以指定true或者false,仅返回悬虚镜像(true)​,或者非悬虚镜像(false)​。
  • before:返回指定镜像之前被创建的全部镜像。
  • since:返回指定镜像之后创建的全部镜像。
  • label:根据标注(label)的名称或者值,对镜像进行过滤。
docker image ls --filter reference="*:latest"
REPOSITORY   TAG      IMAGE ID        CREATED      SIZE
alpine       latest   3fd9065eaf02    8 days ago   4.15MB
test         latest   8426e7efb777    3 days ago   122MB

 

可以使用--format对输出内容进行格式化。

# 例如,只返回Docker主机上镜像的大小属性。
 docker image ls --format "{{.Size}}"
99.3MB
111MB
82.6MB
88.8MB
4.15MB
108MB

# 返回仓库名,标签、大小
docker image ls --format "{{.Repository}}: {{.Tag}}: {{.Size}}"
dodge:  challenger: 99.3MB
ubuntu: latest:     111MB
python: 3.4-alpine: 82.6MB
python: 3.5-alpine: 88.8MB
alpine: latest:     4.15MB
nginx:  latest:     108MB

 

7. 搜索Docker Hub中的仓库

简单模式下,该命令会搜索所有“NAME”字段中包含特定字符串的仓库。例如,下面的命令会查找所有“NAME”包含“nigelpoulton”的仓库。

$ docker search nigelpoulton
NAME                         DESCRIPTION                STARS    AUTOMATED
nigelpoulton/pluralsight..   Web app used in...         8        [OK]
nigelpoulton/tu-demo                                    7
nigelpoulton/k8sbook         Kubernetes Book web app    1
nigelpoulton/web-fe1         Web front end example      0
nigelpoulton/hello-cloud     Quick hello-world image    0

 

8. 镜像分层

8.1. 镜像和分层

一个Docker镜像由一些松耦合的只读镜像层组成。Docker负责堆叠这些镜像层,并且将它们表示为单个统一的对象:即Docker镜像。

在这里插入图片描述

 

通过pull来查看仓库的分层。可以看到,这个镜像包含5个镜像层。

$ docker image pull ubuntu:latest
latest: Pulling from library/ubuntu
952132ac251a: Pull  complete
82659f8f1b76: Pull  complete
c19118ca682d: Pull  complete
8296858250fe: Pull  complete
24e0251a0e2c: Pull complete
...
# 在上面输出内容中,以Pull complete结尾的每一行都代表了镜像中某个被拉取的镜像层。

 

8.2. 共享镜像层

多个镜像之间会共享镜像层。这样可以有效节省空间并提升性能。如下例子

$ docker image pull -a nigelpoulton/tu-demo

latest: Pulling from nigelpoulton/tu-demo
...

v2: Pulling from nigelpoulton/tu-demo
237d5fcd25cf: Already exists
a3ed95caeb02: Already exists
<Snip>
eab5aaac65de: Pull complete
Digest: sha256:d3c0d8c9d5719d31b79c...fef58a7e038cf0ef2ba5eb74c

Status: Downloaded newer image for nigelpoulton/tu-demo

$ docker image ls
REPOSITORY             TAG      IMAGE ID       CREATED        SIZE
nigelpoulton/tu-demo   v2       6ac...ead   4 months ago   211.6 MB
nigelpoulton/tu-demo   latest   9b9...e29   4 months ago   211.6 MB
nigelpoulton/tu-demo   v1       9b9...e29   4 months ago   211.6 MB

Docker很聪明,可以识别出要拉取的镜像中,哪几层已经在本地存在。

Docker在Linux上支持很多存储引擎(Snapshotter)​。每个存储引擎都有自己的镜像分层、镜像层共享以及写时复制(CoW)技术的具体实现。但是,其最终效果和用户体验是完全一致的。

 

9. 镜像散列值

9.1. 根据摘要拉取镜像

如果出现给镜像打错标签的情况,有时甚至会给新镜像打一个已经存在的标签。

如下描述一个存在的问题

假设镜像golftrack:1.5存在一个已知的Bug。因此可以拉取该镜像后修复它,并使用相同的标签将更新的镜像重新推送回仓库。此时原镜像被覆盖,但在生产环境中遗留了大量运行中的容器,没有什么好办法区分正在使用的镜像版本是修复前还是修复后的,因为两个镜像的标签是相同的!

 

摘要
每一个镜像都会有有一个基于其内容的密码散列值即摘要。所以当镜像内容变更时,散列值一定会改变。这种方式可以解决前面讨论的问题。

在docker image ls命令之后添加--digests参数即可在本地查看镜像摘要。如下

# 拉取镜像
$ docker image pull alpine
Using default tag: latest
。。。
Digest: sha256:3dcdb92d7432d56604d...6d99b889d0626de158f73a

# 显示摘要
$ docker image ls --digests alpine
REPOSITORY  TAG     DIGEST              IMAGE ID      CREATED        SIZE
alpine      latest  sha256:3dcd...f73a  4e38e38c8ce0  10 weeks ago   4.8 MB

目前原生Docker命令不支持从远端镜像仓库服务(如Docker Hub)中获取镜像签名了。这意味着只能先通过标签方式拉取镜像到本地,然后自己维护镜像的摘要列表。
 

下面的例子首先在Docker主机上删除alpine:latest镜像,然后显示如何通过摘要来再次拉取该镜像。

$ docker image rm alpine:latest
Untagged: alpine:latest
Untagged: alpine@sha256:c0537...7c0a7726c88e2bb7584dc96
Deleted: sha256:02674b9cb179d...abff0c2bf5ceca5bad72cd9
Deleted: sha256:e154057080f40...3823bab1be5b86926c6f860

$ docker image pull alpine@sha256:c0537...7c0a7726c88e2bb7584dc96
sha256:c0537...7726c88e2bb7584dc96: Pulling from library/alpine
cfc728c1c558: Pull complete
Digest: sha256:c0537ff6a5218...7c0a7726c88e2bb7584dc96
Status: Downloaded newer image for alpine@sha256:c0537...bb7584dc96

 

9.2. 镜像散列值(摘要)

镜像本身是一个配置对象,其中包含了镜像层的列表以及一些元数据信息。镜像层才是实际数据存储的地方(比如文件等,镜像层之间是完全独立的,并没有从属于某个镜像集合的概念)​。

镜像的唯一标识是一个加密ID,即配置对象本身的散列值。每个镜像层也由一个加密ID区分,其值为镜像层本身内容的散列值。

这意味着修改镜像的内容或其中任意的镜像层,都会导致加密散列值的变化。

 

9.3. 压缩散列值

我们再看一个场景:在推送和拉取镜像的时候,都会对镜像层进行压缩来节省网络带宽以及仓库二进制存储空间。

例如,在推送镜像层到Docker Hub的时候,Docker Hub会尝试确认接收到的镜像没有在传输过程中被篡改。为了完成校验,Docker Hub会根据镜像层重新计算散列值,并与原散列值进行比较。因为镜像在传输过程中被压缩​,所以散列值的校验也会失败。为避免该问题,每个镜像层同时会包含一个分发散列值(DistributionHash)​。这是一个压缩版镜像的散列值,当从镜像仓库服务拉取或者推送镜像的时候,其中就包含了分发散列值,该散列值会用于校验拉取的镜像是否被篡改过

这个内容寻址存储模型极大地提升了镜像的安全性,因为在拉取和推送操作后提供了一种方式来确保镜像和镜像层数据是一致的。

 

10. 删除镜像

删除操作会在当前主机上删除该镜像以及相关的镜像层。

$ docker image rm 02674b9cb179
Untagged: alpine@sha256:c0537ff6a5218...c0a7726c88e2bb7584dc96
Deleted: sha256:02674b9cb179d57...31ba0abff0c2bf5ceca5bad72cd9
Deleted: sha256:e154057080f4063...2a0d13823bab1be5b86926c6f860

注意:

  1. 如果某个镜像层被多个镜像共享,那只有当全部依赖该镜像层的镜像都被删除后,该镜像层才会被删除。
  2. 如果被删除的镜像上存在运行状态的容器,那么删除操作不会被允许。

 

一种删除某Docker主机上全部镜像的快捷方式是在docker image rm命令中传入当前系统的全部镜像ID,可以通过docker image ls获取全部镜像ID(使用-q参数)​。

$ docker image rm $(docker image ls -q) -f
# -q:只返回了系统中本地拉取的全部镜像的ID列表

谨慎使用!!!

 

三. 多架构镜像:支持多架构和多平台

读者会突然发现,在拉取镜像并运行之前,需要考虑镜像是否与当前运行环境的架构匹配,这破坏了Docker的流畅体验。多架构镜像(Multi-architecture Image)的出现解决了这个问题!这意味着某个镜像仓库标签(repository:tag)下的镜像可以同时支持64位Linux、PowerPC Linux、64位Windows和ARM等多种架构。简单地说,就是一个镜像标签之下可以支持多个平台和架构

 

为了实现这个特性,镜像仓库服务API支持两种重要的结构:Manifest列表(新)和Manifest。

Manifest列表是指某个镜像标签支持的架构列表。其支持的每种架构,都有自己的Mainfest定义,其中列举了该镜像的构成。

如下图:使用Golang官方镜像作为示例。图左侧是Manifest列表,其中包含了该镜像支持的每种架构。Manifest列表的每一项都有一个箭头,指向具体的Manifest,其中包含了镜像配置和镜像层数据。
在这里插入图片描述

这里:不需要告知Docker具体的镜像版本是64位Linux还是64位Windows。

$ docker container run --rm golang go version

Unable to find image 'golang:latest' locally
latest: Pulling from library/golang
723254a2c089: Pull complete
<Snip>
39cd5f38ffb8: Pull complete
Digest: sha256:947826b5b6bc4...
Status: Downloaded newer image for golang:latest
go version go1.9.2 linux/amd64

 

四. 镜像:命令

命令说明
docker image pull1. 镜像从远程镜像仓库服务的仓库中下载。
2. 默认情况下,镜像会从Docker Hub的仓库中拉取。
docker image ls列出了本地Docker主机上存储的镜像。可以通过–digests参数来查看镜像的SHA256签名。
docker image inspect展示了镜像的细节,包括镜像层数据和元数据。
docker image rm用于删除镜像。docker image rm alpine:latest命令的含义是删除alpine:latest镜像。当镜像存在关联的容器,并且容器处于运行(Up)或者停止(Exited)状态时,不允许删除该镜像。

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

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

相关文章

【C++题解】1004 - 编程求1*2*3*...*n

欢迎关注本专栏《C从零基础到信奥赛入门级&#xff08;CSP-J&#xff09;》 问题&#xff1a;1004 - 编程求1 * 2 * 3 * … * n 类型&#xff1a;简单循环 题目描述&#xff1a; 编程求 123⋯n 。 输入&#xff1a; 输入一行&#xff0c;只有一个整数 n(1≤n≤10)&#xf…

监狱单位如何选择适合的FTP传输替代方案?

监狱单位是我国司法体系中的重要组成部分&#xff0c;监狱对于维持社会稳定也有重要作用。监狱的正常运作中&#xff0c;少不了文件的传输。由于监狱的封闭性和特殊性&#xff0c;所有传输到监狱的文件都需要经过严格的审核和登记手续&#xff0c;以确保文件的安全性和合法性。…

Linux 进程介绍

今天给伙伴们分享一下Linux 进程介绍&#xff0c;希望看了有所收获。 我是公众号「想吃西红柿」「云原生运维实战派」作者&#xff0c;对云原生运维感兴趣&#xff0c;也保持时刻学习&#xff0c;后续会分享工作中用到的运维技术&#xff0c;在运维的路上得到支持和共同进步&am…

HBase原理和操作

目录 一、HBase在Zookeeper中的存储元数据信息集群状态信息 二、HBase的操作Web Console命令行操作 三、HBase中数据的保存过程 一、HBase在Zookeeper中的存储 元数据信息 HBase的元数据信息是HBase集群运行所必需的关键数据&#xff0c;它存储在Zookeeper的"/hbase&quo…

C++学习笔记----3、设计专业的C++程序(六)---- 重用既有代码(选择库重用指导一)

当你决定使用库、框架、同事的代码、整个应用或者你自己的代码的时候&#xff0c;要记住选择正确的代码重用的几个指导原则。 1、理解功能与限制 要花时间去熟悉代码。理解其功能与限制还是很重要的。开始阅读文档与公开接口或API。理想情况下&#xff0c;有这些去理解怎么使用…

chromedriver下载地址大全(包括124.*后)以及替换exe后仍显示版本不匹配的问题

Chrome for Testing availability CNPM Binaries Mirror 若已经更新了系统环境变量里的chromdriver路径下的exe&#xff0c;仍显示版本不匹配&#xff1a; 则在cmd界面输入 chromedriver 会跳出version verison与刚刚下载好的exe不匹配&#xff0c;则再输入&#xff1a; w…

使用 Python 绘制词云图的详细教程

如何使用python绘制词云图 词云图&#xff08;Word Cloud&#xff09;是数据可视化中常用的一种技术&#xff0c;通过将文字以不同的大小、颜色和方向排列&#xff0c;以展示文本数据中词汇的频次和重要性。对于文本分析、情感分析、关键词提取等应用&#xff0c;词云图都能够…

软件设计师教程(第5版)第3章 数据结构(更新中)

【数据结构】是指数据元素的集合及元素间的相互关系和构造方法。P99 元素之间的相互关系是数据的【逻辑结构】。P99 数据元素及元素之间关系的存储称为【存储结构】(或【物理结构】)。P99 数据结构按照【逻辑关系】的不同分为【线性结构】和【非线性结构】两大类。P99 【非…

计算机组成原理(4):指令系统/控制器

1 指令格式 【补充知识】 计算机语言的层级关系&#xff1a;机器语言 - 汇编语言 - 高级语言&#xff1b; ​ 机器语言用二进制来编写&#xff0c;用来反映硬件的语言。但是二进制编写太难了&#xff0c;就诞生了汇编语言&#xff0c;对其编程进行封装、简化&#xff1b; ​ …

C++ | Leetcode C++题解之第357题统计各位数字都不同的数字个数

题目&#xff1a; 题解&#xff1a; class Solution { public:int countNumbersWithUniqueDigits(int n) {if (n 0) {return 1;}if (n 1) {return 10;}int ans 10, cur 9;for (int i 0; i < n - 1; i) {cur * 9 - i;ans cur;}return ans;} };

8.Java基础概念-方法

欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 Facts speak louder than words&#xff01; 什么是方法 方法是程序…

QT 与 C++实现基于[ TCP ]的聊天室界面

TCP客户端 Widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QTcpSocket> //客户端类 #include <QMessageBox> #include <QListWidgetItem> #include <QDebug>QT_BEGIN_NAMESPACE namespace Ui { class Widget; } …

基于YOLO V8的PCB缺陷检测识别系统(python源码+Pyqt5界面+数据集+训练代码)

数据集准备&#xff1a;收集并标注PCB缺陷的图像。模型训练&#xff1a;使用YOLO v8框架训练一个模型来识别这些缺陷。GUI开发&#xff1a;利用PyQt5创建一个用户友好的图形界面。模型部署&#xff1a;在GUI中集成训练好的模型&#xff0c;使用户能够上传PCB图像并得到缺陷检测…

数据结构-树(二叉树)-第三天

结合leetcode学习c 学习资料来源 定义 二叉树&#xff08;binary tree&#xff09;是一种非线性数据结构&#xff0c;代表“祖先”与“后代”之间的派生关系&#xff0c;体现了“一分为二”的分治逻辑。 与链表类似&#xff0c;二叉树的基本单元是节点&#xff0c;每个节点包含…

[数据集][目标检测]停车场空位检测数据集VOC+YOLO格式7959张2类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;7959 标注数量(xml文件个数)&#xff1a;7959 标注数量(txt文件个数)&#xff1a;7959 标注…

p9 镜像的基本命令

docker的常用命令 帮助命令 查看docker的版本 docker version2. 查看当前安装的docker的详细的信息 docker的系统信息包括镜像和容器的数量 docker info3. 查询帮助命令 image是你想要获取哪一个命令的帮助文档,一般百度或者人工智能就行所有命令的可选项都可以用这个–hel…

DN专业3D图形制作软件win/mac软件安装下载(附下载链接)

目录 一、软件概述 1.1 Adobe DN简介 1.2 Windows/Mac系统要求 Windows系统&#xff1a; Mac系统&#xff1a; 二、安装步骤 2.1 下载与解压 2.2 安装程序 2.3 启动软件 三、使用教程 3.1 界面介绍 3.2 创建和编辑3D内容 3.3 合成与渲染 四、高级技巧与注意事项 …

.NET内网实战:通过DNS查找出网主机

01阅读须知 此文所节选自小报童《.NET 内网实战攻防》专栏&#xff0c;主要内容有.NET在各个内网渗透阶段与Windows系统交互的方式和技巧&#xff0c;对内网和后渗透感兴趣的朋友们可以订阅该电子报刊&#xff0c;解锁更多的报刊内容。 02基本介绍 03编码实现 在红队活动中&…

Modbus 数据帧解析

Modbus 是一种通信协议&#xff0c;广泛应用于工业自动化系统中&#xff0c;用于连接电子设备。它是一种基于主从结构的通信协议&#xff0c;其中主设备可以与多个从设备通信。数据通过一系列的帧进行传输&#xff0c;每一帧包含多个字段&#xff0c;每个字段都有特定的功能。 …

SQL进阶技巧:最近有效的缺失值填充问题【last_value实现版】

目录 0 场景描述 1 数据准备 2 问题分析 3 小结 0 场景描述 场景:现在有一张商品入库表,包括商品id、商品成本和入库日期3个字段,由于某些原因,导致部分商品的成本缺失(为0或者没有值都是缺失),这样不利于我们计算成本。所以现在要把缺失的商品进价补充完整,补充的…