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

【Docker】Dockerfile使用技巧

在这里插入图片描述

开启Buildkit

BuildKit是Docker官方社区推出的下一代镜像构建神器,可以更加快速,有效,安全地构建docker镜像。

尽管目前BuildKit不是Docker的默认构建工具,但是完全可以考虑将其作为Docker(v18.09+)的首选构建工具。

官方文档:https://docs.docker.com/build/buildkit/

下面介绍一下怎么开启BuildKit。

/etc/docker/daemon.json里添加(如果没有这个文件,则新建), 然后重启docker

{ "features": { "buildkit": true } }

或者在执行docker build命令时设置

$ DOCKER_BUILDKIT=1 docker build .

镜像的选择

可以前往官网学习官方的镜像怎么制作的:https://github.com/docker-library/official-images

基础镜像的选择原则:

  • 官方镜像优于非官方的镜像,如果没有官方镜像,则尽量选择Dockerfile开源的。
  • 固定版本tag而不是每次都使用latest
  • 尽量选择体积小的镜像

下面的镜像列表中,都是jre8的镜像,但是由于基础的镜像不同导致最终镜像大小不同。

$ docker image ls
REPOSITORY        TAG             IMAGE ID       CREATED         SIZE
eclipse-temurin   8-jre-jammy     ec4a8981544b   6 days ago      223MB
eclipse-temurin   8-jre-focal     e588bf105eb7   3 weeks ago     227MB
eclipse-temurin   8-jre-alpine    f7a454a165ae   3 weeks ago     135MB
eclipse-temurin   8-jre-centos7   e5b6f35176e9   23 months ago   350MB
openjdk           8-jre-alpine    f7a292bbb70c   4 years ago     84.9MB

Jammy和Focal:这两个都是Ubuntu的版本代号。"Focal"对应的是Ubuntu 20.04 LTS(长期支持版),"Jammy"对应的则是更加新的Ubuntu版本。Ubuntu是一个非常受欢迎的Linux发行版,因为它既有强大的功能,又有着广大的用户和开发者社区。

Alpine:Alpine Linux是一个面向安全、简单和轻量级的Linux发行版,它的镜像大小通常远小于基于 Ubuntu或其他发行版的镜像。这使得它非常适合于Docker镜像,因为小的镜像可以更快地被拉取和部署。

AdoptOpenJDK停止发布OpenJDK二进制,而Eclipse Temurin是它的延伸,提供更好的稳定性。

减少镜像的分层

例如下面的镜像:

from centos:7label author=morirsenv WORK_DIR /usr/localarg version=6.2.5workdir $WORK_DIRADD redis-${version}.tar.gz .run yum -y update
run yum install -y wget gcc gcc-c++ automake autoconf libtool make
run make -C redis-${version}expose 6379env REDIS_HOME $WORK_DIR/redis-6.2.5env PATH $PATH:$REDIS_HOME/srcentrypoint ["redis-server"]

查询镜像的分层:

$ docker image history redis:6.2.5.1
IMAGE          CREATED             CREATED BY                                      SIZE      COMMENT
444f31557106   57 seconds ago      ENTRYPOINT ["redis-server"]                     0B        buildkit.dockerfile.v0
<missing>      57 seconds ago      ENV PATH=/usr/local/sbin:/usr/local/bin:/usr…   0B        buildkit.dockerfile.v0
<missing>      57 seconds ago      ENV REDIS_HOME=/usr/local/redis-6.2.5           0B        buildkit.dockerfile.v0
<missing>      57 seconds ago      EXPOSE map[6379/tcp:{}]                         0B        buildkit.dockerfile.v0
<missing>      57 seconds ago      RUN |1 version=6.2.5 /bin/sh -c make -C redi…   122MB     buildkit.dockerfile.v0
<missing>      About an hour ago   RUN |1 version=6.2.5 /bin/sh -c yum install …   302MB     buildkit.dockerfile.v0
<missing>      About an hour ago   RUN |1 version=6.2.5 /bin/sh -c yum -y updat…   358MB     buildkit.dockerfile.v0
<missing>      About an hour ago   ADD redis-6.2.5.tar.gz . # buildkit             10.4MB    buildkit.dockerfile.v0
<missing>      2 hours ago         WORKDIR /usr/local                              0B        buildkit.dockerfile.v0
<missing>      2 hours ago         ARG version=6.2.5                               0B        buildkit.dockerfile.v0
<missing>      2 hours ago         ENV WORK_DIR=/usr/local                         0B        buildkit.dockerfile.v0
<missing>      2 hours ago         LABEL author=morirs                             0B        buildkit.dockerfile.v0
<missing>      2 years ago         /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B
<missing>      2 years ago         /bin/sh -c #(nop)  LABEL org.label-schema.sc…   0B
<missing>      2 years ago         /bin/sh -c #(nop) ADD file:b3ebbe8bd304723d4…   204MB

每一行的RUN命令都会产生一层image layer, 导致镜像的臃肿。

修改为如下:

from centos:7label author=morirsenv WORK_DIR /usr/localarg version=6.2.5workdir $WORK_DIRADD redis-${version}.tar.gz .run yum -y update \&& yum install -y wget gcc gcc-c++ automake autoconf libtool make \&& run make -C redis-${version}expose 6379env REDIS_HOME $WORK_DIR/redis-6.2.5env PATH $PATH:$REDIS_HOME/srcentrypoint ["redis-server"]

新的镜像分层如下:

$ docker history redis:6.2.5.2
IMAGE          CREATED          CREATED BY                                      SIZE      COMMENT
fa6f23e424bc   30 seconds ago   ENTRYPOINT ["redis-server"]                     0B        buildkit.dockerfile.v0
<missing>      30 seconds ago   ENV PATH=/usr/local/sbin:/usr/local/bin:/usr…   0B        buildkit.dockerfile.v0
<missing>      30 seconds ago   ENV REDIS_HOME=/usr/local/redis-6.2.5           0B        buildkit.dockerfile.v0
<missing>      30 seconds ago   EXPOSE map[6379/tcp:{}]                         0B        buildkit.dockerfile.v0
<missing>      30 seconds ago   RUN |1 version=6.2.5 /bin/sh -c yum -y updat…   593MB     buildkit.dockerfile.v0
<missing>      2 hours ago      ADD redis-6.2.5.tar.gz . # buildkit             10.4MB    buildkit.dockerfile.v0
<missing>      2 hours ago      WORKDIR /usr/local                              0B        buildkit.dockerfile.v0
<missing>      2 hours ago      ARG version=6.2.5                               0B        buildkit.dockerfile.v0
<missing>      2 hours ago      ENV WORK_DIR=/usr/local                         0B        buildkit.dockerfile.v0
<missing>      2 hours ago      LABEL author=morirs                             0B        buildkit.dockerfile.v0
<missing>      2 years ago      /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B
<missing>      2 years ago      /bin/sh -c #(nop)  LABEL org.label-schema.sc…   0B
<missing>      2 years ago      /bin/sh -c #(nop) ADD file:b3ebbe8bd304723d4…   204MB

镜像的大小变化如下:

$ docker image ls
REPOSITORY        TAG             IMAGE ID       CREATED              SIZE
redis             6.2.5.2         fa6f23e424bc   About a minute ago   807MB
redis             6.2.5.1         444f31557106   15 minutes ago       996MB

合理使用缓存

在构建的时候尽量将不变的结构放在Dockerfile的前面,经常变化的结构放在Dockerfile的后面,这样构建的时候不变的部分层构建过了就无需再次构建,节约时间,可以在构建的日志中看到CACHED

s$ docker image build -f redis.dockerfile2 -t redis:6.2.5.2 .
[+] Building 268.3s (9/9) FINISHED=> [internal] load build definition from redis.dockerfile2                                                                                0.0s=> => transferring dockerfile: 412B                                                                                                       0.0s=> [internal] load .dockerignore                                                                                                          0.0s=> => transferring context: 2B                                                                                                            0.0s=> [internal] load metadata for docker.io/library/centos:7                                                                                0.0s=> [1/4] FROM docker.io/library/centos:7                                                                                                  0.0s=> [internal] load build context                                                                                                          0.0s=> => transferring context: 42B                                                                                                           0.0s=> CACHED [2/4] WORKDIR /usr/local                                                                                                        0.0s=> CACHED [3/4] ADD redis-6.2.5.tar.gz .                                                                                                  0.0s=> [4/4] RUN yum -y update  && yum install -y wget gcc gcc-c++ automake autoconf libtool make  && make -C redis-6.2.5                   265.0s=> exporting to image                                                                                                                     3.2s=> => exporting layers                                                                                                                    3.2s=> => writing image sha256:fa6f23e424bc6088f6cc84d5ff67ae1376f18fbc906e14b670bc3e4c316046e6                                               0.0s=> => naming to docker.io/library/redis:6.2.5.2                                                                                           0.0s

合理使用.dockerignore

Docker是client-server架构,理论上Client和Server可以不在一台机器上。

在构建docker镜像的时候,需要把所需要的文件由CLI(client)发给Server,这些文件实际上就是build context。

举例:

$ cat redis6.2.6.dockerfile
from centos:7label author=morirsenv WORK_DIR /usr/localarg version=6.2.6workdir $WORK_DIRCOPY . .run tar -zxvf redis-${version}.tar.gz
run yum -y update
run yum install -y wget gcc gcc-c++ automake autoconf libtool make
run make -C redis-${version}expose 6379env REDIS_HOME $WORK_DIR/redis-6.2.5env PATH $PATH:$REDIS_HOME/srcentrypoint ["redis-server"]

构建目录下的文件:

total 4848
drwxrwxr-x 2 morris morris    4096 Sep 19 19:30 ./
drwxrwxr-x 4 morris morris    4096 Sep 18 10:00 ../
-rw-rw-r-- 1 morris morris 2465302 Jul 22  2021 redis-6.2.5.tar.gz
-rw-rw-r-- 1 morris morris 2476542 Oct  4  2021 redis-6.2.6.tar.gz
-rw-rw-r-- 1 morris morris     356 Sep 18 11:28 redis.dockerfile
-rw-rw-r-- 1 morris morris     360 Sep 18 11:39 redis.dockerfile2
-rw-rw-r-- 1 morris morris     373 Sep 19 19:30 redis6.2.6.dockerfile

构建的时候,第一行输出就是发送build context大小为4.947MB,这里包含了不需要的文件redis-6.2.5.tar.gz

$ docker image build -f redis6.2.6.dockerfile -t redis:6.2.6.1 .
Sending build context to Docker daemon  4.947MB
Step 1/14 : from centos:7---> eeb6ee3f44bd

编写.dockerignore文件,忽略掉不需要的文件,然后放到docker构建上下文的根路径下。

$ docker image build -f redis6.2.6.dockerfile -t redis:6.2.6.1 .
Sending build context to Docker daemon  2.482MB
Step 1/14 : from centos:7---> eeb6ee3f44bd

再次构建build context大小变为2.482MB

镜像的多阶段构建

假如有一个C的程序,我们想用Docker去做编译,然后执行可执行文件。

#include <stdio.h>void main(int argc, char *argv[])
{printf("hello %s\n", argv[argc - 1]);
}

构建一个Docker镜像,因为要有C的环境,所以我们选择gcc这个image

FROM gcc:9.4COPY hello.c /src/hello.cWORKDIR /srcRUN gcc --static -o hello hello.cENTRYPOINT [ "/src/hello" ]CMD []

build和测试:

$ docker image build -f c.dockerfile -t hello:1.0 .
... ...$ docker container run --rm -it hello:1.0 hello
hello hello$ docker image ls
REPOSITORY        TAG             IMAGE ID       CREATED          SIZE
hello             1.0             93b8a1824b80   45 seconds ago   1.14GB

可以看到镜像非常的大,1.14GB

实际上当我们把hello.c编译完以后,并不需要这样一个大的GCC环境,一个小的alpine镜像就可以了。

这时候我们就可以使用多阶段构建了。

FROM gcc:9.4 AS builderCOPY hello.c /src/hello.cWORKDIR /srcRUN gcc --static -o hello hello.cFROM alpine:3.13.5COPY --from=builder /src/hello /src/helloENTRYPOINT [ "/src/hello" ]CMD []

构建和测试:

$ docker image build -f c2.dockerfile -t hello:2.0 .
... ...$ docker container run --rm -it hello:2.0 hi
hello hi$ docker image ls
REPOSITORY        TAG             IMAGE ID       CREATED          SIZE
hello             2.0             8127f3ac5ea6   4 seconds ago    6.55MB
hello             1.0             93b8a1824b80   45 seconds ago   1.14GB

可以看到这个镜像非常小,只有6.55MB。

尽量使用非root用户

Root的危险性

docker的root权限一直是其遭受诟病的地方,docker的root权限有那么危险么?我们举个例子。

假如我们有一个用户,叫morris,它本身不具有sudo的权限,所以就有很多文件无法进行读写操作,比如/root目录它是无法查看的。

$ ls /root
ls: cannot open directory '/root': Permission denied

但是这个用户有执行docker的权限,也就是它在docker这个group里。

$ groups
morris docker

这时,我们就可以通过Docker做很多越权的事情了,比如,我们可以把这个无法查看的/root目录映射到docker container里,你就可以自由进行查看了。

$ docker container run -it --rm -v /root:/root/tmp centos:7 bash
[root@9cc0d1275a15 /]# ls /root/tmp
snap

更甚至我们可以给我们自己加sudo权限:

$ docker container run -it --rm -v /etc/sudoers:/root/sudoers centos:7 bash
[root@744b21d23ba9 /]# echo "demo    ALL=(ALL)       ALL" >> /root/sudoers
[root@744b21d23ba9 /]# more /root/sudoers | grep demo
demo    ALL=(ALL)       ALL

然后退出container,morris用户已经有sudo权限了。

$ ls /etc/sudoers
/etc/sudoers

如何使用非root用户

通过groupadd和useradd创建一个nonroot的组和用户,通过USER指定后面的命令要以nonroot这个用户的身份运行

from centos:7label author=morirsenv WORK_DIR /usr/localarg version=6.2.5workdir $WORK_DIRADD redis-${version}.tar.gz .run yum -y update \&& yum install -y wget gcc gcc-c++ automake autoconf libtool make \&& make -C redis-${version} \&& groupadd -r nonroot \&& useradd -r -g nonroot nonroot \&& chown -R nonroot:nonroot $WORK_DIRUSER nonrootexpose 6379env REDIS_HOME $WORK_DIR/redis-6.2.5env PATH $PATH:$REDIS_HOME/srcentrypoint ["redis-server"]

相关文章:

【Docker】Dockerfile使用技巧

开启Buildkit BuildKit是Docker官方社区推出的下一代镜像构建神器&#xff0c;可以更加快速&#xff0c;有效&#xff0c;安全地构建docker镜像。 尽管目前BuildKit不是Docker的默认构建工具&#xff0c;但是完全可以考虑将其作为Docker&#xff08;v18.09&#xff09;的首选…...

一招解决“请在微信客户端中打开链接”

一招解决“请在微信客户端中打开链接”-遇见你与你分享 在浏览器访问网站&#xff0c;却提示“请在微信客户端打开链接”。虽然这个情况你可能从未遇到过&#xff0c;但对于爱折腾的小伙伴&#xff0c;确是一道拦路虎 其实解决办法很简单&#xff0c;就是新建一个UA&#xff1…...

Python循环语句(一)

目录 一.while循环1.while循环的基础语法2.while循环的嵌套应用3.while循环嵌套案例 一.while循环 1.while循环的基础语法 while循环注意点 while的条件需得到布尔类型&#xff0c;True表示继续循环&#xff0c;False表示结束循环需要设置循环终止的条件&#xff0c;如i 1配…...

期中考核复现

web 1z_php ?0o0[]1A&OoO[]2023a include "flag.php"&#xff1a;尝试包含名为 "flag.php" 的文件。这意味着它会尝试引入一个名为 "flag.php" 的脚本文件&#xff0c;其中可能包含一些敏感信息或标志。 error_reporting(0)&#xff1a;…...

基于XML的Web服务Java接口(JAX-WS)、Jakarta XML Web Services Eclipse 实现

简介 JAX-WS&#xff08;Java API for XML-Based Web Services&#xff09;&#xff0c;是创建web服务的Java编程接口&#xff0c;特别是SOAP服务。是Java XML编程接口之一&#xff0c;是Java SE 和Java EE 平台的一部分。 JAX-WS 2.0 规范是代替JAX-RPC 1.0的下一代Web服务AP…...

公网无信号区域远程抄表问题解决方案及产品选型

摘要&#xff1a;随着计量自动化系统的逐步完善&#xff0c;电网全用户表码信息采集成为系统数据得以深化应用的重要基础。利用无线公网通信是目前实现远程抄表的主要手段之一&#xff0c;但仍存在公网难以覆盖的偏远山区、公网信号屏蔽地下室或弱信号区域&#xff0c;无法实现…...

lunar-1.5.jar

公历农历转换包 https://mvnrepository.com/artifact/com.github.heqiao2010/lunar <!-- https://mvnrepository.com/artifact/com.github.heqiao2010/lunar --> <dependency> <groupId>com.github.heqiao2010</groupId> <artifactId>l…...

c++编译使用log4cplus

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、log4cplus是什么&#xff1f;二、使用步骤1.下载源代码2.开始配置1.配置介绍2.开始编译 3.cmake引用4.示例 总结 前言 C很强大&#xff0c;但是仍然有很多…...

zookeeper源码(02)源码编译启动及idea导入

本文介绍一下zookeeper-3.9.0源码下载、编译及本地启动。 下载源码 git clone https://gitee.com/apache/zookeeper.gitcd zookeeper git checkout release-3.9.0 git checkout -b release-3.9.0源码编译 README_packaging.md文件 该文件介绍了编译zookeeper需要的环境和命…...

Github 2FA绑定中国+86手机号码实现两步验证

GitHub宣布&#xff0c;到 2023 年底&#xff0c;所有用户都必须要启用双因素身份验证 (2FA)&#xff0c;不能只用密码. GitHub开启2FA后&#xff0c;除了输入密码外&#xff0c;还需要通过一次性密码&#xff08;OTP&#xff09;等方式做第二级身份验证&#xff0c;才能成功登…...

windows安装mysql-8.0.35

打开cmd(以管理员身份运行)&#xff0c;切换到mysql下的bin目录 mysqld --initialize 执行完毕之后&#xff0c;在data目录下会生成很多文件。 打开cmd(以管理员身份运行)&#xff0c;切换到mysql下的bin目录&#xff0c;如果刚才的cmd没有关闭&#xff0c;可以继续mysqld -…...

最详细STM32,cubeMX串口发送,接收数据

这篇文章将详细介绍 串口 发送数据&#xff0c;接受数据。 文章目录 前言一、串口的基础知识二、cubeMX 配置三、自动生成代码解析四、串口发送数据函数五、使用串口收发数据点亮 led重定向函数&#xff1a; 总结 前言 实验开发板&#xff1a;STM32F103C8T6。所需软件&#xf…...

Kafka入门04——原理分析

目录 01理解Topic和Partition Topic(主题) Partition(分区) 02理解消息分发 消息发送到分区 消费者订阅和消费指定分区 总结 03再均衡(rebalance) 再均衡的触发 分区分配策略 RangeAssignor(范围分区) RoundRobinAssignor(轮询分区) StickyAssignor(粘性分区) Re…...

k8s-----17、集群安全机制

1、集群安全机制概述 1.1 访问k8s的三个步骤 1、认证 2、鉴权(授权) 3、准入控制 进行访问的时候&#xff0c;过程中都需要经过apiserver&#xff0c;apiserver做统一协调&#xff0c;比如门卫。且访问过程中需要证书、token、或者用户名密码。如果需要访问pod&#xff0c;…...

蓝桥算法赛(铺地板)

问题描述 小蓝家要装修了&#xff0c;小蓝爸爸买来了很多块&#xff08;你可以理解为数量无限&#xff09; 23 规格的地砖&#xff0c;小蓝家的地板是 nm 规格的&#xff0c;小蓝想问你&#xff0c;能否用这些 23 的地砖铺满地板。 铺满地板&#xff1a;对于地板的每个区域&…...

浅谈AcrelEMS-GYM文体建筑能效管理解决方案-安科瑞 蒋静

1 概述 AcrelEMS-CA 文体建筑能效管理聚焦建筑的能量和信息的流向搭建平台解决方案。该系统解决方案集变电站综合自动化、电力监控、电能质量分析及治理、电气安全、能耗分析、照明控制、设备运维于一体。打破子系统孤立&#xff0c;配置方便&#xff0c;运维便捷&#xff1b;…...

在LayerUI中使用onChange事件监听复选框的值变化

在LayerUI中&#xff0c;你可以使用onChange事件监听复选框的值变化。当复选框的状态发生变化时&#xff0c;onChange事件会被触发。 以下是一个示例代码&#xff0c;演示了如何使用onChange事件监听复选框的值变化&#xff1a; jsx import React from react; import { Chec…...

决策树--ID3算法

决策树–ID3算法 概念 &#xff08;1&#xff09;信息熵 E n t r o p y ( x ) − ∑ i N c l a s s P ( x i ) l o g 2 P ( x i ) Entropy(x) -\sum_{i}^{N_{class}}P(x_i)log_2 P(x_i) Entropy(x)−i∑Nclass​​P(xi​)log2​P(xi​) 假设只有2个类别&#xff08;N2&…...

js延时加载有哪些方式

...

VSCode运行python提示No module name ‘xxx‘

在进行from * import *导入操作时&#xff0c;编辑器能够解析到module, 但是在编辑器中运行时确提示。 No module name xxx 而且单独运行该文件&#xff0c;或在其他编辑器、或terminal中python file运行&#xff0c;都能正常导入module. 解决方案&#xff1a; 在vscode的用…...

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…...

JVM垃圾回收机制全解析

Java虚拟机&#xff08;JVM&#xff09;中的垃圾收集器&#xff08;Garbage Collector&#xff0c;简称GC&#xff09;是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象&#xff0c;从而释放内存空间&#xff0c;避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...

Linux --进程控制

本文从以下五个方面来初步认识进程控制&#xff1a; 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程&#xff0c;创建出来的进程就是子进程&#xff0c;原来的进程为父进程。…...

Springboot社区养老保险系统小程序

一、前言 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;社区养老保险系统小程序被用户普遍使用&#xff0c;为方…...

关键领域软件测试的突围之路:如何破解安全与效率的平衡难题

在数字化浪潮席卷全球的今天&#xff0c;软件系统已成为国家关键领域的核心战斗力。不同于普通商业软件&#xff0c;这些承载着国家安全使命的软件系统面临着前所未有的质量挑战——如何在确保绝对安全的前提下&#xff0c;实现高效测试与快速迭代&#xff1f;这一命题正考验着…...

视觉slam十四讲实践部分记录——ch2、ch3

ch2 一、使用g++编译.cpp为可执行文件并运行(P30) g++ helloSLAM.cpp ./a.out运行 二、使用cmake编译 mkdir build cd build cmake .. makeCMakeCache.txt 文件仍然指向旧的目录。这表明在源代码目录中可能还存在旧的 CMakeCache.txt 文件,或者在构建过程中仍然引用了旧的路…...

基于IDIG-GAN的小样本电机轴承故障诊断

目录 🔍 核心问题 一、IDIG-GAN模型原理 1. 整体架构 2. 核心创新点 (1) ​梯度归一化(Gradient Normalization)​​ (2) ​判别器梯度间隙正则化(Discriminator Gradient Gap Regularization)​​ (3) ​自注意力机制(Self-Attention)​​ 3. 完整损失函数 二…...

怎么让Comfyui导出的图像不包含工作流信息,

为了数据安全&#xff0c;让Comfyui导出的图像不包含工作流信息&#xff0c;导出的图像就不会拖到comfyui中加载出来工作流。 ComfyUI的目录下node.py 直接移除 pnginfo&#xff08;推荐&#xff09;​​ 在 save_images 方法中&#xff0c;​​删除或注释掉所有与 metadata …...

第7篇:中间件全链路监控与 SQL 性能分析实践

7.1 章节导读 在构建数据库中间件的过程中&#xff0c;可观测性 和 性能分析 是保障系统稳定性与可维护性的核心能力。 特别是在复杂分布式场景中&#xff0c;必须做到&#xff1a; &#x1f50d; 追踪每一条 SQL 的生命周期&#xff08;从入口到数据库执行&#xff09;&#…...

从“安全密码”到测试体系:Gitee Test 赋能关键领域软件质量保障

关键领域软件测试的"安全密码"&#xff1a;Gitee Test如何破解行业痛点 在数字化浪潮席卷全球的今天&#xff0c;软件系统已成为国家关键领域的"神经中枢"。从国防军工到能源电力&#xff0c;从金融交易到交通管控&#xff0c;这些关乎国计民生的关键领域…...