Skip to content

Commit aaa3765

Browse files
committed
hack: use buildx to cross-build images with docker
When Docker is used and the target architecture differs from the host architecture, buildx is used for cross-building. Depending on the container engine and the target architecture, multiple commands need to be executed to prepare the environment, build the image, and clean up artifacts afterward. To streamline this process, a tasks array (an array of lambdas) has been introduced, its elements are executed sequencally at the end of the container_build function. Signed-off-by: Alexander Bachmann <[email protected]>
1 parent 7a16e9f commit aaa3765

File tree

1 file changed

+36
-17
lines changed

1 file changed

+36
-17
lines changed

hack/build-image

Lines changed: 36 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -203,23 +203,42 @@ def container_engine(cli):
203203

204204
def container_build(cli, target):
205205
"""Construct and execute a command to build the target container image."""
206-
args = [container_engine(cli), "build"]
207-
pkgs_from = PACKAGES_FROM[target.pkg_source]
208-
if pkgs_from:
209-
args.append(f"--build-arg=INSTALL_PACKAGES_FROM={pkgs_from}")
210-
# docker doesn't currently support alt. architectures
211-
if "docker" in args[0]:
212-
if target.arch != host_arch():
213-
raise RuntimeError("Docker does not support --arch")
214-
elif target.arch != host_arch() or FORCE_ARCH_FLAG:
215-
# We've noticed a few small quirks when using podman with the --arch
216-
# option. The main issue is that building the client image works
217-
# but then the toolbox image fails because it somehow doesn't see
218-
# the image we just built as usable. This doesn't happen when
219-
# --arch is not provided. So if the target arch and the host_arch
220-
# are the same, skip passing the extra argument.
221-
args.append(f"--arch={target.arch}")
222-
run(cli, args + create_common_container_engine_args(cli, target), check=True)
206+
eng = container_engine(cli)
207+
tasks = []
208+
209+
# For docker cross-builds we need to use buildx
210+
if "docker" in eng and target.arch != host_arch():
211+
args = [eng, "buildx"]
212+
213+
# Docker's default builder only supports the host architecture.
214+
# Therefore, we need to create a new builder to support other
215+
# architectures, and we must ensure we start with a fresh builder
216+
# that does not contain any images from previous builds.
217+
tasks.append(lambda : run(cli, args + ["rm", target.flat_name()], check=False))
218+
tasks.append(lambda : run(cli, args + ["create", f"--name={target.flat_name()}"], check=True))
219+
220+
tasks.append(lambda : run(cli, args + [
221+
"build",
222+
f"--builder={target.flat_name()}",
223+
f"--platform=linux/{target.arch}",
224+
"--load"] + create_common_container_engine_args(cli, target), check=True))
225+
226+
tasks.append(lambda : run(cli, args + ["rm", target.flat_name()], check=True))
227+
else:
228+
args = [eng, "build"]
229+
if target.arch != host_arch() or FORCE_ARCH_FLAG:
230+
# We've noticed a few small quirks when using podman with the --arch
231+
# option. The main issue is that building the client image works
232+
# but then the toolbox image fails because it somehow doesn't see
233+
# the image we just built as usable. This doesn't happen when
234+
# --arch is not provided. So if the target arch and the host_arch
235+
# are the same, skip passing the extra argument.
236+
args += [f"--arch={target.arch}"]
237+
238+
tasks.append(lambda : run(cli, args + create_common_container_engine_args(cli, target), check=True))
239+
240+
for task in tasks:
241+
task()
223242

224243
def create_common_container_engine_args(cli, target):
225244
args = []

0 commit comments

Comments
 (0)