1 回答

TA貢獻1873條經(jīng)驗 獲得超9個贊
當您使用以下命令在arm7映像的amd64系統(tǒng)上運行構(gòu)建時:
docker build -t registry.gitlab.com/company/edge_to_bc:armhf .
它將使用基礎(chǔ)映像并在該映像中運行 amd64 的命令。因此,即使您的單個edge_to_bc二進制文件可以交叉編譯,圖像的其余部分也不會。接下來,二進制編譯命令本身看起來像是鏈接到庫,而這些庫很可能不在您的最終映像中。您可以運行l(wèi)dd edge_to_bc查看這些鏈接,如果它們丟失,您將收到文件未找到錯誤。
在我自己的交叉編譯測試中,我在 19.03.0-rc2 上使用 BuildKit、Buildx 和一些實驗性功能,因此其中的某些部分不向后兼容,但希望對您有所幫助。我使用多階段構(gòu)建來避免在 docker 之外進行編譯,然后進行第二次構(gòu)建。我還指定了構(gòu)建主機的平臺,并使用目標架構(gòu)和操作系統(tǒng)變量來配置交叉編譯。在這種情況下,我使用了完全靜態(tài)鏈接的二進制文件,因此沒有要包含的庫,并且在最終發(fā)布映像中僅使用復(fù)制命令,我避免了在不同平臺上運行構(gòu)建的問題。
# syntax=docker/dockerfile:experimental
# ^ above line must be at the beginning of the Dockerfile for BuildKit
# --platform pulls an image for the build host rather than target OS/Arch
FROM --platform=$BUILDPLATFORM golang:1.12-alpine as dev
RUN apk add --no-cache git ca-certificates
RUN adduser -D appuser
WORKDIR /src
COPY . /src/
CMD CGO_ENABLED=0 go build -o app . && ./app
# my dev stage is separate from build to allow mounting source and rebuilding
# on developer machines
FROM --platform=$BUILDPLATFORM dev as build
ARG TARGETPLATFORM
ARG TARGETOS
ARG TARGETARCH
# --mount is an experimental BuildKit feature
RUN --mount=type=cache,id=gomod,target=/go/pkg/mod/cache \
--mount=type=cache,id=goroot,target=/root/.cache/go-build \
CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} \
go build -ldflags '-w -extldflags -static' -o app .
USER appuser
CMD [ "./app" ]
# this stage will have the target OS/Arch and cannot have any RUN commands
FROM scratch as release
COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=build /etc/passwd /etc/group /etc/
COPY --from=build /src/app /app
USER appuser
CMD [ "/app" ]
FROM scratch as artifact
COPY --from=build /src/app /app
FROM release
為了構(gòu)建這個,我可以使用 BuildKit 運行一次性構(gòu)建命令:
DOCKER_BUILDKIT=1 docker build --platform=linux/amd64 -f Dockerfile -t golang-app:amd64 .
DOCKER_BUILDKIT=1 docker build --platform=linux/arm64 -f Dockerfile -t golang-app:arm64 .
但更好的是 Buildx 版本,它創(chuàng)建了一個可以在多個平臺上運行的多架構(gòu)映像。這確實需要您推送到注冊表服務(wù)器:
docker buildx build -f Dockerfile --platform linux/amd64,linux/arm64 \
-t ${docker_hub_id}/golang-app:multi-arch --output type=registry .
對于您的場景,您可以將 arm64 的引用替換為您自己的架構(gòu)。該--platform選項在我運行的許多命令中被列為實驗性選項,因此您可能需要在 /etc/docker/daemon.json 文件中配置以下內(nèi)容才能啟用:
{ "experimental": true }
我相信這需要完全重新啟動 docker 守護進程 ( systemctl restart docker),而不僅僅是重新加載才能生效。
為了從構(gòu)建中提取工件(特定架構(gòu)的編譯二進制文件),我使用:
docker build -f Dockerfile --target artifact -o type=local,dest=. .
這會將工件階段(單個二進制文件)的內(nèi)容輸出到本地目錄。
以上是 Docker 構(gòu)建多架構(gòu)鏡像的方法列表中的選項 3。
選項 1 是使用 binfmt_misc 配置 qemu 來為不同平臺構(gòu)建和運行映像。我還無法通過 Buildx 在 Linux 上實現(xiàn)這一點,但 Docker 已經(jīng)在 Mac 上實現(xiàn)了這一點,您也許可以找到有關(guān)他們在 LinuxKit 項目中所做的更多詳細信息。如果您需要運行命令并安裝其他工具作為構(gòu)建的一部分,而不僅僅是交叉編譯單個靜態(tài)鏈接的二進制文件,那么根據(jù)您的情況使用 qemu 可能是理想的選擇。
選項 2 是在目標平臺上運行構(gòu)建,正如您所看到的,效果很好。使用Buildx,您可以添加多個構(gòu)建節(jié)點,每個平臺最多一個,從而允許您從單個位置(CI 服務(wù)器)運行構(gòu)建。
- 1 回答
- 0 關(guān)注
- 258 瀏覽
添加回答
舉報