CNB: Cloud Native Buildpacks 与 Paketo

是什么 Cloud Native Buildpacks(常缩写 CNB)是一套把应用源码或编译产物自动打成 OCI 容器镜像的规范与工具生态,站点在 buildpacks.io。思路类似早年 Heroku、Cloud Foundry 上的 buildpack:平台检测你推上来的是什么(Java jar、Node 项目等),自动选运行时、装依赖、写好启动命令,不必为每种语言手写 Dockerfile。 Paketo(paketo.io)是 CNB 生态里常用的开源实现,提供现成的 builder 镜像和一系列 language buildpack(Java、Node.js、Go、Python 等)。它与 Spring 无隶属关系,但 Spring Boot 的 bootBuildImage / spring-boot:build-image 默认使用 Paketo 的 builder。 CNB ← 规范 + 生态(buildpack / builder / lifecycle) │ ├── Paketo ← 开源实现(Spring Boot 默认路径) ├── Heroku buildpacks └── Google Cloud buildpacks … 调用方: pack CLI、Spring Boot 插件、Tekton、CI … → 拉 builder → 跑 buildpack → 出 OCI 镜像 Spring Boot 侧如何把 fat jar、分层 JAR、jlink 与 Buildpack 串起来,见 Spring Boot Container Packaging。 ...

Created 21216-06-21 · Updated 12126-10-12 · 3 min · 589 words · -

Dockerfile/BuildKit vs CNB: 为什么会有 Cloud Native Buildpacks

问题从哪来 构建容器镜像,最常见的做法是写一个 Dockerfile(或 Containerfile),交给 BuildKit、Buildah、Kaniko 之类的构建器执行。Cloud Native Buildpacks(CNB)则不需要 Dockerfile:把源码或 jar 交给 builder,自动产出 OCI 镜像。 既然 Dockerfile 已经能构建任意镜像,为什么还会出现 CNB?它解决的是 Dockerfile 解决不了的问题,还是别的问题?本文把这几个问题放在一起整理。CNB 的概念与 Paketo 用法见 CNB: Cloud Native Buildpacks 与 Paketo,Dockerfile 写法见 Containerfile。 先说结论:CNB 主要解决的不是「单个镜像能不能构建出来」,而是「几百上千个应用的镜像由谁来写、怎么统一、基础镜像出漏洞后怎么批量修」。这是组织规模上的问题,不是 Dockerfile 语法能力上的问题。 BuildKit 是什么 BuildKit 是 Moby 项目下的构建引擎,Docker Engine 23.0 起在 Linux 上成为 docker build 的默认后端,docker buildx 也基于它。 一个常被忽略的点:BuildKit 本身并不依赖 Dockerfile。它的结构分两层: 前端(frontend):把某种构建描述翻译成 LLB(Low-Level Build definition,一种描述构建步骤的有向无环图)。Dockerfile 只是其中一个前端,Dockerfile 首行的 # syntax=docker/dockerfile:1 指定的就是前端镜像。 求解器(solver):执行 LLB,负责并行、缓存、导出镜像。 flowchart LR DF[Dockerfile] OTHER[其他前端Dagger / Railpack 等] FE[Frontend] LLB[LLB DAG] SOLVER[BuildKit Solver并行 + 缓存] OUT[OCI 镜像 / 本地文件] DF --> FE OTHER --> LLB FE --> LLB --> SOLVER --> OUT 所以更准确的说法是:「Dockerfile 是一种构建描述语言,BuildKit 是执行引擎」。Dagger 的引擎、Railway 的 Railpack 等工具都直接生成 LLB,不写 Dockerfile 也能用 BuildKit。 ...

Created 12126-10-12 · Updated 12126-10-12 · 6 min · 1133 words · -

Docker Network 网络

docker 网络 安装 Docker 时,它会自动创建 3 个网络。可以使用 docker network ls 命令列出这些网络。 $ docker network ls NETWORK ID NAME DRIVER 7fca4eb8c647 bridge bridge 9f904ee27bf5 none null cf03ee007fb4 host host 运行一个容器时,可以使用 the -net 标志指定您希望在哪个网络上运行该容器。 bridge 网络表示所有 Docker 安装中都存在的 docker0 网络。除非使用 docker run --net=<NETWORK> 选项另行指定,否则 Docker 守护进程默认情况下会将容器连接到此网络。在主机上使用 ifconfig命令,可以看到此网桥是主机的网络堆栈的一部分。 none 网络在一个特定于容器的网络堆栈上添加了一个容器。该容器缺少网络接口。 host 网络在主机网络堆栈上添加一个容器。您可以发现,容器中的网络配置与主机相同。 用户定义的网络 您可以创建自己的用户定义网络来更好地隔离容器。Docker 提供了一些默认网络驱动程序来创建这些网络。您可以创建一个新 bridge 网络或覆盖一个网络。也可以创建一个网络插件或远程网络并写入您自己的规范中。 您可以创建多个网络。可以将容器添加到多个网络。容器仅能在网络内通信,不能跨网络进行通信。一个连接到两个网络的容器可与每个网络中的成员容器进行通信。当一个容器连接到多个网络时,外部连接通过第一个 (按词典顺序) 非内部网络提供。 维护记录 时间 修改内容 原因 2026-10-09 修复本地 Hugo 构建的 Raw HTML 警告:代码/配置放入代码块,正文中的尖括号占位符改为行内代码;文件重命名为 docker-network.md;title 改为「Docker Network 网络」;url 改为 docker-network;旧 url 加入 aliases 正文中的 HTML/XML 片段被当作原始 HTML 丢弃;文件名/URL/标题按规范调整

Created 19196-04-19 · Updated 9096-10-09 · 1 min · 82 words · -

Diun: Homelab 容器镜像更新通知

背景 homelab 里不少服务钉在某个镜像 tag 上,上游发了新版本不会自动跟着走。以前靠偶尔看 GitHub Release,或者写脚本去打 releases/latest。后者对把每个版本都标成 pre-release 的项目几乎没用——接口长期停在旧版,等于没监控。 现在改成在 K8s 集群里跑 Diun(Docker Image Update Notifier):盯 registry 里的镜像 tag,出现匹配规则的新稳定版就推 Telegram。它不负责滚动升级,只负责通知。它在服务清单里的位置见 Homelab Services;硬件与集群拓扑见 Homelab 拓扑。 它盯的是 registry,不是正在跑的容器 Diun 用 file provider 读一份 watch 列表,直接问 registry「这个仓库现在有哪些 tag」,不扫描集群里的 Pod。所以: 可以盯 homelab 里跑着的容器(例如 Vaultwarden) 也可以盯并不在集群里跑的软件:只要上游会在打 release 时构建官方镜像,tag 与版本号一一对应,就可以把镜像当发版探针 后者用来补 GitHub releases/latest 的坑。有些项目几乎每个 release 都标 pre-release,那个接口会一直停在旧稳定版;镜像 tag 没有这层过滤。 homelab 部署 跑在独立 namespace diun,由 Argo CD 管(w10n-config 里的 infra/homelab/k8s/diun/)。要点: 项 现网 镜像 Nexus 代理后的 crazymax/diun 检查频率 每 6 小时;启动时再跑一次 通知 Telegram Bot;凭据在 notifications namespace,由 Reflector 反射进 diun 状态 Longhorn PVC 记已经见过的 tag,重启不会把历史版本再推一遍 UI 没有。纯后台 + 推送 首次检查关掉通知(DIUN_WATCH_FIRSTCHECKNOTIF=false),只建基线。之后才对真正的新 tag 发消息。 ...

Created 14146-09-14 · Updated 14146-09-14 · 1 min · 196 words · -

Spring Boot Container Packaging: Fat JAR、分层 JAR 与 Buildpacks

背景 Spring Boot REST API 打成 jar 之后,放进容器常见有三层递进:先有一个能跑的 fat jar,再用分层 JAR 优化 Docker 缓存,最后用 Cloud Native Buildpacks 一键出镜像;若还要缩小运行时,可在 Buildpack 上显式开启 jlink 裁剪 JRE。fat jar 布局与 JarLauncher 见专文 Spring Boot Executable JAR。 Spring Framework 本身几乎不讲容器镜像;相关说明集中在 Spring Boot Reference 的 Packaging → Container Images。本文把分层 JAR、bootBuildImage、Paketo jlink 串成一条阅读路径,并附上官方文档索引。GraalVM Native Image 是另一条路线,见 GraalVM Native Image 简介。 三条路径总览 flowchart TB subgraph build [构建] SRC[源码 mvn package / bootJar] FAT[Fat JAR 可执行 uber jar] LAY[分层 JAR 含 layers.idx] end subgraph deploy [容器化] D1[简单 DockerfileCOPY jar + java -jar] D2[分层 Dockerfilejarmode extract --layers] BP[bootBuildImage / build-imagePaketo Buildpacks] end subgraph runtime [运行时 JVM] JRE[完整 JRE] JLINK[jlink 精简 JREBP_JVM_JLINK_ENABLED] end SRC --> FAT FAT --> LAY FAT --> D1 LAY --> D2 LAY --> BP D1 --> JRE D2 --> JRE BP --> JRE BP -.->|可选| JLINK 路径 典型产物 主要收益 复杂度 Fat jar + 简单镜像 单层 app.jar + JRE 基础镜像 上手最快 低 分层 JAR + Dockerfile 多 COPY 层 + JRE 推送镜像时依赖层可缓存 中 Buildpack(bootBuildImage) OCI 镜像,自动检测 jar 零 Dockerfile、与 Paketo 生态一致 低~中 Buildpack + jlink 同上,运行时 JRE 更小 缩小镜像体积 中(需调 env) 分层 JAR 分层 JAR 在 fat jar 布局不变的前提下,额外写入 BOOT-INF/layers.idx,声明哪些路径属于哪一层、层的写入顺序。Spring Boot 2.3 起默认开启;Maven repackage / Gradle bootJar 的 layered 无需额外配置即可得到。 ...

Created 21216-06-21 · Updated 24246-06-24 · 5 min · 1027 words · -

openvpn docker

openvpn docker export OVPN_DATA="ovpn-data" docker volume create --name $OVPN_DATA docker run -v $OVPN_DATA:/etc/openvpn --log-driver=none --rm kylemanna/openvpn ovpn_genconfig -u udp://home.wiloon.com docker run -v $OVPN_DATA:/etc/openvpn --log-driver=none --rm -it kylemanna/openvpn ovpn_initpki docker run -v $OVPN_DATA:/etc/openvpn -d -p 192.168.50.220:1194:1194/udp --cap-add=NET_ADMIN --name openvpn --restart=always kylemanna/openvpn docker run -v $OVPN_DATA:/etc/openvpn --log-driver=none --rm -it kylemanna/openvpn easyrsa build-client-full client0 nopass docker run -v $OVPN_DATA:/etc/openvpn --log-driver=none --rm kylemanna/openvpn ovpn_getclient client0 > client0.ovpn # Retrieve the client configuration with embedded certificates docker run -v $OVPN_DATA:/etc/openvpn --rm kylemanna/rpi-openvpn ovpn_getclient client0 > client0.ovpn docker run -v $OVPN_DATA:/etc/openvpn -p 1194:1194/udp --privileged -e DEBUG=1 kylemanna/rpi-openvpn server 192.168.255.0 255.255.255.0 verb 3 key /etc/openvpn/pki/private/xxxx.key ca /etc/openvpn/pki/ca.crt cert /etc/openvpn/pki/issued/xxx.crt dh /etc/openvpn/pki/dh.pem tls-auth /etc/openvpn/pki/ta.key key-direction 0 keepalive 10 60 persist-key persist-tun proto udp # Rely on Docker to do port mapping, internally always 1194 port 1194 dev tun0 status /tmp/openvpn-status.log user nobody group nogroup comp-lzo no ### Route Configurations Below route 192.168.254.0 255.255.255.0 ### Push Configurations Below push "block-outside-dns" push "dhcp-option DNS 192.168.50.1" push "comp-lzo no" push "redirect-gateway def1 bypass-dhcp"

Created 29296-04-29 · Updated 29296-04-29 · 1 min · 162 words · -