Docker / multiple architectures in different stages of a Multi-Stage Dockerfile

85 views Asked by At

I want to build a docker image for aarch64 and an intermediate stage ist to cross compile an application using another stage which builds an amd64 build environment. A simple example works as expected:

FROM alpine AS base
RUN <<EOF
  uname -a
  touch example_file1
EOF

FROM --platform=linux/amd64 alpine AS cross_build_image
RUN <<EOF
  uname -a
  touch example_file2
EOF

FROM base AS release
COPY --from=cross_build_image example_file2 .
RUN <<EOF
  uname -a
EOF

running this with:

docker buildx build --platform linux/arm64 --target release --tag release_image --no-cache --progress=plain .

outputs:

#10 [cross_build_image2/2] RUN <<EOF (uname -a...)
#10 0.058 Linux buildkitsandbox 5.15.133.1-microsoft-standard-WSL2 #1 SMP Thu Oct 5 21:02:42 UTC 2023 x86_64 Linux
#10 DONE 0.1s

#11 [base 2/2] RUN <<EOF (echo uname -a...)
#11 0.088 Linux buildkitsandbox 5.15.133.1-microsoft-standard-WSL2 #1 SMP Thu Oct 5 21:02:42 UTC 2023 aarch64 Linux
#11 DONE 0.1s

#12 [release 1/2] COPY --from=cross_build_image example_file2 .
#12 DONE 0.1s

#13 [release 2/2] RUN <<EOF (echo uname -a...)
#13 0.087 Linux buildkitsandbox 5.15.133.1-microsoft-standard-WSL2 #1 SMP Thu Oct 5 21:02:42 UTC 2023 aarch64 Linux
#13 DONE 0.1s

As you can see, cross_build_image runs correctly with x86_64 and the release is build using aarch64.

But this does not work anymore with the following construct:

FROM alpine AS base
RUN <<EOF
  uname -a
  touch example_file1
EOF

FROM --platform=linux/amd64 base AS cross_build_image
RUN <<EOF
  uname -a
  touch example_file2
EOF

FROM base AS release
COPY --from=cross_build_image example_file2.
RUN <<EOF
  uname -a
EOF

Now it does the following:

#8 [base 2/2] RUN <<EOF (echo uname -a...)
#8 0.075 Linux buildkitsandbox 5.15.133.1-microsoft-standard-WSL2 #1 SMP Thu Oct 5 21:02:42 UTC 2023 aarch64 Linux
#8 DONE 0.1s

#9 [cross_build_image 1/1] RUN <<EOF (echo uname -a...)
#9 0.088 Linux buildkitsandbox 5.15.133.1-microsoft-standard-WSL2 #1 SMP Thu Oct 5 21:02:42 UTC 2023 aarch64 Linux
#9 DONE 0.1s

#10 [release 1/2] COPY --from=cross_build_image example_file2.
#10 DONE 0.0s

#11 [release 2/2] RUN <<EOF (echo uname -a...)
#11 0.091 Linux buildkitsandbox 5.15.133.1-microsoft-standard-WSL2 #1 SMP Thu Oct 5 21:02:42 UTC 2023 aarch64 Linux
#11 DONE 0.1s

As you can see, now everything is built using aarch64. This is not what I expected. But the cross_build_image shall use the same base as the release image, only with different architectures. What am I doing wrong here?

1

There are 1 answers

0
maikelmeyers On

Finally the only (not that nice) solution is this:

FROM alpine AS base
RUN <<EOF
  uname -a
  touch example_file1
EOF

# same installation content AS base
FROM --platform=linux/amd64 alpine AS base_clone
RUN <<EOF
  uname -a
  touch example_file1
EOF

FROM --platform=linux/amd64 base_clone AS cross_build_image
RUN <<EOF
  uname -a
  touch example_file2
EOF

FROM base AS release
COPY --from=cross_build_image example_file2 .
RUN <<EOF
  uname -a
  ls -la
EOF

running this with:

docker buildx build --platform linux/arm64 --target release --tag release_image --no-cache --progress=plain .

This works finally, but you have to code repeat the base.