Kubernetes入门实战课 3

05 镜像仓库:该怎样用好Docker Hub这个宝藏

你好,我是Chrono。

上一次课里我们学习了"Dockerfile"和"docker build"的用法,知道了如何创建自己的镜像。那么镜像文件应该如何管理呢,具体来说,应该如何存储、检索、分发、共享镜像呢?不解决这些问题,我们的容器化应用还是无法顺利地实施。

今天,我就来谈一下这个话题,聊聊什么是镜像仓库,还有该怎么用好镜像仓库。

什么是镜像仓库(Registry)

之前我们已经用过 docker pull 命令拉取镜像,也说过有一个"镜像仓库"(Registry)的概念,那到底什么是镜像仓库呢?

还是来看Docker的官方架构图(它真的非常重要):

图里右边的区域就是镜像仓库,术语叫Registry,直译就是"注册中心",意思是所有镜像的Repository都在这里登记保管,就像是一个巨大的档案馆。

然后我们再来看左边的"docker pull",虚线显示了它的工作流程,先到"Docker daemon",再到Registry,只有当Registry里存有镜像才能真正把它下载到本地。

当然了,拉取镜像只是镜像仓库最基本的一个功能,它还会提供更多的功能,比如上传、查询、删除等等,是一个全面的镜像管理服务站点。

你也可以把镜像仓库类比成手机上的应用商店,里面分门别类存放了许多容器化的应用,需要什么去找一下就行了。有了它,我们使用镜像才能够免除后顾之忧。

什么是Docker Hub

不过,你有没有注意到,在使用 docker pull 获取镜像的时候,我们并没有明确地指定镜像仓库。在这种情况下,Docker就会使用一个默认的镜像仓库,也就是大名鼎鼎的"Docker Hub "(https://hub.docker.com/)。

Docker Hub是Docker公司搭建的官方Registry服务,创立于2014年6月,和Docker 1.0同时发布。它号称是世界上最大的镜像仓库,和GitHub一样,几乎成为了容器世界的基础设施。

Docker Hub里面不仅有Docker自己打包的镜像,而且还对公众免费开放,任何人都可以上传自己的作品。经过这8年的发展,Docker Hub已经不再是一个单纯的镜像仓库了,更应该说是一个丰富而繁荣的容器社区。

你可以看看下面的这张截图,里面列出的都是下载量超过10亿次(1 Billion)的最受欢迎的应用程序,比如Nginx、MongoDB、Node.js、Redis、OpenJDK等等。显然,把这些容器化的应用引入到我们自己的系统里,就像是站在了巨人的肩膀上,一开始就会有一个高水平的起点。

但和GitHub、App Store一样,面向所有人公开的Docker Hub也有一个不可避免的缺点,就是"良莠不齐"。

在Docker Hub搜索框里输入关键字,比如Nginx、MySQL,它立即就会给出几百几千个搜索结果,有点"乱花迷人眼"的感觉,这么多镜像,应该如何挑选出最适合自己的呢?下面我就来说说自己在这方面的一些经验。

如何在Docker Hub上挑选镜像

首先,你应该知道,在Docker Hub上有官方镜像认证镜像非官方镜像的区别。

官方镜像是指Docker公司官方提供的高质量镜像(https://github.com/docker-library/official-images),都经过了严格的漏洞扫描和安全检测,支持x86_64、arm64等多种硬件架构,还具有清晰易读的文档,一般来说是我们构建镜像的首选,也是我们编写Dockerfile的最佳范例。

官方镜像目前有大约100多个,基本上囊括了现在的各种流行技术,下面就是官方的Nginx镜像网页截图:

你会看到,官方镜像会有一个特殊的"Official image"的标记,这就表示这个镜像经过了Docker公司的认证,有专门的团队负责审核、发布和更新,质量上绝对可以放心。

第二类是认证镜像,标记是"Verified publisher",也就是认证发行商,比如Bitnami、Rancher、Ubuntu等。它们都是颇具规模的大公司,具有不逊于Docker公司的实力,所以就在Docker Hub上开了个认证账号,发布自己打包的镜像,有点类似我们微博上的"大V"。

这些镜像有公司背书,当然也很值得信赖,不过它们难免会带上一些各自公司的"烙印",比如Bitnami的镜像就统一以"minideb"为基础,灵活性上比Docker官方镜像略差,有的时候也许会不符合我们的需求。

除了官方镜像和认证镜像,剩下的就都属于非官方镜像了,不过这里面也可以分出两类。

第一类是"半官方"镜像。因为成为"Verified publisher"是要给Docker公司交钱的,而很多公司不想花这笔"冤枉钱",所以只在Docker Hub上开了公司账号,但并不加入认证。

这里我以OpenResty为例,看一下它的Docker Hub页面,可以看到显示的是OpenResty官方发布,但并没有经过Docker正式认证,所以难免就会存在一些风险,有被"冒名顶替"的可能,需要我们在使用的时候留心鉴别一下。不过一般来说,这种"半官方"镜像也是比较可靠的。

第二类就是纯粹的"民间"镜像了,通常是个人上传到Docker Hub的,因为条件所限,测试不完全甚至没有测试,质量上难以得到保证,下载的时候需要小心谨慎。

除了查看镜像是否为官方认证,我们还应该再结合其他的条件来判断镜像质量是否足够好。做法和GitHub差不多,就是看它的下载量、星数、还有更新历史,简单来说就是"好评"数量。

一般来说下载量是最重要的参考依据,好的镜像下载量通常都在百万级别(超过1M),而有的镜像虽然也是官方认证,但缺乏维护,更新不及时,用的人很少,星数、下载数都寥寥无几,那么还是应该选择下载量最多的镜像,通俗来说就是"随大流"。

下面的这张截图就是OpenResty在Docker Hub上的搜索结果。可以看到,有两个认证发行商的镜像(Bitnami、IBM),但下载量都很少,还有一个"民间"镜像下载量虽然超过了1M,但更新时间是3年前,所以毫无疑问,我们应该选择排在第三位,但下载量超过10M、有360多个星的"半官方"镜像。

看了这么多Docker Hub上的镜像,你一定注意到了,应用都是一样的名字,比如都是Nginx、Redis、OpenResty,该怎么区分不同作者打包出的镜像呢?

如果你熟悉GitHub,就会发现Docker Hub也使用了同样的规则,就是"用户名/应用名 "的形式,比如 bitnami/nginxubuntu/nginxrancher/nginx 等等。

所以,我们在使用 docker pull 下载这些非官方镜像的时候,就必须把用户名也带上,否则默认就会使用官方镜像:

复制代码

docker pull bitnami/nginx docker pull ubuntu/nginx

Docker Hub上镜像命名的规则是什么

确定了要使用的镜像还不够,因为镜像还会有许多不同的版本,也就是"标签"(tag)。

直接使用默认的"latest"虽然简单方便,但在生产环境里是一种非常不负责任的做法,会导致版本不可控。所以我们还需要理解Docker Hub上标签命名的含义,才能够挑选出最适合我们自己的镜像版本。

下面我就拿官方的Redis镜像作为例子,解释一下这些标签都是什么意思。

通常来说,镜像标签的格式是应用的版本号加上操作系统

版本号你应该比较了解吧,基本上都是主版本号+次版本号+补丁号的形式,有的还会在正式发布前出rc版(候选版本,release candidate)。而操作系统的情况略微复杂一些,因为各个Linux发行版的命名方式"花样"太多了。

Alpine、CentOS的命名比较简单明了,就是数字的版本号,像这里的 alpine3.15 ,而Ubuntu、Debian则采用了代号的形式。比如Ubuntu 18.04是 bionic,Ubuntu 20.04是 focal,Debian 9是 stretch,Debian 10是 buster,Debian 11是 bullseye

另外,有的标签还会加上 slimfat,来进一步表示这个镜像的内容是经过精简的,还是包含了较多的辅助工具 。通常 slim 镜像会比较小,运行效率高,而 fat 镜像会比较大,适合用来开发调试。

下面我就列出几个标签的例子来说明一下。

  • nginx:1.21.6-alpine,表示版本号是1.21.6,基础镜像是最新的Alpine。
  • redis:7.0-rc-bullseye,表示版本号是7.0候选版,基础镜像是Debian 11。
  • node:17-buster-slim,表示版本号是17,基础镜像是精简的Debian 10。

该怎么上传自己的镜像

现在,我想你应该对如何在Docker Hub上选择镜像有了比较全面的了解,那么接下来的问题就是,我们自己用Dockerfile创建的镜像该如何上传到Docker Hub上呢?

这件事其实一点也不难,只需要4个步骤就能完成。

第一步,你需要在Docker Hub上注册一个用户,这个就不必再多说了。

第二步,你需要在本机上使用 docker login 命令,用刚才注册的用户名和密码认证身份登录,像这里就用了我的用户名"chronolaw":

第三步很关键,需要使用 docker tag 命令,给镜像改成带用户名的完整名字,表示镜像是属于这个用户的。或者简单一点,直接用 docker build -t 在创建镜像的时候就起好名字。

这里我就用上次课里的镜像"ngx-app"作为例子,给它改名成 chronolaw/ngx-app:1.0

复制代码

docker tag ngx-app chronolaw/ngx-app:1.0

第四步,用 docker push 把这个镜像推上去,我们的镜像发布工作就大功告成了:

复制代码

docker push chronolaw/ngx-app:1.0

你还可以登录Docker Hub网站验证一下镜像发布的效果,可以看到它会自动为我们生成一个页面模板,里面还可以进一步丰富完善,比如添加描述信息、使用说明等等:

现在你就可以把这个镜像的名字(用户名/应用名:标签)告诉你的同事,让他去用 docker pull 下载部署了。

离线环境该怎么办

使用Docker Hub来管理镜像的确是非常方便,不过有一种场景下它却是无法发挥作用,那就是企业内网的离线环境,连不上外网,自然也就不能使用 docker pushdocker pull 来推送拉取镜像了。

那这种情况有没有解决办法呢?

方法当然有,而且有很多。最佳的方法就是在内网环境里仿造Docker Hub,创建一个自己的私有Registry服务,由它来管理我们的镜像,就像我们自己搭建GitLab做版本管理一样。

自建Registry已经有很多成熟的解决方案,比如Docker Registry,还有CNCF Harbor,不过使用它们还需要一些目前没有讲到的知识,步骤也有点繁琐,所以我会在后续的课程里再介绍。

下面我讲讲存储、分发镜像的一种"笨"办法,虽然比较"原始",但简单易行,可以作为临时的应急手段。

Docker提供了 saveload 这两个镜像归档命令,可以把镜像导出成压缩包,或者从压缩包导入Docker,而压缩包是非常容易保管和传输的,可以联机拷贝,FTP共享,甚至存在U盘上随身携带。

需要注意的是,这两个命令默认使用标准流作为输入输出(为了方便Linux管道操作),所以一般会用 -o-i 参数来使用文件的形式,例如:

复制代码

docker save ngx-app:latest -o ngx.tar docker load -i ngx.tar

小结

好了,今天我们一起学习了镜像仓库,了解了Docker Hub的使用方法,整理一下要点方便你加深理解:

  1. 镜像仓库(Registry)是一个提供综合镜像服务的网站,最基本的功能是上传和下载。
  2. Docker Hub是目前最大的镜像仓库,拥有许多高质量的镜像。上面的镜像非常多,选择的标准有官方认证、下载量、星数等,需要综合评估。
  3. 镜像也有很多版本,应该根据版本号和操作系统仔细确认合适的标签。
  4. 在Docker Hub注册之后就可以上传自己的镜像,用 docker tag 打上标签再用 docker push 推送。
  5. 离线环境可以自己搭建私有镜像仓库,或者使用 docker save 把镜像存成压缩包,再用 docker load 从压缩包恢复成镜像。

课下作业

最后是课下作业时间,给你留两个思考题:

  1. 很多应用(如Nginx、Redis、Go)都已经有了Docker官方镜像,为什么其他公司(Bitnami、Rancher)还要重复劳动,发布自己打包的镜像呢?
  2. 你能否对比一下GitHub和Docker Hub,说说它们两个在功能、服务对象、影响范围等方面的异同点呢?

记得在留言区留言参与讨论哦,如果我看到,也会第一时间给你回复。我们下节课再见。

精选留言(15)

  • 朱雯 👍(13) 💬(5) 老师您好,在文中提到的arm架构和x86架构支持,请问一下,能否使用dockerfile创建同时支持两种服务的镜像呢。

    2022-07-01

  • 拾掇拾掇 👍(9) 💬(1) 1.我猜是把自己的工具打包进去或者官方镜像满足不了他们自己的需求 2.github 和docker hub都是仓库,不过一个是代码仓库,一个是容器仓库,面向的都是程序员或者是计算机爱好者,都提供了存储和分发功能

06 打破次元壁:容器该如何与外界互联互通

你好,我是Chrono。

在前面的几节课里,我们已经学习了容器、镜像、镜像仓库的概念和用法,也知道了应该如何创建镜像,再以容器的形式启动应用。

不过,用容器来运行"busybox""hello world"这样比较简单的应用还好,如果是Nginx、Redis、MySQL这样的后台服务应用,因为它们运行在容器的"沙盒"里,完全与外界隔离,无法对外提供服务,也就失去了价值。这个时候,容器的隔离环境反而成为了一种负面特性。

所以,容器的这个"小板房"不应该是一个完全密闭的铁屋子,而是应该给它开几扇门窗,让应用在"足不出户"的情况下,也能够与外界交换数据、互通有无,这样"有限的隔离"才是我们真正所需要的运行环境。

那么今天,我就以Docker为例,来讲讲有哪些手段能够在容器与外部系统之间沟通交流。

如何拷贝容器内的数据

我们首先来看看Docker提供的 cp 命令,它可以在宿主机和容器之间拷贝文件,是最基本的一种数据交换功能。

试验这个命令需要先用 docker run 启动一个容器,就用Redis吧:

复制代码

docker run -d --rm redis

注意这里使用了 -d--rm 两个参数,表示运行在后台,容器结束后自动删除,然后使用 docker ps 命令可以看到Redis容器正在运行,容器ID是"062"。

docker cp 的用法很简单,很类似Linux的"cp""scp",指定源路径(src path)和目标路径(dest path)就可以了。如果源路径是宿主机那么就是把文件拷贝进容器,如果源路径是容器那么就是把文件拷贝出容器,注意需要用容器名或者容器ID来指明是哪个容器的路径。

假设当前目录下有一个"a.txt"的文件,现在我们要把它拷贝进Redis容器的"/tmp"目录,如果使用容器ID,命令就会是这样:

复制代码

docker cp a.txt 062:/tmp

接下来我们可以使用 docker exec 命令,进入容器看看文件是否已经正确拷贝了:

复制代码

docker exec -it 062 sh

可以看到,在"/tmp"目录下,确实已经有了一个"a.txt"。

现在让我们再来试验一下从容器拷贝出文件,只需要把 docker cp 后面的两个路径调换一下位置:

复制代码

docker cp 062:/tmp/a.txt ./b.txt

这样,在宿主机的当前目录里,就会多出一个新的"b.txt",也就是从容器里拿到的文件。

如何共享主机上的文件

docker cp 的用法模仿了操作系统的拷贝命令,偶尔一两次的文件共享还可以应付,如果容器运行时经常有文件来往互通,这样反复地拷来拷去就显得很麻烦,也很容易出错。

你也许会联想到虚拟机有一种"共享目录"的功能。它可以在宿主机上开一个目录,然后把这个目录"挂载"进虚拟机,这样就实现了两者共享同一个目录,一边对目录里文件的操作另一边立刻就能看到,没有了数据拷贝,效率自然也会高很多。

沿用这个思路,容器也提供了这样的共享宿主机目录的功能,效果也和虚拟机几乎一样,用起来很方便,只需要在 docker run 命令启动容器的时候使用 -v 参数就行,具体的格式是"宿主机路径:容器内路径"。

我还是以Redis为例,启动容器,使用 -v 参数把本机的"/tmp"目录挂载到容器里的"/tmp"目录,也就是说让容器共享宿主机的"/tmp"目录:

复制代码

docker run -d --rm -v /tmp:/tmp redis

然后我们再用 docker exec 进入容器,查看一下容器内的"/tmp"目录,应该就可以看到文件与宿主机是完全一致的。

复制代码

docker exec -it b5a sh # b5a是容器ID

你也可以在容器里的"/tmp"目录下随便做一些操作,比如删除文件、建立新目录等等,再回头观察一下宿主机,会发现修改会即时同步,这就表明容器和宿主机确实已经共享了这个目录。

-v 参数挂载宿主机目录的这个功能,对于我们日常开发测试工作来说非常有用,我们可以在不变动本机环境的前提下,使用镜像安装任意的应用,然后直接以容器来运行我们本地的源码、脚本,非常方便。

这里我举一个简单的例子。比如我本机上只有Python 2.7,但我想用Python 3开发,如果同时安装Python 2和Python 3很容易就会把系统搞乱,所以我就可以这么做:

  1. 先使用 docker pull 拉取一个Python 3的镜像,因为它打包了完整的运行环境,运行时有隔离,所以不会对现有系统的Python 2.7产生任何影响。
  2. 在本地的某个目录编写Python代码,然后用 -v 参数让容器共享这个目录。
  3. 现在就可以在容器里以Python 3来安装各种包,再运行脚本做开发了。
复制代码

docker pull python:alpine docker run -it --rm -v `pwd`:/tmp python:alpine sh

显然,这种方式比把文件打包到镜像或者 docker cp 会更加灵活,非常适合有频繁修改的开发测试工作。

如何实现网络互通

现在我们使用 docker cpdocker run -v 可以解决容器与外界的文件互通问题,但对于Nginx、Redis这些服务器来说,网络互通才是更要紧的问题。

网络互通的关键在于"打通"容器内外的网络,而处理网络通信无疑是计算机系统里最棘手的工作之一,有许许多多的名词、协议、工具,在这里我也没有办法一下子就把它都完全说清楚,所以只能从"宏观"层面讲个大概,帮助你快速理解。

Docker提供了三种网络模式,分别是nullhostbridge

null是最简单的模式,也就是没有网络,但允许其他的网络插件来自定义网络连接,这里就不多做介绍了。

host的意思是直接使用宿主机网络,相当于去掉了容器的网络隔离(其他隔离依然保留),所有的容器会共享宿主机的IP地址和网卡。这种模式没有中间层,自然通信效率高,但缺少了隔离,运行太多的容器也容易导致端口冲突。

host模式需要在 docker run 时使用 --net=host 参数,下面我就用这个参数启动Nginx:

复制代码

docker run -d --rm --net=host nginx:alpine

为了验证效果,我们可以在本机和容器里分别执行 ip addr 命令,查看网卡信息:

复制代码

ip addr # 本机查看网卡 docker exec xxx ip addr # 容器查看网卡

可以看到这两个 ip addr 命令的输出信息是完全一样的,比如都是一个网卡ens160,IP地址是"192.168.10.208",这就证明Nginx容器确实与本机共享了网络栈。

第三种bridge,也就是桥接模式,它有点类似现实世界里的交换机、路由器,只不过是由软件虚拟出来的,容器和宿主机再通过虚拟网卡接入这个网桥(图中的docker0),那么它们之间也就可以正常的收发网络数据包了。不过和host模式相比,bridge模式多了虚拟网桥和网卡,通信效率会低一些。

和host模式一样,我们也可以用 --net=bridge 来启用桥接模式,但其实并没有这个必要,因为Docker默认的网络模式就是bridge,所以一般不需要显式指定。

下面我们启动两个容器Nginx和Redis,就像刚才说的,没有特殊指定就会使用bridge模式:

复制代码

docker run -d --rm nginx:alpine # 默认使用桥接模式 docker run -d --rm redis # 默认使用桥接模式

然后我们还是在本机和容器里执行 ip addr 命令(Redis容器里没有ip命令,所以只能在Nginx容器里执行):

对比一下刚才host模式的输出,就可以发现容器里的网卡设置与宿主机完全不同,eth0是一个虚拟网卡,IP地址是B类私有地址"172.17.0.2"。

我们还可以用 docker inspect 直接查看容器的ip地址:

复制代码

docker inspect xxx |grep IPAddress

这显示出两个容器的IP地址分别是"172.17.0.2"和"172.17.0.3",而宿主机的IP地址则是"172.17.0.1",所以它们都在"172.17.0.0/16"这个Docker的默认网段,彼此之间就能够使用IP地址来实现网络通信了。

如何分配服务端口号

使用host模式或者bridge模式,我们的容器就有了IP地址,建立了与外部世界的网络连接,接下来要解决的就是网络服务的端口号问题。

你一定知道,服务器应用都必须要有端口号才能对外提供服务,比如HTTP协议用80、HTTPS用443、Redis是6379、MySQL是3306。第4讲我们在学习编写Dockerfile的时候也看到过,可以用 EXPOSE 指令声明容器对外的端口号。

一台主机上的端口号数量是有限的,而且多个服务之间还不能够冲突,但我们打包镜像应用的时候通常都使用的是默认端口,容器实际运行起来就很容易因为端口号被占用而无法启动。

解决这个问题的方法就是加入一个"中间层",由容器环境例如Docker来统一管理分配端口号,在本机端口和容器端口之间做一个"映射"操作,容器内部还是用自己的端口号,但外界看到的却是另外一个端口号,这样就很好地避免了冲突。

端口号映射需要使用bridge模式,并且在 docker run 启动容器时使用 -p 参数,形式和共享目录的 -v 参数很类似,用 : 分隔本机端口和容器端口。比如,如果要启动两个Nginx容器,分别跑在80和8080端口上:

复制代码

docker run -d -p 80:80 --rm nginx:alpine docker run -d -p 8080:80 --rm nginx:alpine

这样就把本机的80和8080端口分别"映射"到了两个容器里的80端口,不会发生冲突,我们可以用curl再验证一下:

使用 docker ps 命令能够在"PORTS"栏里更直观地看到端口的映射情况:

小结

好了,今天我们一起学习了容器与外部系统之间沟通交流的几种方法。

你会发现,这些方法几乎消除了容器化的应用和本地应用因为隔离特性而产生的差异,而因为镜像独特的打包机制,容器技术显然能够比apt/yum更方便地安装各种应用,绝不会"污染"已有的系统。

今天的课里我列举了Python、Nginx等例子,你还可以举一反三,借鉴它们把本地配置文件加载到容器里适当的位置,再映射端口号,把Redis、MySQL、Node.js都运行起来,让容器成为我们工作中的得力助手。

照例简单小结一下这次的要点:

  1. docker cp 命令可以在容器和主机之间互相拷贝文件,适合简单的数据交换。
  2. docker run -v 命令可以让容器和主机共享本地目录,免去了拷贝操作,提升工作效率。
  3. host网络模式让容器与主机共享网络栈,效率高但容易导致端口冲突。
  4. bridge网络模式实现了一个虚拟网桥,容器和主机都在一个私有网段内互联互通。
  5. docker run -p 命令可以把主机的端口号映射到容器的内部端口号,解决了潜在的端口冲突问题。

课下作业

最后是课下作业时间,给你留两个思考题:

  1. 你能说出今天学的 docker cp 命令和第4讲Dockerfile里的COPY指令有什么区别吗?
  2. 你觉得host模式和bridge模式各有什么优缺点,在什么场景下应用最合适?

欢迎积极留言讨论,我会第一时间给你回复,如果有收获也欢迎你转发给身边的朋友一起学习。

下节课是实战演练,下节课见。

精选留言(15)

  • xmr 👍(30) 💬(1) 1.第四节的COPY是在构建镜像时把本地文件拷贝到镜像,而本节的cp命令是在容器运行后容器和宿主机互相拷贝文件,一个构建时,一个运行时。 2.host性能好,隔离性差;bridge隔离性好,性能差了一点。host一般用在集群的边界需要和集群外通信的场景,比如ingress-nginx;bridge用于集群内部,如无特殊需求默认都是bridge。

    2022-07-05

  • 马以 👍(22) 💬(3) 1:第四节的copy命令是在容器启动过程中的COPY命令,该命令应该是在声明了"namespace"之后,所以这个时候进程看到的世界是一个隔离的环境; 而这里的COPY更像是站在"上帝视角(宿主机操作系统层面)"进行拷贝,所以这里不受"namespace"的约束; 2:host就是简单粗暴效率高,适合小规模集群的简单拓扑结构;bridge适合大规模集群,有了bridge就有更多的可操作空间,比如XLAN和VXLAN这些,它可以提供更多的可定制化服务,比如流量控制、灰度策略这些,从而像flannel和Calico这些组件才有了更多的发挥余地。

相关推荐
2601_962219012 小时前
版本平滑升级架构:万象生鲜系统 V4.3.3 迭代无停机更新技术拆解
微服务·云原生·架构
小张同学a.2 小时前
Docker 容器实战 1—— docker 基础与镜像构建
linux·运维·docker·容器
NJCloud3 小时前
Docker 容器技术入门:部署、核心概念与基础命令
运维·docker·容器
2601_962072333 小时前
docker自建rustdesk-server远程桌面
运维·docker·容器
阿里云云原生3 小时前
深入解析 STAROps 瑶池 Agent:如何实现从应用告警到数据库命令级的全栈 RCA?
云原生
阿里云云原生4 小时前
告别手工配置:利用 Migration Skill 实现 Nginx Ingress 注解的智能分析与自动转换
云原生
2601_962218474 小时前
万象生鲜系统冷链物联网接入技术实现生鲜企业温控管理数字化
大数据·运维·微服务·云原生·架构
阿里云云原生4 小时前
Event-Driven AI 架构解析:从 Confluent Intelligence 三大支柱到阿里云实践
云原生
阿里云云原生5 小时前
从手工回测到全自动化:AgentLoop 在 Agent Engineering 中的落地与实践总结
云原生·agent