news 2026/9/8 4:19:01

Docker私有仓库搭建实战:从Registry到HTTPS认证与故障排查

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Docker私有仓库搭建实战:从Registry到HTTPS认证与故障排查

在公司内部跑了两年业务,部署环境从一台测试机膨胀到几十台服务器之后,我越来越觉得当初认真搭一套 Docker Registry 私有仓库是个极其正确的决定。

倒不是说 Docker Hub 不好用,而是在真实生产环境里,你会发现公共镜像源存在几个硬伤:一是网络链路不稳定,尤其在业务高峰期,docker pull一个几百兆的镜像可能反复超时;二是企业内部网络往往有隔离要求,生产区服务器根本不允许访问外网;三是安全和合规问题,团队镜像推到公共仓库总是不踏实,代码版本、内部配置全暴露在第三方平台上。

所以这篇文章不打算讲虚的,直接以我自己的实操经验,把一个私有镜像仓库从选型、搭建、加 HTTPS、加认证,到日常维护和那些年踩过的坑完整梳理一遍。如果你正准备在团队内部搭一套镜像仓库,或者已经在用 Registry 但总感觉哪里不对劲,这篇内容应该能帮你省下不少时间。

1. 为什么我要劝你搭私有仓库:公共镜像源的三个硬伤

很多团队初期人少、服务器少,习惯直接从 Docker Hub 拉镜像跑服务,觉得私有仓库是多此一举。我自己也经历过这个阶段,但等规模上来,公共镜像源的痛点会逐步放大到不可忽略。

第一个硬伤是网络不稳定带来的连锁故障。Docker Hub 的服务器在国外,跨海链路的延迟和丢包率往往让人抓狂。一次docker pull ubuntu:20.04,可能下载到一半连接断了,重试又是从头开始。更麻烦的是,如果你用的是云服务器,某些时段公共镜像源的访问速度会明显下降。曾经我遇到过上游限流,应用发布时需要重新拉取基础镜像,结果整个发布会因为一个镜像卡了半个多小时。

第二个硬伤是内网隔离环境下根本无源可用。现在稍微正规一点的公司,生产环境和开发环境都是做了网络隔离的,生产服务器往往只能访问内网。这种情况下,开发机从 Docker Hub 拉好镜像,想传到生产机上,靠docker save导出一个 tar 包再手动拷过去,小规模还勉强能用,机器一多、版本一变,这玩法就是灾难。

第三个硬伤是安全与合规风险。你想想,镜像里面有什么?基础环境变量、启动脚本、依赖包版本、甚至数据库连接地址。虽然公共镜像仓库有私有库功能,但在无法控制的环境里存放内部镜像,始终是一件让人心里打鼓的事。尤其当团队的镜像需要包含某些内部编译的二进制时,用公共仓库就等于把机密文件交给第三方保管。

那私有 Registry 到底解决了什么?说白了,它在你的内网里充当一个"镜像中转站 + 版本仓库"。开发机把镜像推到内网 Registry,生产服务器只需要从内网 Registry 拉取,整个过程完全不依赖外网。同时,镜像的版本管理、覆盖、回滚都有了统一的入口,团队协作效率也跟着上来了。

2. Registry还是Harbor,别让选型变成日后搬家

其实我在好几个不同规模的团队里见过关于选型的争执,一边说 Harbor 功能全、有 Web UI,另一边说 Registry 轻量、够用就行。这两者的差异,我先用一张表说清楚。

对比项Docker RegistryHarbor
部署复杂度单个容器,一条命令搞定需要 docker-compose 起多个组件,依赖 PostgreSQL、Redis
资源占用极低,适合资源紧张的服务器较高,至少需要 2C4G 起步
Web 管理界面无,只有 REST API有完整的 Web UI,可视化操作
镜像复制不支持,需额外开发或用第三方工具支持跨实例复制,做两地容灾很方便
权限体系仅支持基础认证,无细粒度权限控制支持项目级权限、RBAC,可对接 LDAP
漏洞扫描集成 Clair,扫描镜像 CVE
适用场景中小团队、内网单实例、资源受限大型团队、多环境、合规要求高的企业

为什么最终我还是选了 Registry?关键判断逻辑是"够用就好"。当时我的团队不到二十人,容器规模在几十个左右,没有跨机房复制需求,也不需要对镜像做漏洞扫描。Harbor 虽然好,但它引入的 PostgreSQL、Redis、Trivy 这些组件,本身就是需要被维护的东西。一个只有几百兆内存的小服务器上,Harbor 跑起来捉襟见肘,而 Registry 配合 Nginx 反向代理,几百 MB 内存就运行得绰绰有余。

你可以这样理解:Registry 像是一个朴素的仓库货架,功能简单但稳定可靠;Harbor 则像一个带保安、带巡检、带仓库管理系统的现代化仓库。如果你的团队已经上了 K8s、有专职运维、对安全合规有硬性要求,那 Harbor 值得上;如果你的场景是内网开发测试、小规模生产,先把 Registry 跑起来,以后需要了再平滑迁移到 Harbor 也不迟,因为两者在 Docker 客户端侧的用法完全一样。

3. 最简搭建:一条docker run命令跑通推送拉取

选型定了,接下来直接搭建。私有 Registry 官方镜像就是registry:2,它是 Docker 团队维护的,稳定性和兼容性都没问题。下面这套步骤是我在 Ubuntu 20.04 服务器上实测过的。

第一步:规划目录结构。建议把 Registry 的持久化数据单独挂载到一个独立目录,方便备份和迁移。

mkdir -p /opt/registry/data mkdir -p /opt/registry/certs mkdir -p /opt/registry/auth
  • /opt/registry/data存放镜像分层数据
  • /opt/registry/certs存放 HTTPS 证书
  • /opt/registry/auth存放认证文件

第二步:启动容器。最简的启动命令如下:

docker run -d \ --name registry \ --restart=always \ -p 5000:5000 \ -v /opt/registry/data:/var/lib/registry \ registry:2

将宿主机的 5000 端口映射到容器的 5000 端口,把数据目录挂载进去。--restart=always保证服务重启后自动拉起,这个参数在生产环境是必须的。

第三步:本机验证推送与拉取。先从 Docker Hub 拉一个测试镜像,打上私有仓库的标签再推上去。

# 拉镜像 docker pull nginx:1.24 # 打标签,格式是 <registry地址>:<端口>/<镜像名>:<版本> docker tag nginx:1.24 192.168.1.100:5000/nginx:1.24 # 推送 docker push 192.168.1.100:5000/nginx:1.24 # 查看仓库里的镜像列表 curl http://192.168.1.100:5000/v2/_catalog # 查看某个镜像的标签列表 curl http://192.168.1.100:5000/v2/nginx/tags/list

看到镜像列表里有nginx,就说明整套链路已经通了。这一步会暴露出来一个很重要的问题:为什么 docker push 到非 443 端口时,默认走的是 HTTP?其实 Docker 客户端对镜像仓库地址有约定,默认只信任 HTTPS 和本地地址(localhost),你直接用 IP,会被当作 insecure registry 处理。这个后面第四节单独说。

再补充一句,如果你只是想临时玩一下,连/opt/registry/data挂载都可以省掉,但容器一删数据就没了。Git 仓库删了还能 clone,Registry 里的数据没了可是连底裤都翻不出来,所以持久化从第一天就要做好。

4. 从本机到局域网:客户端访问配置和HTTP的坑

基础版搭建只是万里长征第一步。当你想从另一台机器上推送或拉取镜像时,大概率会看到这样的报错:

Error response from daemon: Get "https://192.168.1.100:5000/v2/": http: server gave HTTP response to HTTPS client

这个报错的根源在于,Docker 客户端默认会用 HTTPS 访问镜像仓库,而我的私有 Registry 目前只是个裸 HTTP 服务。要让它正常工作,有两种思路:一是配置客户端对指定地址放行 HTTP,这个参数叫insecure-registries;二是给 Registry 配置上 HTTPS 证书,一劳永逸地解决信任问题。

先说第一种方式,适合内网测试环境快速打通。修改 Docker 客户端的 daemon.json 文件:

vi /etc/docker/daemon.json

内容如下:

{ "insecure-registries": ["192.168.1.100:5000"] }

修改完成后重启 Docker 服务:

systemctl restart docker

注意:这个改动影响的是 Docker 守护进程,而不是单个容器。配置完成后,当前机器上所有 docker 命令都会对192.168.1.100:5000放行 HTTP。

在 macOS 或 Windows 的 Docker Desktop 上,路径不一样,需要在 Docker Desktop 的 Settings -> Docker Engine 里编辑同样的 JSON,然后点击 Apply & Restart。

第二种方式是配置 HTTPS,这个我在第五节单独讲。这里先补充一个跨机器使用时非常容易踩的坑:即使你把insecure-registries配好了,docker push依然可能报错,原因是操作系统的代理设置。我当时排查了很久才发现,服务器上配置了 HTTP_PROXY 指向一个代理端口,Docker 客户端会把 Registry 的请求也走代理转发,结果内网地址被代理给拦截了。解决办法是在 daemon.json 里显式声明 no_proxy:

{ "insecure-registries": ["192.168.1.100:5000"], "no_proxy": "192.168.1.100" }

然后再重启 Docker。这也是为什么我在文章开头说,私有仓库搭起来不难,难的是把周边环境梳理干净。

另外,如果你在公司电脑上用的是 Docker Desktop,还要留意一个细节:Docker Desktop 需要额外勾选 "Expose daemon on tcp://localhost:2375 without TLS",否则容器内访问宿主机的 Registry 会遇到网络不通的问题。这个选项在 Settings -> General 里。

5. 给仓库上锁:HTTPS证书与基础认证一次配齐

裸 HTTP 的 Registry 在外人看来就像没关门的仓库,谁都能进出。在内网环境可能还觉得问题不大,但只要这台机器有公网 IP,或者有跨部门访问的需求,你就必须把 HTTPS 和认证两手抓。

5.1 生成自签证书

如果没有公司内部 CA,可以使用自签证书。注意,自签证书在 Docker 客户端里不会自动被信任,需要在每台客户端机器上配置信任。

cd /opt/registry/certs # 生成私钥 openssl genrsa -out registry.key 2048 # 生成自签证书,注意CN和SAN要跟你的访问域名对应 openssl req -new -x509 \ -key registry.key \ -out registry.crt \ -days 365 \ -subj "/CN=registry.example.com" \ -addext "subjectAltName=DNS:registry.example.com,IP:192.168.1.100"

这里有个容易忽略的点:如果客户端使用的是 IP 地址访问,那么证书的 SAN 里必须包含这个 IP。如果客户端使用的是域名,SAN 里就要包含域名。两边对不上,哪怕客户端信任了证书,Docker 依然会报 x509 证书错误。

5.2 启用 HTTPS 启动 Registry

docker run -d \ --name registry \ --restart=always \ -p 5000:5000 \ -v /opt/registry/data:/var/lib/registry \ -v /opt/registry/certs:/certs \ -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/registry.crt \ -e REGISTRY_HTTP_TLS_KEY=/certs/registry.key \ registry:2

加两个环境变量告诉 Registry 证书和私钥的位置。重启容器后,用 curl 验证一下:

curl https://192.168.1.100:5000/v2/_catalog --insecure

注意这里是https了。--insecure只是 curl 跳过证书验签,用来快速验证服务是否起来了,实际客户端还是要配信任的。

5.3 客户端信任自签证书

在 Linux 客户端机器上,把证书复制到系统信任目录并更新:

cp /opt/registry/certs/registry.crt /usr/local/share/ca-certificates/registry.crt update-ca-certificates

然后重启 Docker:

systemctl restart docker

做完这一步,客户端再访问https://192.168.1.100:5000就不会报证书错误了。注意,如果你之前配置过相同的 IP 在insecure-registries里,建议去掉,否则 Docker 反而会跳过 HTTPS 校验,行为不可预期。

5.4 添加基础认证

Registry 本身没有用户体系,但支持 htpasswd 基础认证。先创建认证文件:

mkdir -p /opt/registry/auth # 用官方镜像里的 htpasswd 工具生成密码文件 # 这里的账户是 admin,按提示输入两次密码 docker run --rm --entrypoint htpasswd registry:2 -Bbn admin '你的强密码' > /opt/registry/auth/htpasswd

重启 Registry 容器,加上认证相关环境变量:

docker run -d \ --name registry \ --restart=always \ -p 5000:5000 \ -v /opt/registry/data:/var/lib/registry \ -v /opt/registry/certs:/certs \ -v /opt/registry/auth:/auth \ -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/registry.crt \ -e REGISTRY_HTTP_TLS_KEY=/certs/registry.key \ -e REGISTRY_AUTH=htpasswd \ -e REGISTRY_AUTH_HTPASSWD_REALM=Registry_Realm \ -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \ -e REGISTRY_STORAGE_DELETE_ENABLED=true \ registry:2

注意我把REGISTRY_STORAGE_DELETE_ENABLED=true也加上了,没有这个参数,后面想用 API 删除镜像会直接返回 405,后面讲垃圾回收时具体说。

加了认证之后,所有 docker 操作都需要先登录:

docker login 192.168.1.100:5000 Username: admin Password:

登录成功后会生成~/.docker/config.json,之后的 push / pull 就不需要重复输密码了。

不过这里有个坑:如果你的客户端之前是在 insecure-registries 模式下登录的,现在改成 HTTPS 后 token 会失效,需要重新 docker login 一次。别问我怎么知道的,上线那天我连着输错三次密码被锁麻了。

6. 离线环境镜像分发:save、load、push三板斧

私有仓库还有一个非常实用的场景,就是离线环境部署。很多内网生产环境与外界物理隔离,想安装一个新服务,连基础镜像都拉不下来。这时候 Registry 的作用就出来了:在能联网的机器上拉镜像、打包、拷贝、导入到内网,然后推到私有仓库供生产机器统一拉取。

整个流程固定四步,我用一个实际例子演示。

第一步:在联网机器上拉取并打包镜像。

docker pull mysql:8.0 docker save mysql:8.0 -o mysql-8.0.tar

第二步:压缩并拷贝到目标机器。

gzip mysql-8.0.tar scp mysql-8.0.tar.gz user@192.168.1.100:/tmp/

如果文件很大,也可以用pigz多线程压缩,速度能快好几倍。实测一个 2GB 的镜像,单线程 gzip 要三五分钟,pigz 大概只要一半时间。

第三步:在目标机器上解压并导入镜像。

gunzip mysql-8.0.tar.gz docker load -i mysql-8.0.tar

这里有个容易混淆的点:docker load加载进来的是镜像,不是容器,它会把镜像连同标签一起加载到本地镜像库里。你可以docker images确认一下。

第四步:打标签并推送到私有仓库。

docker tag mysql:8.0 192.168.1.100:5000/mysql:8.0 docker push 192.168.1.100:5000/mysql:8.0

之后所有离线环境的服务器,只需要从192.168.1.100:5000/mysql:8.0拉取镜像,不用再一个个拷贝大文件了。

我建议把常用基础镜像,比如nginxmysqlredisalpine,提前全量推送到私有仓库里,形成一个内网基础镜像库。这样等业务真正需要扩容的时候,只要一条docker pull命令就搞定,根本不用等外网。

这里再补充一个docker savevsdocker export的区别:save保存的是镜像(含历史层和元数据),export导出的是容器当前的文件系统(不含历史记录)。离线分发镜像,一定用save,不要用export,否则镜像在私有仓库里会失去分层结构,体积也会膨胀。

还有一个经常有人问的问题:docker pull私有仓库的镜像,标签到底该怎么写?标准格式是<仓库地址>:<端口>/<项目>/<镜像名>:<标签>。如果你在启动 Registry 时开了多个命名空间(项目),Docker 客户端的 url 路径会对应上。没有项目隔离的话,直接192.168.1.100:5000/镜像名:标签即可。

7. 故障排查实录:从报错日志到根因的一条完整链路

这里我挑三个高频出现的故障,把排查思路完整写下来,因为这些东西在官方文档里根本找不到现成答案。

7.1 报错:"http: server gave HTTP response to HTTPS client"

这个错在第四节出现过,根因是客户端用 HTTPS 去访问一个 HTTP 服务。排查链路如下:

  1. 先在客户端机器上执行curl http://192.168.1.100:5000/v2/_catalog,如果返回 JSON 正常,说明服务端是 HTTP。
  2. 再执行curl https://192.168.1.100:5000/v2/_catalog,如果报 SSL 错误或连接失败,说明服务端确实不支持 HTTPS。
  3. 确认客户端 daemon.json 是否配置了insecure-registries,且包含了正确的 IP:端口。

最常见的翻车点,是配置了"insecure-registries": ["192.168.1.100"],但漏了端口 5000。Docker 客户端对地址匹配要求非常严格,端口不一致,配置就无效。

7.2 报错:"x509: certificate signed by unknown authority"

这个错说明服务端确实上了 HTTPS,但客户端不信任服务端使用的证书。排查链路如下:

  1. 检查服务端证书是否过期:openssl x509 -in /opt/registry/certs/registry.crt -noout -dates
  2. 检查证书的 SAN 是否与访问地址匹配:openssl x509 -in /opt/registry/certs/registry.crt -noout -text | grep -A 1 "Subject Alternative Name"
  3. 确认客户端的信任证书已正确安装到系统 CA 目录。

一个细节:如果你在 daemon.json 里同时配置了insecure-registries和证书信任,Docker 客户端会优先采用 insecure 方式,导致证书校验被跳过。这种情况不会报错,但会带来安全问题,所以最好别这么干。

7.3 镜像 push 到一半报错:"blob upload unknown"

这个错出现时,我第一反应是磁盘满了。用df -h一看,果不其然,/opt/registry/data对应的分区使用率 100%。这个错误的根因是,Registry 在接收镜像层时,会把 blob 临时写入磁盘,磁盘空间不够,上传中断。

解决办法有两个层次:

  • 短期清理磁盘空间,删掉无用日志或大文件。
  • 从根本上扩容或迁移 Registry 存储目录到更大的数据盘。

存储目录迁移其实很简单,因为 Registry 的数据就是/opt/registry/data下的文件,把整个目录 rsync 到新盘,再修改挂载路径重启容器即可:

# 停容器 docker stop registry docker rm registry # 迁移数据 rsync -avP /opt/registry/data /data/registry/ # 用新路径启动容器 docker run -d \ --name registry \ --restart=always \ -p 5000:5000 \ -v /data/registry:/var/lib/registry \ -v /opt/registry/certs:/certs \ -v /opt/registry/auth:/auth \ -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/registry.crt \ -e REGISTRY_HTTP_TLS_KEY=/certs/registry.key \ -e REGISTRY_AUTH=htpasswd \ -e REGISTRY_AUTH_HTPASSWD_REALM=Registry_Realm \ -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \ -e REGISTRY_STORAGE_DELETE_ENABLED=true \ registry:2

7.4 磁盘空间回收:GC 的坑与正确姿势

很多人在 Registry 上删除镜像,用的是 API 或直接删文件。直接删文件是最危险的,Registry 的存储结构是内容寻址的,你删了某个 blob 文件,可能导致其他镜像拉取时损坏。

正确姿势是分两步走:

第一步,通过 API 删除镜像的 manifest 引用。先获取 digest:

# 列出镜像的 tags curl -u admin:'你的密码' https://192.168.1.100:5000/v2/nginx/tags/list # 获取指定 tag 的 manifest digest curl -u admin:'你的密码' \ -H "Accept: application/vnd.docker.distribution.manifest.v2+json" \ https://192.168.1.100:5000/v2/nginx/manifests/1.24 \ -I

响应头里的Docker-Content-Digest就是 digest 值。然后用 DELETE 请求删除这个 manifest:

curl -u admin:'你的密码' \ -X DELETE \ https://192.168.1.100:5000/v2/nginx/manifests/<上一步得到的digest>

注意:没开启REGISTRY_STORAGE_DELETE_ENABLED=true的话,这步会直接 405。

第二步,执行垃圾回收,清理无引用的 blob 层。Registry 官方提供的 GC 命令需要在容器内手动运行:

docker exec -it registry bin/registry garbage-collect /etc/docker/registry/config.yml

遇到老的 registry 镜像,路径也可能是/bin/registry。执行完成后,会有输出列出哪些存储层被标记删除。

GC 有个比较坑的特性:GC 期间 Registry 需要进入只读模式,否则可能出现并发读写导致数据不一致。官方建议是停容器再跑 GC,但这样会中断服务。如果你的镜像仓库承载着线上发布任务,最好挑业务低峰期操作,或者先临时摘掉服务再执行 GC。

后来我为了防止磁盘被撑爆,写了个 crontab 脚本,每周四凌晨两点检查磁盘使用率,超过 80% 就自动执行一次 GC,顺手推送一个告警消息到企业微信。这个脚本你自己写也很简单,关键是理解了 GC 的原理之后就不会瞎操作了。

8. 日常维护的几点个人经验

仓库上线这段时间,我总结了几条值得提的日常维护经验,都是实践里趟出来的:

镜像命名规范要提前定好。团队里每个人都用自己的习惯命名镜像,仓库很快就会乱成一锅粥。我推荐格式是<仓库地址>/<团队名>/<应用名>:<版本>,并且统一要求版本标签必须带完整版本号,禁止用latest上生产。原因很简单:latest 标签是可以被覆盖的,一旦覆盖,你没法保证线上环境拉到的就是你测试通过的那个版本。哪怕多花一步打标签,也值得。

定期备份数据目录。/opt/registry/data是仓库的全部身家,丢了它等于所有镜像全部蒸发。建议每天凌晨用 rsync 把数据目录同步到另一台机器或对象存储,保留 7 天版本。恢复时只需要把目录放回去再启动容器,过程十分钟以内。

日志和监控要安排上。Registry 容器默认会把访问日志输出到 stdout,docker logs registry能看到所有 pull / push 请求。但在关键时刻,比如排查"谁把 latest 标签覆盖了",你会发现日志里没有用户身份信息。因此我给 Nginx 反代加了一层访问日志,记录客户端的 IP 和请求时间,排查效率高了很多。

不要在一棵树上吊死。Registry 官方镜像只是诸多实现之一,如果你后续要跨机房复制镜像,或者需要更细粒度的权限管理,Harbor、Nexus 都可以作为替代方案。存储在后端的实现是兼容的,迁移起来并不痛苦。先把眼前的需求满足好,不要一开始就上重型的全家桶。

这些经验没有一条来自官方文档,全是运维过程中一点点攒出来的。其实玩 Docker Registry 就是这样:真正难的不是启动一个容器,而是它上线之后能不能稳定地服务好你的团队,在故障面前能不能快速恢复。把这套东西想明白了,私有仓库才真正成为你基础设施的一部分,而不是又一个需要操心的临时组件。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/8 4:17:03

本地部署多模态模型实战:16G显存优化Qwen2.5-VL,性能直追云端

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/8 4:16:02

技术博客写作:从项目标题到摘要的关键准备方法

当前输入中“项目标题”显示为占位符“点击输入文字”&#xff0c;且没有提供项目正文、关键词、摘要描述等有效素材&#xff0c;我无法据此生成一篇真实可用的 CSDN 技术教程。为避免编造技术主题、虚构版本和项目信息&#xff0c;请补充以下内容后我再为你输出完整博文&#…

作者头像 李华
网站建设 2026/9/8 4:15:24

三模机械键盘选购与配置指南:从概念到实操

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/8 4:14:39

海尔空调扇HFL-LG1822R3203评测:无叶设计强效制冷,节能降温新选择

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/8 4:13:47

我的世界RPG服务器入门与运维:从进服准备到百人在线优化

八月大型 RPG 服务器更新&#xff0c;最能抓住眼球的关键词是“百人在线”“挂机不肝”和“世界 Boss”。如果你玩原版游戏偏多&#xff0c;第一次进这种服务器会有点不适应&#xff1a;职业、等级、领地、装备、Boss 机制全都要重新学&#xff1b;如果你是零基础新手&#xff…

作者头像 李华
网站建设 2026/9/8 4:12:25

QEMU CPU建模实践:为ARM64自定义CPU模型并验证内核启动

你是不是也遇到过这种局面&#xff1a;一块新CPU的硬件开发板还没到手&#xff0c;软件团队已经拿着数据手册催着要开发环境&#xff1b;或者手里有一颗自研IP&#xff0c;想提前把内核、BSP、RTOS的适配问题消灭掉&#xff0c;而不是等板卡回来后临时抓瞎。我在这类项目里折腾…

作者头像 李华