# syntax=docker/dockerfile:1
ARG GO_VERSION=1.21
ARG GOLANGCI_LINT_VERSION=v1.52
FROM --platform=$BUILDPLATFORM golang:${GO_VERSION}-alpine AS base
WORKDIR /go/src
COPY go.mod go.sum ./
RUN --mount=type=cache,target=/go/pkg/mod \
go mod download -x
FROM base as build-client
ARG TARGETOS
ARG TARGETARCH
RUN --mount=type=cache,target=/go/pkg/mod \
--mount=type=bind,target=. \ #挂载代码
GOOS=$TARGETOS GOARCH=$TARGETARCH go build -v -o /bin/client ./cmd/client
FROM base as build-server
ARG TARGETOS
ARG TARGETARCH
ARG APP_VERSION="v0.0.0+unknown"
RUN --mount=type=cache,target=/go/pkg/mod \
--mount=type=bind,target=. \ #挂载代码
GOOS=$TARGETOS GOARCH=$TARGETARCH go build -v -ldflags "-X main.version=$APP_VERSION" -o /bin/server ./cmd/server
FROM scratch AS client
COPY --from=build-client /bin/client /bin/
ENTRYPOINT [ "/bin/client" ]
FROM scratch AS server
COPY --from=build-server /bin/server /bin/
ENTRYPOINT [ "/bin/server" ]
FROM scratch AS binaries
COPY --from=build-client /bin/client /
COPY --from=build-server /bin/server /
FROM golangci/golangci-lint:${GOLANGCI_LINT_VERSION} as lint
WORKDIR /test
RUN --mount=type=bind,target=. \
golangci-lint run
导出构建后的文件
docker build
--output=bin \ #指定导出目录
--target=binaries \ #指定构建阶段
.
多平台构建
docker buildx create --driver=docker-container --name=container
docker buildx build \
--target=binaries \ #指定构建阶段
--output=bin \ #指定导出目录
--builder=container \
--platform=darwin/arm64,windows/amd64,linux/amd64 \
.
Dockerfile中的变量
TARGETOS
和TARGETARCH
--platform=linux/amd64
会被解析为:TARGETOS=linux TARGETARCH=amd64
BUILDPLATFORM
值为当前构建镜像的平台,例如我当前在mac m1平台上编译镜像,则 BUILDPLATFORM=darwin/arm64
构建过程中挂载的坑
RUN --mount=type=cache,target=/go/pkg/mod \
--mount=type=bind,target=. \
GOOS=$TARGETOS GOARCH=$TARGETARCH go build -v -o /bin/client ./cmd/client
当使用 --mount=type=bind,target=.
时 go build -v -o /bin/client
/bin/client 必须用绝对路径且可写,不能是 ./bin/client
否则会出现 mkdir ./bin/: read-only file system
推送到dockerhub遇到的坑
- 有多个dockerhub账号
- 来回切换过
- docker buildx build 加上 --push后,会在历史登陆过的所有账号验证token,导致一直出现 insufficient_scope: authorization failed
- 解决办法
我们在使用buildx前新建了一个builder:docker buildx create --driver=docker-container --name=container
办法就是移除后重建:docker buildx rm container