mirror of
https://github.com/moby/moby.git
synced 2026-01-11 18:51:37 +00:00
API: add Platform (OS and Architecture) to /containers/json
Adds platform information to containers (for `docker ps`). Signed-off-by: Jonathan A. Sternberg <jonathan.sternberg@docker.com>
This commit is contained in:
@@ -113,6 +113,13 @@ func (c *containerRouter) getContainersJSON(ctx context.Context, w http.Response
|
||||
}
|
||||
}
|
||||
|
||||
if versions.LessThan(version, "1.48") {
|
||||
// ImageManifestDescriptor information was added in API 1.48
|
||||
for _, c := range containers {
|
||||
c.ImageManifestDescriptor = nil
|
||||
}
|
||||
}
|
||||
|
||||
return httputils.WriteJSON(w, http.StatusOK, containers)
|
||||
}
|
||||
|
||||
|
||||
@@ -5109,6 +5109,17 @@ definitions:
|
||||
ImageID:
|
||||
description: "The ID of the image that this container was created from"
|
||||
type: "string"
|
||||
ImageManifestDescriptor:
|
||||
$ref: "#/definitions/OCIDescriptor"
|
||||
x-nullable: true
|
||||
description: |
|
||||
OCI descriptor of the platform-specific manifest of the image
|
||||
the container was created from.
|
||||
|
||||
Note: Only available if the daemon provides a multi-platform
|
||||
image store.
|
||||
|
||||
This field is not populated in the `GET /system/df` endpoint.
|
||||
Command:
|
||||
description: "Command to run when starting the container"
|
||||
type: "string"
|
||||
|
||||
@@ -121,19 +121,20 @@ type State struct {
|
||||
// Summary contains response of Engine API:
|
||||
// GET "/containers/json"
|
||||
type Summary struct {
|
||||
ID string `json:"Id"`
|
||||
Names []string
|
||||
Image string
|
||||
ImageID string
|
||||
Command string
|
||||
Created int64
|
||||
Ports []Port
|
||||
SizeRw int64 `json:",omitempty"`
|
||||
SizeRootFs int64 `json:",omitempty"`
|
||||
Labels map[string]string
|
||||
State string
|
||||
Status string
|
||||
HostConfig struct {
|
||||
ID string `json:"Id"`
|
||||
Names []string
|
||||
Image string
|
||||
ImageID string
|
||||
ImageManifestDescriptor *ocispec.Descriptor `json:"ImageManifestDescriptor,omitempty"`
|
||||
Command string
|
||||
Created int64
|
||||
Ports []Port
|
||||
SizeRw int64 `json:",omitempty"`
|
||||
SizeRootFs int64 `json:",omitempty"`
|
||||
Labels map[string]string
|
||||
State string
|
||||
Status string
|
||||
HostConfig struct {
|
||||
NetworkMode string `json:",omitempty"`
|
||||
Annotations map[string]string `json:",omitempty"`
|
||||
}
|
||||
@@ -183,5 +184,5 @@ type InspectResponse struct {
|
||||
Config *Config
|
||||
NetworkSettings *NetworkSettings
|
||||
// ImageManifestDescriptor is the descriptor of a platform-specific manifest of the image used to create the container.
|
||||
ImageManifestDescriptor *ocispec.Descriptor `json:",omitempty"`
|
||||
ImageManifestDescriptor *ocispec.Descriptor `json:"ImageManifestDescriptor,omitempty"`
|
||||
}
|
||||
|
||||
@@ -301,14 +301,15 @@ func (v *View) transform(ctr *Container) *Snapshot {
|
||||
}
|
||||
snapshot := &Snapshot{
|
||||
Summary: container.Summary{
|
||||
ID: ctr.ID,
|
||||
Names: v.getNames(ctr.ID),
|
||||
ImageID: ctr.ImageID.String(),
|
||||
Ports: []container.Port{},
|
||||
Mounts: ctr.GetMountPoints(),
|
||||
State: ctr.State.StateString(),
|
||||
Status: ctr.State.String(),
|
||||
Created: ctr.Created.Unix(),
|
||||
ID: ctr.ID,
|
||||
Names: v.getNames(ctr.ID),
|
||||
ImageID: ctr.ImageID.String(),
|
||||
ImageManifestDescriptor: ctr.ImageManifest,
|
||||
Ports: []container.Port{},
|
||||
Mounts: ctr.GetMountPoints(),
|
||||
State: ctr.State.StateString(),
|
||||
Status: ctr.State.String(),
|
||||
Created: ctr.Created.Unix(),
|
||||
},
|
||||
CreatedAt: ctr.Created,
|
||||
StartedAt: ctr.StartedAt,
|
||||
@@ -416,6 +417,10 @@ func (v *View) transform(ctr *Container) *Snapshot {
|
||||
}
|
||||
snapshot.NetworkSettings = &container.NetworkSettingsSummary{Networks: networks}
|
||||
|
||||
if ctr.ImageManifest != nil && ctr.ImageManifest.Platform == nil {
|
||||
ctr.ImageManifest.Platform = &ctr.ImagePlatform
|
||||
}
|
||||
|
||||
return snapshot
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,12 @@ func (daemon *Daemon) containerDiskUsage(ctx context.Context) ([]*container.Summ
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to retrieve container list: %v", err)
|
||||
}
|
||||
|
||||
// Remove image manifest descriptor from the result as it should not be included.
|
||||
// https://github.com/moby/moby/pull/49407#discussion_r1954396666
|
||||
for _, c := range containers {
|
||||
c.ImageManifestDescriptor = nil
|
||||
}
|
||||
return containers, nil
|
||||
})
|
||||
return res, err
|
||||
|
||||
@@ -89,6 +89,10 @@ keywords: "API, Docker, rcli, REST, documentation"
|
||||
paths (`/v<API-version>/<endpoint>`).
|
||||
* `POST /build/prune` renames `keep-bytes` to `reserved-space` and now supports
|
||||
additional prune parameters `max-used-space` and `min-free-space`.
|
||||
* `GET /containers/json` now returns an `ImageManifestDescriptor` field
|
||||
matching the same field in `/containers/{name}/json`.
|
||||
This field is only populated if the daemon provides a multi-platform image
|
||||
store.
|
||||
|
||||
## v1.47 API changes
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"github.com/docker/docker/testutil"
|
||||
"gotest.tools/v3/assert"
|
||||
is "gotest.tools/v3/assert/cmp"
|
||||
"gotest.tools/v3/skip"
|
||||
)
|
||||
|
||||
func TestPsFilter(t *testing.T) {
|
||||
@@ -47,3 +48,29 @@ func TestPsFilter(t *testing.T) {
|
||||
assert.Check(t, is.Contains(containerIDs(results), prev))
|
||||
})
|
||||
}
|
||||
|
||||
// TestPsPlatform verifies that containers have a platform set
|
||||
func TestPsImageManifestPlatform(t *testing.T) {
|
||||
skip.If(t, testEnv.IsRemoteDaemon)
|
||||
skip.If(t, testEnv.DaemonInfo.OSType != "linux")
|
||||
skip.If(t, !testEnv.UsingSnapshotter())
|
||||
|
||||
ctx := setupTest(t)
|
||||
apiClient := testEnv.APIClient()
|
||||
|
||||
container.Create(ctx, t, apiClient)
|
||||
|
||||
containers, err := apiClient.ContainerList(ctx, containertypes.ListOptions{
|
||||
All: true,
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, len(containers) > 0)
|
||||
|
||||
ctr := containers[0]
|
||||
if assert.Check(t, ctr.ImageManifestDescriptor != nil && ctr.ImageManifestDescriptor.Platform != nil) {
|
||||
// Check that at least OS and Architecture have a value. Other values
|
||||
// depend on the platform on which we're running the test.
|
||||
assert.Equal(t, ctr.ImageManifestDescriptor.Platform.OS, testEnv.DaemonInfo.OSType)
|
||||
assert.Check(t, ctr.ImageManifestDescriptor.Platform.Architecture != "")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,6 +107,9 @@ func TestDiskUsage(t *testing.T) {
|
||||
// previously used prev.Images[0].Size, which may differ from content data
|
||||
assert.Check(t, is.Equal(du.Containers[0].SizeRootFs, du.LayersSize))
|
||||
|
||||
// ImageManifestDescriptor should NOT be populated.
|
||||
assert.Check(t, is.Nil(du.Containers[0].ImageManifestDescriptor))
|
||||
|
||||
return du
|
||||
},
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user