构建多平台
我们在构建单平台基本没有什么压力, 但我们的服务器从单架构转变成多平台架构时, 那么就会遇到几点挑战:
- 打包的二进制文件要支持多平台
- 运行镜像的系统支持你的软件架构
认识一下这个Dockerfile的架构关键参数:
- TARGETPLATFORM: 构建镜像的目标平台,例如
linux/amd64,linux/arm/v7,windows/amd64。 - TARGETOS:
TARGETPLATFORM的 OS 类型,例如linux,windows - TARGETARCH:
TARGETPLATFORM的架构类型,例如amd64,arm - TARGETVARIANT:
TARGETPLATFORM的变种,该变量可能为空,例如v7 - BUILDPLATFORM: 构建镜像主机平台,例如
linux/amd64 - BUILDOS:
BUILDPLATFORM的 OS 类型,例如linux - BUILDARCH:
BUILDPLATFORM的架构类型,例如amd64 - BUILDVARIANT:
BUILDPLATFORM的变种,该变量可能为空,例如v7
当我们在构建多架构时就需要考虑以上两点了
下载依赖
注意, go mod download -x和go mod tidy是不同, 第一个是只下载全部依赖, 不会修改go.mod和go.sum,而go mod tidy是需要对文件进行写操作的, 当你需要使用go mod tidy时会遇到权限被拒绝的情况, 因为docker bind默认是只读的. 那么你如果需要修改, 那么就需要添加读写权限, 即rw
--mount=type=bind,source=go.mod,target=go.mod,rw \--mount=type=bind,source=go.sum,target=go.sum,rw \# syntax=docker/dockerfile:1
ARG GO_IMAGE=golang:1.24.0-alpine3.21FROM --platform=$BUILDPLATFORM golang:alpine AS compile
ARG TARGETOS=linuxARG TARGETARCHARG SERVICEARG VERSION=devARG GOPROXY=https://goproxy.cn,directARG CGOENABLED=0
WORKDIR /build
# 仅复制根模块文件COPY go.mod go.sum ./
RUN --mount=type=cache,target=/go/pkg/mod \ --mount=type=bind,source=go.mod,target=go.mod \ --mount=type=bind,source=go.sum,target=go.sum \ GOOS=$TARGETOS \ GOARCH=$TARGETARCH \ CGOENABLED=$CGOENABLED \ go mod download -x
# 复制全部代码COPY . .
RUN echo "TARGETOS=${CGO_ENABLED}"RUN echo "CGO_ENABLED=${CGO_ENABLED}"
# 编译指定服务(注意路径调整)RUN --mount=type=cache,target=/go/pkg/mod \ --mount=type=cache,target=/root/.cache/go-build \ CGO_ENABLED=${CGO_ENABLED} \ go build -ldflags="-X main.Version=${VERSION}" -o /app/${SERVICE} ./application/${SERVICE}/cmd/${SERVICE}
# 使用最小化运行时镜像FROM alpine:3.21 AS final
ARG SERVICEENV TZ=Asia/Shanghai
RUN apk add --no-cache tzdata ca-certificates && \ ln -sf /usr/share/zoneinfo/${TZ} /etc/localtime && \ echo ${TZ} > /etc/timezone
COPY --from=compile /app/${SERVICE} /app/service
EXPOSE 30003 30004
ENTRYPOINT ["/app/service"]Kratos 大仓模式的多平台
.PHONY: docker-deployx# 使用 docker 构建多平台架构镜像docker-deployx: @echo "构建的微服务: $(SERVICE)" @echo "平台1: $(ARM64)" @echo "平台2: $(AMD64)" @echo "镜像名: $(REPOSITORY):$(VERSION)" docker buildx build . \ -f application/$(SERVICE)/Dockerfile \ --progress=plain \ -t $(REGISTER)/$(REPOSITORY):$(VERSION) \ --build-arg SERVICE=$(SERVICE) \ --build-arg CGOENABLED=$(CGOENABLED) \ --build-arg GOIMAGE=$(GOIMAGE) \ --build-arg VERSION=$(VERSION) \ --platform $(ARM64),$(AMD64) \ --pushmake docker-deployx SERVICE=user