From 863b54e1064ac000b6f3a61e68a385a2b8c666d3 Mon Sep 17 00:00:00 2001 From: Rowan Manning <138944+rowanmanning@users.noreply.github.com> Date: Thu, 23 Jan 2025 16:08:47 +0000 Subject: [PATCH] fix: allow building ARM64 images in AMD CI jobs You can't use the default `docker build` to build multi-arch images, this is something we need if we want to build ARM-based images in CircleCI. The alternative would be to move _all_ our CircleCI jobs to ARM which is more expensive and a bunch of work. --- plugins/docker/src/tasks/build.ts | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/plugins/docker/src/tasks/build.ts b/plugins/docker/src/tasks/build.ts index cf5ffb9af..3bf60f438 100644 --- a/plugins/docker/src/tasks/build.ts +++ b/plugins/docker/src/tasks/build.ts @@ -15,8 +15,23 @@ export default class DockerBuild extends Task<{ const imageTags = [imageName, ...getImageTagsFromEnvironment(imageOptions)] this.logger.info(`Building image "${imageIdentifier}": with tags ${imageTags.join(', ')}`) try { - const child = spawn('docker', [ + // We need to create a builder so that we're not limited to + // building AMD64 images due to the platform our CircleCI + // builds run on + const childCreate = spawn('docker', [ + 'buildx', + 'create', + '--platform', + imageOptions.platform, + '--use' // This is a shortcut that prevents us having to run `docker buildx use` + ]) + hookFork(this.logger, 'docker-build-create', childCreate) + await waitOnExit('docker-build-create', childCreate) + + const childBuild = spawn('docker', [ + 'buildx', 'build', + '--load', // Without this, the image is not stored and so we can't push it later '--platform', imageOptions.platform, ...imageTags.flatMap((tag) => ['--tag', tag]), @@ -24,8 +39,8 @@ export default class DockerBuild extends Task<{ imageOptions.definition, process.cwd() ]) - hookFork(this.logger, 'docker-build', child) - await waitOnExit('docker-build', child) + hookFork(this.logger, 'docker-build', childBuild) + await waitOnExit('docker-build', childBuild) } catch (err) { if (err instanceof Error) { const error = new ToolKitError('docker build failed to run')