Skip to content

DockerBuildImage.platform property does not produce correct architecture on cross-platform builds #1241

Description

@dustinschultz

Description

When using DockerBuildImage with the platform property set to build for a different architecture than the host (for example, building linux/amd64 on an ARM Mac), the plugin does not successfully produce an image with the correct architecture.


Environment

  • gradle-docker-plugin version: 9.x (uses docker-java library)
  • Docker version: Docker Desktop 4.x+
  • Host architecture: arm64 (Apple Silicon Mac)
  • Target architecture: linux/amd64

Steps to Reproduce

  1. Create a DockerBuildImage task on an ARM Mac:

    tasks.register("buildAmd64Image", DockerBuildImage::class) {
        inputDir.set(file("build/docker"))
        platform.set("linux/amd64")
        images.set(setOf("myapp:test"))
    }
  2. Run the task:

    ./gradlew buildAmd64Image
  3. Inspect the built image:

    docker inspect myapp:test | jq '.[0].Architecture'

Expected Behavior

The image should be built for the linux/amd64 architecture.
All base images in FROM statements should be pulled for the amd64 platform, and the final image should report:

Architecture: amd64

Actual Behavior

The image is built with an incorrect architecture or causes Docker manifest corruption.
When building on an ARM Mac with platform.set("linux/amd64"), the resulting image does not have the correct amd64 architecture.


Root Cause (Likely)

When DockerBuildImage.platform.set("linux/amd64") is configured, the task does not successfully produce an amd64 image when building on an ARM host.
Testing shows that:

  1. Setting platform.set("linux/amd64")
  2. Building on an ARM Mac (aarch64)
  3. Results in either manifest corruption or incorrect-architecture images

Potential causes include:

  • The docker-java library not properly passing the --platform flag to the Docker daemon
  • The platform property being ignored during base image pulls in multi-stage builds
  • A version-specific issue in docker-java’s BuildImageCmd implementation

Running the Docker CLI directly with:

docker build --platform linux/amd64

consistently produces the correct amd64 image, confirming the problem lies in how gradle-docker-plugin / docker-java handle the platform flag.


Impact

  • Cross-platform builds fail or produce incorrect architecture images
  • Developers on ARM Macs cannot reliably build AMD64 images for deployment
  • May cause manifest corruption when pushing mixed-architecture images to registries

Workaround

Define a custom Gradle task that calls the Docker CLI directly:

abstract class DockerBuildImageCli : DefaultTask() {
    @get:Input
    @get:Optional
    abstract val platform: Property<String>

    @get:InputDirectory
    abstract val dockerfileDir: DirectoryProperty

    @get:Input
    abstract val imageTags: SetProperty<String>

    @TaskAction
    fun buildImage() {
        val args = mutableListOf("build")

        if (platform.isPresent) {
            args.add("--platform")
            args.add(platform.get())
        }

        imageTags.get().forEach { tag ->
            args.add("-t")
            args.add(tag)
        }

        args.add(dockerfileDir.get().asFile.absolutePath)

        project.exec {
            commandLine = listOf("docker") + args
        }
    }
}

This correctly passes --platform to the Docker CLI and produces the expected architecture.


Suggested Fix

Ensure DockerBuildImage properly propagates the --platform flag to the Docker daemon for all build stages, including base-image pulls in multi-stage builds.


Additional Context

Docker CLI documentation confirms that --platform applies to all FROM statements:
🔗 https://docs.docker.com/engine/reference/commandline/build/#platform

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions