Docker 供应链安全:SBOM 与镜像签名落地

背景 镜像漏洞扫描只是起点。上线前还需要回答:这个镜像是谁构建的,包含了什么依赖,是否被篡改。 落地步骤 构建后生成 SBOM 对镜像做签名 部署侧验证签名 syft packages ghcr.io/org/app:latest -o spdx-json > sbom.json cosign sign ghcr.io/org/app:latest cosign verify ghcr.io/org/app:latest 总结 供应链安全要形成闭环:生成、签名、验证,缺一不可。 可观测运行时,也要可追溯构建时。

2026年5月2日 · 1 分钟 · BvBeJ

Docker Compose:本地与线上环境一致性实践

背景 很多部署问题,其实在本地就埋下了: 本地依赖版本和线上不同 环境变量缺省值不一致 本地绕过了鉴权或网络策略 一个简单做法 用 Compose profile 区分场景,但保持核心依赖一致。 services: app: build: . env_file: .env depends_on: [db, redis] db: image: postgres:16 redis: image: redis:7 总结 环境一致性不是“完全一样”,而是“关键契约一致”。 只要契约一致,很多线上问题能在开发期提前暴露。 部署质量往往从本地开发流程就开始决定了。

2026年4月28日 · 1 分钟 · BvBeJ

Docker + BuildKit:CI 构建提速实战

背景 CI 最容易浪费时间的阶段之一,就是镜像构建。 常见慢点: 每次都重新下载依赖 layer 顺序不合理导致缓存失效 多架构构建没有缓存复用 BuildKit 的关键能力 cache mount 并行构建 远程缓存导入导出 # syntax=docker/dockerfile:1.7 FROM golang:1.22-alpine AS builder WORKDIR /app COPY go.mod go.sum ./ RUN --mount=type=cache,target=/go/pkg/mod go mod download COPY . . RUN --mount=type=cache,target=/root/.cache/go-build \ CGO_ENABLED=0 GOOS=linux go build -o app . GitHub Actions 示例 - uses: docker/setup-buildx-action@v3 - uses: docker/build-push-action@v6 with: context: . push: true tags: ghcr.io/org/app:latest cache-from: type=registry,ref=ghcr.io/org/app:buildcache cache-to: type=registry,ref=ghcr.io/org/app:buildcache,mode=max 总结 提速的核心不是换机器,而是设计好缓存路径。 构建系统越早做缓存治理,团队长期效率越高。 CI 慢不是宿命,很多时候只是缓存没被认真设计。

2026年4月25日 · 1 分钟 · BvBeJ

Docker BuildKit 提速:缓存策略的正确打开方式

慢构建的根因 很多项目 Docker 构建慢,不是机器不够快,而是缓存命中策略有问题: 频繁变动的文件放在前面导致层失效 依赖下载每次重来 多阶段构建没有复用中间层 先调整 Dockerfile 顺序 典型 Node 项目可参考: FROM node:20-alpine AS deps WORKDIR /app COPY package.json package-lock.json ./ RUN npm ci FROM node:20-alpine AS builder WORKDIR /app COPY --from=deps /app/node_modules ./node_modules COPY . . RUN npm run build FROM nginx:alpine COPY --from=builder /app/dist /usr/share/nginx/html 先拷贝依赖清单再安装,能最大化命中缓存层。 用 BuildKit 缓存挂载 RUN --mount=type=cache,target=/root/.cache/go-build \ --mount=type=cache,target=/go/pkg/mod \ go build -o app ./cmd/server 这类挂载尤其适合 Go/Rust 的依赖与编译缓存。 CI 中的实践 使用远程缓存导入导出 主分支构建作为缓存热源 避免无意义的 --no-cache 小结 镜像构建优化不是玄学,核心就三点: 层次顺序 缓存挂载 CI 缓存复用 把这三点做好,开发反馈速度会提升一个量级。

2026年4月21日 · 1 分钟 · BvBeJ

Docker 镜像安全与瘦身:从能跑到适合上线

背景 上一篇聊了 Docker 多阶段构建,重点是镜像体积和构建效率。 但把镜像做小,只解决了一半问题。真正要上线时,还得继续问几个更现实的问题: 镜像里有没有不该带进去的工具 容器是不是还在用 root 运行 依赖包有没有已知漏洞 基础镜像是不是长期没人维护 很多项目的 Dockerfile 确实“能跑”,但离“适合上线”还差不少。 小镜像通常也更安全 这不是绝对规律,但大体成立。 原因很简单: 装得越多,攻击面越大 多余工具越多,漏洞概率越高 调试方便的环境,往往也更容易被滥用 所以镜像瘦身和安全加固,在很多时候是同一个方向上的事情。 不要默认用 root 运行 很多 Dockerfile 最容易忽略的一点,就是进程默认是 root。 FROM alpine:3.20 WORKDIR /app COPY myapp /app/myapp ENTRYPOINT ["/app/myapp"] 这份文件能跑,但容器里的进程权限过大。 更稳妥的方式是显式创建低权限用户: FROM alpine:3.20 RUN addgroup -S appgroup && adduser -S appuser -G appgroup WORKDIR /app COPY myapp /app/myapp USER appuser ENTRYPOINT ["/app/myapp"] 这样即使应用被利用,攻击者拿到的默认权限也会更低。 基础镜像要尽量克制 基础镜像选型很影响最终的安全边界。 常见选择大概是: ubuntu / debian:通用,但内容更多 alpine:体积小,适合简单运行时 distroless:更克制,适合生产环境 scratch:最小,但调试和兼容性要求更高 如果你的程序是静态编译的 Go 服务,通常可以考虑 scratch 或 distroless。 ...

2026年4月16日 · 2 分钟 · BvBeJ

Docker 多阶段构建:让你的镜像小而美

从一个真实案例说起 之前帮一个项目 Dockerize,初始镜像 800MB,每次部署慢得让人怀疑人生。后来用多阶段构建优化完,8MB,部署时间从 3 分钟变成 10 秒。 这篇文章讲讲多阶段构建的原理和实战技巧。 为什么镜像那么大 看个典型 Dockerfile: FROM golang:1.22 WORKDIR /app COPY . . RUN go mod download RUN go build -o myapp . ENTRYPOINT ["./myapp"] 问题在哪? golang:1.22 镜像本身就 800MB+,因为包含了完整的编译工具链 你的源代码、依赖缓存、编译中间产物全在里面 运行一个简单程序,凭什么需要 gcc、git、make ? 多阶段构建:原理很简单 Dockerfile 可以有多个 FROM 指令,每个阶段是独立的。前面的阶段可以复制文件到后面,最终镜像只包含最后一个阶段的内容。 # 第一阶段:构建 FROM golang:1.22 AS builder WORKDIR /app COPY . . RUN go mod download RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-w -s" -o myapp . # 第二阶段:运行 FROM alpine:3.19 RUN addgroup -S appgroup && adduser -S appuser -G appgroup WORKDIR /app COPY --from=builder /app/myapp . USER appuser ENTRYPOINT ["./myapp"] 关键点: ...

2026年4月15日 · 3 分钟 · BvBeJ