本篇文章介绍了如何使用 osbuilder 生成符合 Dockerfile 最佳实践的 Dockerfile,并生成 image Makefile规则构建镜像。
当前企业应用的部署形态基本都是采用云原生的方式来部署。所谓的云原生部署方式,就是指将服务构建成一个容器镜像,并使用 Kubernetes 进行部署。
在将服务构建成容器镜像时,不仅需要编写 Dockerfile,还需要执行 docker命令基于 Dockerfile 和编译产物来构建出最终的镜像。
本文就来详细介绍下 osbuilder 脚手架,是如何生成符合最佳实践、标准的 Dockerfile,并支持 make image命令,来构建出容器镜像的。

一、Dockerfile 最佳实践
在我的公众号文章 Dockerfile 最佳实践,我详细介绍了如何编写符合最佳实践的 Dockerfile。如果你使用 osbuilder 工具生成项目,osbuilder 工具会为你自动生成符合最佳实践的 Dockerfile 文件。
二、使用 osbuilder 工具生成 Dockerfile
首先需要安装 osbuilder 工具。安装命令如下:
$ go install github.com/onexstack/osbuilder/cmd/osbuilder@latest
$ osbuilder version
接下来只需要执行以下几步,便可以生成能够根据需求生成符合最佳实践的 Dockerfile,并能构建出镜像。
步骤 1:编写项目配置文件
项目的配置文件如下(保存在 /tmp/osdemo.yaml 文件中):
scaffold: osbuilder
version: v0.0.16
metadata:
# 选择二进制文件的部署形式。当前已支持systemd。未来会支持docker、kubernetes,会生产Dockerfile、Kubernetes YAML 等资源
deploymentMethod: kubernetes
image:
# 当指定 deploymentMethod 为 docker、kubernetes 时,构建镜像的地址
registry: docker.io
# 指定 Dockerfile 的生成模式。可选的模式有:
# - none:不生成 Dockerfile。需要自行实现 build/docker/<component_name>/Dockerfile 文件;
# - runtime-only:仅包含运行时阶段(适合已有外部构建产物),适合本地调试;
# - multi-stage:多阶段构建(builder + runtime);
# - combined:同时生成 multi-stage、runtime-only 2 种类型的 Dockerfile:
# - multi-stage:Dockerfile 名字为 Dockerfile
# - runtime-only:Dockerfile 名字为 Dockerfile.runtime-only
dockerfileMode: combined
# 是否采用 distroless 运行时镜像。如果不采用会使用 debian 基础镜像,否则使用 gcr.io/distroless/base-debian12:nonroot
# - true:采用 gcr.io/distroless/base-debian12:nonroot 基础镜像。生产环境建议设置为 true;
# - false:采用 debian:bookworm 基础镜像。测试环境建议设置为 fasle;
distroless: true
# 控制 Makefile 的生成方式。当前支持以下 3 种:
# - none:不生成 makefile
# - structured:生成单个 makefile
# - unstructured:生成结构化的 makefile
makefileMode: unstructured
# 项目创建者名字,用于生成版权信息
author: 孔令飞
# 项目创建者邮箱,用于生成版权信息
email: colin404@foxmail.com
# osbuilder 支持多种应用类型。当前仅支持 Web 服务类型
# 未来会支持:异步任务 Job 类型、命令行工具类型、声明式API服务器类型
webServers:
- binaryName: os-apiserver
# Web Server 使用的框架。当前支持 gin、grpc
# 未来会支持kratos、grpc-gateway、go-zero、kitex、hertz等
webFramework: grpc
# Web Server 后端使用的存储类型。当前支持 memory、mysql
# 未来会支持etcd、redis、sqlite、mongo、postgresql
storageType: memory
# 是否添加健康检查接口
withHealthz: true
# 是否添加用户默认,开启后,有完整的认证、鉴权流程
withUser: false
# 是否生成注册/反注册到腾讯北极星服务中心的代码
withPolaris: false
上面的配置文件中,我们进行了以下配置:
image:
# 当指定 deploymentMethod 为 docker、kubernetes 时,构建镜像的地址
registry: docker.io
# 指定 Dockerfile 的生成模式。可选的模式有:
# - none:不生成 Dockerfile。需要自行实现 build/docker/<component_name>/Dockerfile 文件;
# - runtime-only:仅包含运行时阶段(适合已有外部构建产物),适合本地调试;
# - multi-stage:多阶段构建(builder + runtime);
# - combined:同时生成 multi-stage、runtime-only 2 种类型的 Dockerfile:
# - multi-stage:Dockerfile 名字为 Dockerfile
# - runtime-only:Dockerfile 名字为 Dockerfile.runtime-only
dockerfileMode: combined
# 是否采用 distroless 运行时镜像。如果不采用会使用 debian 基础镜像,否则使用 gcr.io/distroless/base-debian12:nonroot
# - true:采用 gcr.io/distroless/base-debian12:nonroot 基础镜像。生产环境建议设置为 true;
# - false:采用 debian:bookworm 基础镜像。测试环境建议设置为 fasle;
distroless: true
- registry:用来配置镜像的仓库地址;
- dockerfileMode:用来配置镜像的模式:
- multi-stage:Dockerfile 名字为 Dockerfile
- runtime-only:Dockerfile 名字为 Dockerfile.runtime-only
- none:不生成 Dockerfile。需要自行实现 build/docker/<component_name>/Dockerfile 文件;
- runtime-only:仅包含运行时阶段(适合已有外部构建产物),适合本地调试;
- multi-stage:多阶段构建(builder + runtime);
- combined:同时生成 multi-stage、runtime-only 2 种类型的 Dockerfile:
- distroless:用来控制是否使用 distroless 基础镜像。生产环境建议使用 distroless 镜像。测试环境为了排障方便,可以不适用 distroless 镜像。
步骤 2:生成项目
执行以下命令生成项目:
$ osbuilder create project -c /tmp/osdemo.yaml osdemo
步骤 3:生成 REST 资源
$ cd osdemo
$ osbuilder create api --kinds cron_job,job -b os-apiserver
步骤 4:构建 Docker 镜像
在生成的 osdemo 项目中,已经为 os-apiserver 组件生成了 Dockerfile,位于 build/docker/os-apiserver/目录下:
$ ls build/docker/os-apiserver
Dockerfile Dockerfile.runtime-only
- Dockerfile 使用多阶段构建的方式来构建镜像,在 builder 镜像中,编译 Go 源码;
- Dockerfile.runtime-only:在本地编译源码,并被 COPY 到镜像中,适合本地调试。
这里,我们执行以下命令来构建镜像:
$ make protoc # 编译 os-apiserver 的 Protobuf 文件
$ go mod tidy # 下载缺失的依赖包
$ go generate ./... # 生成代码(依赖注入)
$ make image RUNTIME_ONLY=1 # 现在本地编译源码,产出二进制文件,再COPY 到镜像中。
===========> Building binary os-apiserver v0.0.15 for linux amd64
===========> Building docker image os-apiserver v0.0.15 for linux_amd64
[+] Building 3.3s (16/16) FINISHED
... 0.0s
=> => naming to docker.io/osdemo/os-apiserver:v0.0.0
可以看到,上述命令成功构建出了 docker.io/osdemo/os-apiserver:v0.0.0镜像,执行以下命令运行镜像:
$ docker run docker.io/osdemo/os-apiserver:v0.0.0
WARNING: proto: file "auth.proto" is already registered
See https://protobuf.dev/reference/go/faq#namespace-conflict
I1013 12:18:13.514143 7 server.go:66] "Initializing database connection" type="memory"
I1013 12:18:13.515584 7 grpc_server.go:62] "Start to listening the incoming requests" protocol="grpc" addr="[::]:6666"
可以看到,我们可以成功运行镜像。如果你想使用多阶段构建,可以执行以下命令:
$ make image
三、osbuilder 工具生成的 Dockerfile 文件
osbuilder 可以自动生成 4 种类型的 Dockerfile 文件:
(1) 使用 distroless 镜像,本地编译后 COPY 到镜像中,适合本地测试,Dockerfile 如下:
# syntax=docker/dockerfile:1.7
# 0) Build args (overridable in CI)
ARG BUILDER_IMAGE=alpine:3.20
ARG RUNTIME_IMAGE=gcr.io/distroless/base-debian12:nonroot
ARG UID=65532
ARG GID=65532
# 1) Use a lightweight builder image with package manager to fetch tini.
# builder stage does not compile go source files.
FROM ${BUILDER_IMAGE} AS builder
# Work directory
WORKDIR /workspace
# Install minimal tools required to download files securely
RUN apk add --no-cache curl ca-certificates
# Download the static tini binary (example for amd64); use a different file for other architectures
# Then make it executable so it can be used as PID 1 in the final image
RUN curl -fsSL -o /usr/bin/tini https://github.com/krallin/tini/releases/download/v0.19.0/tini-static-amd64 \
&& chmod +x /usr/bin/tini
# 2) Runtime stage
FROM ${RUNTIME_IMAGE} AS runtime
ARG OS
ARG ARCH
ARG UID
ARG GID
# App directory
WORKDIR /app
# Copy artifact and set ownership; numeric UID:GID is more robust
COPY --from=builder --chown=0:0 /usr/bin/tini /usr/bin/tini
COPY --chown=${UID}:${GID} _output/platforms/${OS}/${ARCH}/os-apiserver /app/os-apiserver
# Security: run as non-root
USER ${UID}:${GID}
# Use tini as minimal init to handle signals and reap zombies
ENTRYPOINT ["/usr/bin/tini", "--", "/app/os-apiserver"]
(2) 使用 distroless 镜像,并使用多阶段构建,Dockerfile 如下:
# syntax=docker/dockerfile:1.7
# 0) Build args (overridable in CI)
ARG BUILDER_IMAGE=golang:1.25.0
ARG RUNTIME_IMAGE=gcr.io/distroless/base-debian12:nonroot
ARG UID=65532
ARG GID=65532
# 1) Builder stage
FROM ${BUILDER_IMAGE} AS builder
ARG OS
ARG ARCH
# Optional: install build-time tools (as needed)
# RUN apt-get update && apt-get install -y --no-install-recommends upx && rm -rf /var/lib/apt/lists/*
# Work directory
WORKDIR /workspace
# Install minimal tools required to download files securely
RUN apk add --no-cache curl ca-certificates
# Download the static tini binary (example for amd64); use a different file for other architectures
# Then make it executable so it can be used as PID 1 in the final image
RUN curl -fsSL -o /usr/bin/tini https://github.com/krallin/tini/releases/download/v0.19.0/tini-static-amd64 \
&& chmod +x /usr/bin/tini
# Use Go modules cache - The most important cache optimization
# Copy go.mod and go.sum first to leverage Docker layer cache
COPY go.mod go.sum ./
# Use cache mount to cache Go modules
RUN --mount=type=cache,target=/go/pkg/mod \
--mount=type=cache,target=/root/.cache/go-build \
go mod download
# Copy source code
COPY . .
# Go build parameters (enable CGO if your project needs static linking)
ENV CGO_ENABLED=1 GOOS=${OS} GOARCH=${ARCH} GO111MODULE=on GOCACHE=/root/.cache/go-build GOMODCACHE=/go/pkg/mod
# Build with cache mount for make build
RUN --mount=type=cache,target=/go/pkg/mod \
--mount=type=cache,target=/root/.cache/go-build \
make build BINS=os-apiserver
# 2) Runtime stage
FROM ${RUNTIME_IMAGE} AS runtime
ARG OS
ARG ARCH
ARG UID
ARG GID
# App directory
WORKDIR /app
# Copy artifacts and set ownership; numeric UID:GID is more robust
COPY --from=builder --chown=0:0 /tmp/tini /usr/bin/tini
COPY --from=builder --chown=${UID}:${GID} /workspace/_output/platforms/linux/amd64/os-apiserver /app/os-apiserver
# Security: run as non-root
USER ${UID}:${GID}
# Use tini as minimal init to handle signals and reap zombies
ENTRYPOINT ["/usr/bin/tini", "--", "/app/os-apiserver"]
(3) 不使用 distroless 镜像,本地编译后 COPY 到镜像中,适合本地测试,Dockerfile 如下:
# syntax=docker/dockerfile:1.7
# 0) Build args (overridable in CI)
ARG BUILDER_IMAGE=alpine:3.20
ARG RUNTIME_IMAGE=debian:bookworm
ARG USER=noroot
ARG UID=65532
ARG GID=65532
# 1) Use a lightweight builder image with package manager to fetch tini.
# builder stage does not compile go source files.
FROM ${BUILDER_IMAGE} AS builder
# Work directory
WORKDIR /workspace
# Install minimal tools required to download files securely
RUN apk add --no-cache curl ca-certificates
# Download the static tini binary (example for amd64); use a different file for other architectures
# Then make it executable so it can be used as PID 1 in the final image
RUN curl -fsSL -o /usr/bin/tini https://github.com/krallin/tini/releases/download/v0.19.0/tini-static-amd64 \
&& chmod +x /usr/bin/tini
# 2) Runtime stage
FROM ${RUNTIME_IMAGE} AS runtime
ARG OS
ARG ARCH
ARG USER
ARG UID
ARG GID
# App directory
WORKDIR /app
# Install runtime essentials
RUN apt-get update \
&& apt-get install -y --no-install-recommends ca-certificates tzdata wget curl telnet \
&& rm -rf /var/lib/apt/lists/*
# Security: create a non-root user (ignore if it already exists)
# Use || true to prevent build failures if the group/user already exists in the base image
RUN groupadd -g ${GID} ${USER} 2>/dev/null || true \
&& useradd -u ${UID} -g ${USER} ${USER} 2>/dev/null || true
# Copy artifact and set ownership; numeric UID:GID is more robust
COPY --from=builder --chown=0:0 /usr/bin/tini /usr/bin/tini
COPY --chown=${UID}:${GID} _output/platforms/${OS}/${ARCH}/os-apiserver /app/os-apiserver
# Security: run as non-root
USER ${UID}:${GID}
# Use tini as minimal init to handle signals and reap zombies
ENTRYPOINT ["/usr/bin/tini", "--", "/app/os-apiserver"]
(4) 不使用 distroless 镜像,并使用多阶段构建,Dockerfile 如下:
# syntax=docker/dockerfile:1.7
# 0) Build args (overridable in CI)
ARG BUILDER_IMAGE=golang:1.25.0
ARG RUNTIME_IMAGE=debian:bookworm
ARG USER=noroot
ARG UID=65532
ARG GID=65532
# 1) Builder stage
FROM ${BUILDER_IMAGE} AS builder
ARG OS
ARG ARCH
# Optional: install build-time tools (as needed)
# RUN apt-get update && apt-get install -y --no-install-recommends upx && rm -rf /var/lib/apt/lists/*
# Work directory
WORKDIR /workspace
# Install minimal tools required to download files securely
RUN apk add --no-cache curl ca-certificates
# Download the static tini binary (example for amd64); use a different file for other architectures
# Then make it executable so it can be used as PID 1 in the final image
RUN curl -fsSL -o /usr/bin/tini https://github.com/krallin/tini/releases/download/v0.19.0/tini-static-amd64 \
&& chmod +x /usr/bin/tini
# Use Go modules cache - The most important cache optimization
# Copy go.mod and go.sum first to leverage Docker layer cache
COPY go.mod go.sum ./
# Use cache mount to cache Go modules
RUN --mount=type=cache,target=/go/pkg/mod \
--mount=type=cache,target=/root/.cache/go-build \
go mod download
# Copy source code
COPY . .
# Go build parameters (enable CGO if your project needs static linking)
ENV CGO_ENABLED=1 GOOS=${OS} GOARCH=${ARCH} GO111MODULE=on GOCACHE=/root/.cache/go-build GOMODCACHE=/go/pkg/mod
# Build with cache mount for make build
RUN --mount=type=cache,target=/go/pkg/mod \
--mount=type=cache,target=/root/.cache/go-build \
make build BINS=os-apiserver
# 2) Runtime stage
FROM ${RUNTIME_IMAGE} AS runtime
ARG OS
ARG ARCH
ARG USER
ARG UID
ARG GID
# App directory
WORKDIR /app
# Install runtime essentials
RUN apt-get update \
&& apt-get install -y --no-install-recommends ca-certificates tzdata wget curl telnet \
&& rm -rf /var/lib/apt/lists/*
# Security: create a non-root user (ignore errors if already exists)
# Use || true to avoid build failures when the group/user already exists in base image
RUN groupadd -g ${GID} ${USER} 2>/dev/null || true \
&& useradd -u ${UID} -g ${USER} ${USER} 2>/dev/null || true
# Copy artifacts and set ownership; numeric UID:GID is more robust
COPY --from=builder --chown=0:0 /tmp/tini /usr/bin/tini
COPY --from=builder --chown=${UID}:${GID} /workspace/_output/platforms/linux/amd64/os-apiserver /app/os-apiserver
# Security: run as non-root
USER ${UID}:${GID}
# Use tini as minimal init to handle signals and reap zombies
ENTRYPOINT ["/usr/bin/tini", "--", "/app/os-apiserver"]
四、总结
本篇文章介绍了如何使用 osbuilder 生成符合 Dockerfile 最佳实践的 Dockerfile,并生成 image Makefile规则构建镜像。
AI大模型学习福利
作为一名热心肠的互联网老兵,我决定把宝贵的AI知识分享给大家。 至于能学习到多少就看你的学习毅力和能力了 。我已将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。
一、全套AGI大模型学习路线
AI大模型时代的学习之旅:从基础到前沿,掌握人工智能的核心技能!

因篇幅有限,仅展示部分资料,需要点击文章最下方名片即可前往获取
二、640套AI大模型报告合集
这套包含640份报告的合集,涵盖了AI大模型的理论研究、技术实现、行业应用等多个方面。无论您是科研人员、工程师,还是对AI大模型感兴趣的爱好者,这套报告合集都将为您提供宝贵的信息和启示。

因篇幅有限,仅展示部分资料,需要点击文章最下方名片即可前往获
三、AI大模型经典PDF籍
随着人工智能技术的飞速发展,AI大模型已经成为了当今科技领域的一大热点。这些大型预训练模型,如GPT-3、BERT、XLNet等,以其强大的语言理解和生成能力,正在改变我们对人工智能的认识。 那以下这些PDF籍就是非常不错的学习资源。

因篇幅有限,仅展示部分资料,需要点击文章最下方名片即可前往获
四、AI大模型商业化落地方案

因篇幅有限,仅展示部分资料,需要点击文章最下方名片即可前往获
作为普通人,入局大模型时代需要持续学习和实践,不断提高自己的技能和认知水平,同时也需要有责任感和伦理意识,为人工智能的健康发展贡献力量
567

被折叠的 条评论
为什么被折叠?



