搭建Docker Registry私有仓库

一、概述

本文将详细介绍如何在本地搭建一个 Docker 私有 Registry 仓库,并实现镜像的上传和管理。通过私有仓库,可以方便地在本地网络中存储和分发 Docker 镜像,提高开发和部署效率。

二、搭建步骤

(一)下载Docker Registry镜像

1. 命令:

2. 解析:

  • docker pull 是 Docker 的命令,用于从 Docker Hub 下载指定的镜像。
  • registry 是 Docker 官方提供的 Registry 镜像,用于搭建私有仓库。
  • 默认情况下,docker pull 会下载最新版本的镜像(latest 标签)。
(二)启动Docker Registry容器

1. 命令:

2. 解析:

  • -d:表示以守护进程模式运行容器(后台运行)。
  • -p 5000:6000:将容器的 5000 端口映射到宿主机的 6000 端口,用于访问私有仓库。
  • --restart=always:设置容器在退出后自动重启,确保仓库服务始终可用。
  • --name registry:为容器指定名称 registry,便于后续管理。
  • registry:指定使用的镜像名称(即之前下载的 registry 镜像)。

3. 验证容器是否启动成功:

如果看到名为 registry 的容器正在运行,并且端口映射正确,说明启动成功。

(三)配置Docker客户端以信任私有仓库

由于私有仓库默认使用 HTTPS 协议,Docker 客户端需要配置为信任该仓库。

编辑 /etc/docker/daemon.json 文件:

添加以下内容:

insecure-registries:指定不安全的仓库地址,允许 Docker 客户端通过 HTTP 协议访问该地址。

重启 Docker 服务:

重启 Docker 服务后,配置生效。

如果使用的是 Docker Desktop 则参考下图修改:

(四)上传镜像到私有仓库

1. 标记镜像:

  • docker image tag:用于为镜像重新标记一个新的名称和标签。
  • nginx:latest:本地已有的镜像名称和标签。
  • 10.10.10.189:6000/docker.io/library/nginx:latest:目标仓库地址和镜像名称。

2. 推送镜像到私有仓库:

  • docker push:将标记后的镜像推送到指定的仓库地址。
  • 如果推送成功,会显示镜像层的上传进度和最终的摘要信息。
(五)验证镜像是否上传成功

通过 API 查看仓库中的镜像:

三、常见问题及解决方法

(一)无法连接到私有仓库

1. 问题描述:

在推送或拉取镜像时,可能会遇到以下错误:

2. 解决方法:

  • 确保 /etc/docker/daemon.json 文件中正确配置了 insecure-registries。
  • 确保 Docker 服务已重启。
  • 确保仓库地址正确,且防火墙允许访问 6000 端口。
(二)网络问题导致无法解析地址

1. 问题描述: 如果尝试访问 http://10.10.10.189:6000 或 https://10.10.10.189:6000/v2/ 时,可能会遇到解析失败的问题。

2. 解决方法:

  • 检查仓库地址是否正确,确保 IP 地址和端口无误。
  • 确保网络连接正常,可以尝试 ping 或 curl 测试连通性。
  • 如果问题仍然存在,可能是网络配置或防火墙限制,建议检查网络设置或联系网络管理员。
(三)是否可以使用 Podman 替代

目前测试是不可以的,在推送的时候会报错引用异常,找不到某些引用。

比如如下报错:

使用 docker 执行上述命令不会报错。

参考链接


通过共享内存优化Flutter外接纹理的渲染性能,实时渲染不是梦

前言

看了咸鱼这篇《万万没想到——flutter这样外接纹理》的文章,我们了解到 Flutter 提供一种机制,可以将 Native 的纹理共享给 Flutter 来进行渲染。但是,由于 Flutter 获取 Native 纹理的数据类型是 CVPixelBuffer,导致 Native 纹理需要经过 GPU->CPU->GPU 的转换过程消耗额外性能,这对于需要实时渲染的音视频类需求,是不可接受的。

闲鱼这边的解决方案是修改了 Flutter Engine 的代码,将 FlutterGL 环境和 nativeGL 环境通过 ShareGroup 来联通,避免2个环境的纹理传递还要去 CPU 内存绕一圈。此方案能够解决内存拷贝的性能问题,但暴露 FlutterGL 环境,毕竟是一个存在风险的操作,给以后的 Flutter 渲染问题定位也增加了复杂度。所以,有没有一个完美、简便的方案呢?答案就是利用 CVPixelBuffer 的共享内存机制。

Flutter外接纹理的原理

先回顾下前置知识,看看官方提供的外接纹理机制究竟是怎样运行的。

图中红色块,是我们自己要编写的 Native 代码,黄色是 Flutter Engine 的内部代码逻辑。整体流程分为注册纹理,和整体的纹理渲染逻辑。

注册纹理
  1. 创建一个对象,实现FlutterTexture协议,该对象用来管理具体的纹理数据
  2. 通过FlutterTextureRegistry来注册第一步的FlutterTexture对象,获取一个flutter纹理id
  3. 将该id通过channel机制传递给dart侧,dart侧就能够通过Texture这个widget来使用纹理了,参数就是id
纹理渲染
  1. dart侧声明一个Texture widget,表明该widget实际渲染的是native提供的纹理
  2. engine侧拿到layerTree,layerTree的TextureLayer节点负责外接纹理的渲染
  3. 首先通过dart侧传递的id,找到先注册的FlutterTexture,该flutterTexture是我们自己用native代码实现的,其核心是实现了copyPixelBuffer方法
  4. flutter engine调用copyPixelBuffer拿到具体的纹理数据,然后交由底层进行gpu渲染

CVPixelBuffer格式分析

一切问题的根源就在这里了:CVPixelBuffer。从上面flutter外接纹理的渲染流程来看,native纹理到flutter纹理的数据交互,是通过 copyPixelBuffer 传递的,其参数就是 CVPixelBuffer。而前面咸鱼文章里面说的性能问题,就来自于纹理与 CVPixelBuffer 之间的转换。

那么,如果 CVPixelBuffer 能够和OpenGL的纹理同享同一份内存拷贝,GPU -> CPU -> GPU的性能瓶颈,是否就能够迎刃而解了呢?其实我们看一下flutter engine里面利用CVPixelBuffer来创建纹理的方法,就能够得到答案:

Flutter Engine是使用 CVOpenGLESTextureCacheCreateTextureFromImage 这个接口来从 CVPixelBuffer 对象创建OpenGL纹理的,那么这个接口实际上做了什么呢?我们来看一下官方文档

This function either creates a new or returns a cached CVOpenGLESTextureRef texture object mapped to the CVImageBufferRef and associated parameters. This operation creates a live binding between the image buffer and the underlying texture object. The EAGLContext associated with the cache may be modified to create, delete, or bind textures. When used as a source texture or GL_COLOR_ATTACHMENT, the image buffer must be unlocked before rendering. The source or render buffer texture should not be re-used until the rendering has completed. This can be guaranteed by calling glFlush().

从文档里面,我们了解到几个关键点:

  1. 返回的纹理对象,是直接映射到了CVPixelBufferRef对象的内存的
  2. 这块buffer内存,其实是可以同时被CPU和GPU访问的,我们只需要遵循如下的规则:
    • GPU访问的时候,该 CVPixelBuffer ,不能够处于lock状态。
      使用过pixelbuffer的同学应该都知道,通常CPU操作pixelbuffer对象的时候,要先进行lock操作,操作完毕再unlock。所以这里也容易理解,GPU使用纹理的时候,其必然不能够同时被CPU操作。
    • CPU访问的时候,要保证GPU已经渲染完成,通常是指在 glFlush() 调用之后。
      这里也容易理解,CPU要读写这个buffer的时候,要保证关联的纹理不能正在被OpenGL渲染。

我们用instrument的allocation来验证一下:

instrument的结果,也能够印证文档中的结论。 只有在创建pixelBuffer的时候,才分配了内存,而映射到纹理的时候,并没有新的内存分配。

这里也能印证我们的结论,创建pixelBuffer的时候,才分配了内存,映射到纹理的时候,并没有新的内存分配。

共享内存方案

既然了解到CVPixelBuffer对象,实际上是可以桥接一个OpenGL的纹理的,那我们的整体解决方案就水到渠成了,可以看看下面这个图

关键点在于,首先需要创建pixelBuffer对象,并分配内存。然后在native gl环境和flutter gl环境里面分别映射一个纹理对象。这样,在2个独立的gl环境里面,我们都有各自的纹理对象,但实际上其内存都被映射到同一个CVPixelBuffer上。在实际的每一帧渲染流程里面,native环境做渲染到纹理,而flutter环境里面则是从纹理读取数据。

Demo演示

这里我写了个小demo来验证下实际效果,demo的主要逻辑是以60FPS的帧率,渲染一个旋转的三角形到一个pixelBuffer映射的纹理上。然后每帧绘制完成之后,通知 Flutter 侧来读取这个pixelBuffer对象去做渲染。

核心代码展示如下:

关键代码都添加了注释,这里就不分析了

我们从上面的gif图上可以看到整个渲染过程是十分流畅的,最后看displayLink的帧率也能够达到60FPS。该demo是可以套用到其他的需要CPU与GPU共享内存的场景的。

完整的demo代码在这里flutter_texture

参考链接


通过共享内存优化flutter外接纹理的渲染性能,实时渲染不是梦

ubuntu 24.04编译CEF(Chromium Embedded Framework)

基础知识

CIPD 全称 Chrome Infrastructure Package Deployment (https://chromium.googlesource.com/infra/luci/luci-go/+/main/cipd/README.md),主要用于管理 Google 项目构建中用到的二进制文件(例如编译器之类的),你可以简单的认为是针对大文件的git系统。

CIPD管理的所有文件可以在(https://chrome-infra-packages.appspot.com)上查看。

手动下载( version 参数从 depot_tools/cipd_client_version 读取)

linux-x86-64:
https://chrome-infra-packages.appspot.com/client?platform=linux-amd64&version=git_revision:b1f414539ac10cc67a0250890a38712cc06cf102

windows-x86-64:
https://chrome-infra-packages.appspot.com/client?platform=windows-amd64&version=git_revision:b1f414539ac10cc67a0250890a38712cc06cf102

动手实践

外网构建

国内镜像构建
1. 使用镜像地址替换 Git 仓库

命令执行后的 .gitconfig 文件:

2. 创建 Chromium 项目 DEPSpatch 文件

下载源代码:

执行如下脚本,对 DEPS 文件的下载地址调整为镜像服务器下载地址:

3. 执行编译

参考链接