Linux Containers on macOS: Colima, Apple container, OrbStack

macOS 内核不能直接跑 Linux 容器,所有方案都是先起一个 Linux 虚拟机,再在里面跑容器运行时。区别在于虚拟机怎么起、几个容器共用一台虚拟机、对外提供什么 CLI。 分层 层级 例子 作用 容器运行时 containerd、Docker Engine 拉镜像、起容器,跑在 Linux 里 Mac 上的 Linux 环境 Colima(基于 Lima)、Apple container、OrbStack、Docker Desktop 在 macOS 上提供 Linux 虚拟机,并把 CLI 暴露给宿主 CLI nerdctl、docker、container 用户敲的命令 containerd 和 Colima 不是同一类东西:containerd 是引擎,Colima 负责给 containerd 准备一台 Linux 虚拟机。 Colima 基于 Lima,所有容器共用一台 Linux 虚拟机 运行时可选 docker 或 containerd,选 containerd 时用 nerdctl,和 Linux 服务器上的用法一致 支持 compose(nerdctl compose 或 docker compose),可选内置 k3s MIT 协议,商用免费,只有 CLI brew install colima # native arm64 VM, use Rosetta for amd64 images colima start --arch aarch64 --vm-type vz --vz-rosetta --runtime containerd colima nerdctl -- run --rm hello-world colima list colima stop 注意 --arch x86_64 会让整台虚拟机走模拟,在 Apple Silicon 上很慢。需要 amd64 镜像时,用 arm64 虚拟机加 --platform linux/amd64 构建即可。 ...

Created 15156-10-15 · Updated 15156-10-15 · 2 min · 252 words · -

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 · -

Containerfile

Containerfile, Dockerfile buildkit 默认会查找当前目录的 Containerfile 或者 Dockerfile FROM golang:1.22.0 AS build ENV GO111MODULE on ARG APP_NAME=rssx-api WORKDIR /workdir COPY . . RUN CGO_ENABLED=0 GOOS=linux GOPROXY=https://goproxy.io go build -a -o ${APP_NAME} main.go FROM alpine:3.19.1 AS prod ARG APP_NAME=rssx-api COPY --from=build /workdir/${APP_NAME} /data/${APP_NAME} COPY config.toml config.toml COPY config.toml /data/config.toml ENV APPLICATION_NAME ${APP_NAME} CMD "/usr/local/bin/${APPLICATION_NAME}" FROM golang:1.12.4 AS build ENV GO111MODULE on WORKDIR /go/src/xxx.com/xxx ADD . . ADD cmd cmd ADD internal internal ADD pkg pkg RUN CGO_ENABLED=0 GOOS=linux go build -a cmd/xxx.go FROM alpine AS prod COPY --from=build /go/src/xxx.com/xxx/xxx . # dev ADD configs/xxx.json . CMD ["./xxx"] buildah -f Dockerfile-0 --build-arg foo="bar" 环境变量 设置环境变量 USERNAME 默认值为 admin,后面可以通过docker run -e USERNAME=“XXXXXX"修改,这个环境变量在容器里也可以$USERNAME获取 ...

Created 22226-12-22 · Updated 9096-10-09 · 3 min · 608 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 · -