跳到主要内容

构建多平台

我们在构建单平台基本没有什么压力, 但我们的服务器从单架构转变成多平台架构时, 那么就会遇到几点挑战:

  1. 打包的二进制文件要支持多平台
  2. 运行镜像的系统支持你的软件架构

认识一下这个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.21
FROM --platform=$BUILDPLATFORM golang:alpine AS compile

ARG TARGETOS=linux
ARG TARGETARCH
ARG SERVICE
ARG VERSION=dev
ARG GOPROXY=https://goproxy.cn,direct
ARG 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 SERVICE
ENV 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) \
--push
make docker-deployx SERVICE=user

https://docs.docker.com/build/building/multi-platform/