Repository: docker/buildx (Go)

Issue:
buildx bake ignores "platforms" key in docker-compose.yaml
### Contributing guidelines

- [x] I've read the [contributing guidelines](https://github.com/docker/buildx/blob/master/.github/CONTRIBUTING.md) and wholeheartedly agree

### I've found a bug and checked that ...

- [x] ... the documentation does not mention anything about my problem
- [x] ... there are no open or closed issues that are related to my problem

### Description

`docker buildx bake -f docker-compose.yaml` builds only the native platform, even when the docker compose file lists multiple under the "platforms" key. 

### Steps To Reproduce

Build this docker compose file and inspect the image. 

```
docker buildx bake -f docker-compose.yaml
```

list.manifest.json:
```
{
    "schemaVersion": 2,
    "mediaType": "application/vnd.oci.image.index.v1+json",
    "manifests": [{
            "mediaType": "application/vnd.oci.image.manifest.v1+json",
            "digest": "sha256:854512a7e492982f94a82258ece4eec7aae8bfd061866d8bdddf54b42c118218",
            "size": 480,
            "platform": {
                "architecture": "arm64",
                "os": "linux"
            }
        },
        {
            "mediaType": "application/vnd.oci.image.manifest.v1+json",
            "digest": "sha256:948045a53f60db611f2ec7e5d4637d156e84dd0226c5eb23d346a5caea8211e2",
            "size": 566,
            "annotations": {
                "vnd.docker.reference.digest": "sha256:854512a7e492982f94a82258ece4eec7aae8bfd061866d8bdddf54b42c118218",
                "vnd.docker.reference.type": "attestation-manifest"
            },
            "platform": {
                "architecture": "unknown",
                "os": "unknown"
            }
        }
    ]
}
```

### Anything else?

Thanks for all your work on this amazing tool.

### Expected behavior

The resulting manifest file should contain both image manifests for both platforms, as in:
```
    "manifests": [{
            "mediaType": "application/vnd.oci.image.manifest.v1+json",
            "platform": {
                "architecture": "amd64",
                "os": "linux"
            }
        },
        {
            "mediaType": "application/vnd.oci.image.manifest.v1+json",
            "platform": {
                "architecture": "arm64",
                "os": "linux"
            }
        }
    ]
```


### Actual behavior
It creates a list, but only contains the native platform:

```
    "manifests": [
        {
            "mediaType": "application/vnd.oci.image.manifest.v1+json",
            "platform": {
                "architecture": "arm64",
                "os": "linux"
            }
        }
    ]
```

### Buildx version

github.com/docker/buildx v0.21.1-desktop.2 65a04767fd3000fbac3b7120cc6115d518678e33

### Docker info

```text
Client:
 Version:    28.0.1
 Context:    desktop-linux
 Debug Mode: false
 Plugins:
  ai: Docker AI Agent - Ask Gordon (Docker Inc.)
    Version:  v0.9.4
    Path:     /Users/redacted/.docker/cli-plugins/docker-ai
  buildx: Docker Buildx (Docker Inc.)
    Version:  v0.21.1-desktop.2
    Path:     /Users/redacted/.docker/cli-plugins/docker-buildx
  compose: Docker Compose (Docker Inc.)
    Version:  v2.33.1-desktop.1
    Path:     /Users/redacted/.docker/cli-plugins/docker-compose
  debug: Get a shell into any image or container (Docker Inc.)
    Version:  0.0.38
    Path:     /Users/redacted/.docker/cli-plugins/docker-debug
  desktop: Docker Desktop commands (Beta) (Docker Inc.)
    Version:  v0.1.5
    Path:     /Users/redacted/.docker/cli-plugins/docker-desktop
  dev: Docker Dev Environments (Docker Inc.)
    Version:  v0.1.2
    Path:     /Users/redacted/.docker/cli-plugins/docker-dev
  extension: Manages Docker extensions (Docker Inc.)
    Version:  v0.2.27
    Path:     /Users/redacted/.docker/cli-plugins/docker-extension
  feedback: Provide feedback, right in your terminal! (Docker Inc.)
    Version:  v1.0.5
    Path:     /Users/redacted/.docker/cli-plugins/docker-feedback
  init: Creates Docker-related starter files for your project (Docker Inc.)
    Version:  v1.4.0
    Path:     /Users/redacted/.docker/cli-plugins/docker-init
  sbom: View the packaged-based Software Bill Of Materials (SBOM) for an image (Anchore Inc.)
    Version:  0.6.0
    Path:     /Users/redacted/.docker/cli-plugins/docker-sbom
  scout: Docker Scout (Docker Inc.)
    Version:  v1.16.3
    Path:     /Users/redacted/.docker/cli-plugins/docker-scout

Server:
 Containers: 6
  Running: 4
  Paused: 0
  Stopped: 2
 Images: 15
 Server Version: 28.0.1
 Storage Driver: overlayfs
  driver-type: io.containerd.snapshotter.v1
 Logging Driver: json-file
 Cgroup Driver: cgroupfs
 Cgroup Version: 2
 Plugins:
  Volume: local
  Network: bridge host ipvlan macvlan null overlay
  Log: awslogs fluentd gcplogs gelf journald json-file local splunk syslog
 CDI spec directories:
  /etc/cdi
  /var/run/cdi
 Swarm: inactive
 Runtimes: io.containerd.runc.v2 runc
 Default Runtime: runc
 Init Binary: docker-init
 containerd version: bcc810d6b9066471b0b6fa75f557a15a1cbf31bb
 runc version: v1.2.4-0-g6c52b3f
 init version: de40ad0
 Security Options:
  seccomp
   Profile: unconfined
  cgroupns
 Kernel Version: 6.10.14-linuxkit
 Operating System: Docker Desktop
 OSType: linux
 Architecture: aarch64
 CPUs: 10
 Total Memory: 31.29GiB
 Name: docker-desktop
 ID: 46593c18-765b-4e8b-8ee2-774587396981
 Docker Root Dir: /var/lib/docker
 Debug Mode: false
 HTTP Proxy: http.docker.internal:3128
 HTTPS Proxy: http.docker.internal:3128
 No Proxy: hubproxy.docker.internal
 Labels:
  com.docker.desktop.address=unix:///Users/redacted/Library/Containers/com.docker.docker/Data/docker-cli.sock
 Experimental: false
 Insecure Registries:
  hubproxy.docker.internal:5555
  ::1/128
  127.0.0.0/8
 Live Restore Enabled: false
```

### Builders list

```text
NAME/NODE               DRIVER/ENDPOINT     STATUS    BUILDKIT   PLATFORMS
ecstatic_volhard*       docker-container                         
 \_ ecstatic_volhard0    \_ desktop-linux   running   v0.20.2    linux/amd64 (+2), linux/arm64, linux/arm (+2), linux/ppc64le, (3 more)
default                 docker                                   
 \_ default              \_ default         running   v0.20.0    linux/amd64 (+2), linux/arm64, linux/ppc64le, linux/s390x, (2 more)
desktop-linux           docker                                   
 \_ desktop-linux        \_ desktop-linux   running   v0.20.0    linux/amd64 (+2), linux/arm64, linux/ppc64le, linux/s390x, (2 more)
kubernetes              docker                                   
 \_ kubernetes           \_ kubernetes      running   v0.20.0    linux/amd64 (+2), linux/arm64, linux/ppc64le, linux/s390x, (2 more)
```

### Configuration


Here are the contents to reproduce:

Dockerfile
```
FROM busybox
```

docker-compose.yaml
```
services:
  issue-3085:
    container_name: issue-3085
    build:
      dockerfile: Dockerfile
      platforms:
        - linux/amd64
        - linux/arm64
    image: issue-3085:latest
```


### Build logs

```text

```

### Additional info

- [ ] _No response_no


Discussion:
> `docker buildx build -f docker-compose.yaml`

I guess you mean `docker buildx bake -f docker-compose.yaml` and not the `build` command?

___

This is the provenance attestation manifest that is created by default.

If you do not want the provenance attestation manifest you can set the `BUILDX_NO_DEFAULT_ATTESTATIONS` env var: https://docs.docker.com/build/building/variables/#buildx_no_default_attestations

```
BUILDX_NO_DEFAULT_ATTESTATIONS=1 docker buildx bake -f docker-compose.yaml
```

I was also looking at the compose spec https://github.com/compose-spec/compose-spec/blob/main/build.md and it doesn't seem the [`attest` attribute](https://docs.docker.com/build/bake/reference/#targetattest) has been implemented otherwise you could disable the provenance attestation with:

```yaml
services:
  issue-3085:
    container_name: issue-3085
    build:
      dockerfile: Dockerfile
      platforms:
        - linux/amd64
        - linux/arm64
      attest:
        - type=provenance,disabled=true
    image: issue-3085:latest
```

cc @ndeloof @glours 
> I guess you mean docker buildx bake -f docker-compose.yaml and not the build command?

Yes, correct, sorry, I've just fixed some copy paste errors in description.

Were you able to reproduce?

Of note, we've found a workaround which produces the manifest with "Linux/amd64" and solves our immediate problem: 

`--set '*:platform=linux/amd64' --push` 

This builds and pushes the amd64 variant successfully, which allows kubernetes to pull and run our images.  It loses the arm64 variant but at this moment that doesn't matter for us because for local testing we do `docker compose up --build` and this brings up the arm64 variant. Quite lucky.

To be honest, I know very little about manifests. I first discovered this issue because my amd64 Kubernetes's was unable to find the images I was building and pushing from my arm64 Mac.  I was using docker compose build && docker compose push.  Then I learned about multi-platform, and added the platforms list to my compose file. It turns out there's a bug in Docker compose such that "build" doesn't implicitly "tag", so I discovered "docker buildx bake" which seemed to be perfect, until I hit this other bug.

> This is the provenance attestation manifest that is created by default.

Ok, now I get it.  I will re-title and edit the description of this ticket. 

I now believe that the real issue is that `docker buildx bake` simply doesn't respect the key `platforms` in compose. It just builds the native platform by default.  I was able to do a buildx/compose multi-platform build by specifying the platforms with:

```
docker buildx bake --set "*.platform=linux/amd64" --set "*.platform=linux/arm64" -f docker-compose.yml --push
```




Patch:
diff --git a/bake/compose.go b/bake/compose.go
index 523d52cdd950..931fec36281e 100644
--- a/bake/compose.go
+++ b/bake/compose.go
@@ -177,6 +177,7 @@ func ParseCompose(cfgs []composetypes.ConfigFile, envs map[string]string) (*Conf
 				CacheFrom:   cacheFrom,
 				CacheTo:     cacheTo,
 				NetworkMode: networkModeP,
+				Platforms:   s.Build.Platforms,
 				SSH:         ssh,
 				Secrets:     secrets,
 				ShmSize:     shmSize,


Test patch:
diff --git a/bake/compose_test.go b/bake/compose_test.go
index 82182cc18973..7619fc7ab768 100644
--- a/bake/compose_test.go
+++ b/bake/compose_test.go
@@ -463,6 +463,21 @@ services:
 	require.NoError(t, err)
 }
 
+func TestPlatforms(t *testing.T) {
+	dt := []byte(`
+services:
+  foo:
+    build:
+      context: .
+      platforms:
+        - linux/amd64
+        - linux/arm64
+`)
+	c, err := ParseCompose([]composetypes.ConfigFile{{Content: dt}}, nil)
+	require.NoError(t, err)
+	require.Equal(t, []string{"linux/amd64", "linux/arm64"}, c.Targets[0].Platforms)
+}
+
 func newBool(val bool) *bool {
 	b := val
 	return &b