Merge pull request #6913 from Mohammed-Thaha/6203-add-healthcheck-format

container/ps: add HealthStatus formatter field
This commit is contained in:
Paweł Gronowski
2026-05-13 14:01:16 +02:00
committed by GitHub
3 changed files with 59 additions and 23 deletions
+38 -7
View File
@@ -21,13 +21,14 @@ import (
const ( const (
defaultContainerTableFormat = "table {{.ID}}\t{{.Image}}\t{{.Command}}\t{{.RunningFor}}\t{{.Status}}\t{{.Ports}}\t{{.Names}}" defaultContainerTableFormat = "table {{.ID}}\t{{.Image}}\t{{.Command}}\t{{.RunningFor}}\t{{.Status}}\t{{.Ports}}\t{{.Names}}"
namesHeader = "NAMES" namesHeader = "NAMES"
commandHeader = "COMMAND" commandHeader = "COMMAND"
runningForHeader = "CREATED" runningForHeader = "CREATED"
mountsHeader = "MOUNTS" mountsHeader = "MOUNTS"
localVolumes = "LOCAL VOLUMES" localVolumes = "LOCAL VOLUMES"
networksHeader = "NETWORKS" networksHeader = "NETWORKS"
platformHeader = "PLATFORM" platformHeader = "PLATFORM"
healthStatusHeader = "HEALTH STATUS"
) )
// Platform wraps a [ocispec.Platform] to implement the stringer interface. // Platform wraps a [ocispec.Platform] to implement the stringer interface.
@@ -121,6 +122,7 @@ func NewContainerContext() *ContainerContext {
"LocalVolumes": localVolumes, "LocalVolumes": localVolumes,
"Networks": networksHeader, "Networks": networksHeader,
"Platform": platformHeader, "Platform": platformHeader,
"HealthStatus": healthStatusHeader,
} }
return &containerCtx return &containerCtx
} }
@@ -352,6 +354,35 @@ func (c *ContainerContext) Networks() string {
return strings.Join(networks, ",") return strings.Join(networks, ",")
} }
// HealthStatus returns the container's health status (for example, "healthy","unhealthy", or "starting").
// If no healthcheck is configured, an empty
// string is returned.
func (c *ContainerContext) HealthStatus() string {
if c.c.Health != nil && c.c.Health.Status != "" {
return string(c.c.Health.Status)
}
// Fallback for API versions before v1.52, which include health only in Status text;
// see https://github.com/moby/moby/pull/50281
// see https://github.com/moby/moby/blob/docker-v29.4.3/daemon/container/health.go#L18-L43
_, health, ok := strings.Cut(c.c.Status, "(")
if !ok || !strings.HasSuffix(health, ")") {
return ""
}
health = strings.TrimSuffix(health, ")")
health = strings.TrimPrefix(health, "health: ")
switch container.HealthStatus(health) {
case container.Healthy, container.Unhealthy, container.Starting:
return health
case container.NoHealthcheck:
return ""
default:
return ""
}
}
// DisplayablePorts returns formatted string representing open ports of container // DisplayablePorts returns formatted string representing open ports of container
// e.g. "0.0.0.0:80->9090/tcp, 9988/tcp" // e.g. "0.0.0.0:80->9090/tcp, 9988/tcp"
// it's used by command 'docker ps' // it's used by command 'docker ps'
+4
View File
@@ -494,6 +494,7 @@ func TestContainerContextWriteJSON(t *testing.T) {
{ {
"Command": `""`, "Command": `""`,
"CreatedAt": expectedCreated, "CreatedAt": expectedCreated,
"HealthStatus": "",
"ID": "containerID1", "ID": "containerID1",
"Image": "ubuntu", "Image": "ubuntu",
"Labels": "", "Labels": "",
@@ -511,6 +512,7 @@ func TestContainerContextWriteJSON(t *testing.T) {
{ {
"Command": `""`, "Command": `""`,
"CreatedAt": expectedCreated, "CreatedAt": expectedCreated,
"HealthStatus": "",
"ID": "containerID2", "ID": "containerID2",
"Image": "ubuntu", "Image": "ubuntu",
"Labels": "", "Labels": "",
@@ -528,6 +530,7 @@ func TestContainerContextWriteJSON(t *testing.T) {
{ {
"Command": `""`, "Command": `""`,
"CreatedAt": expectedCreated, "CreatedAt": expectedCreated,
"HealthStatus": "",
"ID": "containerID3", "ID": "containerID3",
"Image": "ubuntu", "Image": "ubuntu",
"Labels": "", "Labels": "",
@@ -615,6 +618,7 @@ func TestContainerBackCompat(t *testing.T) {
{field: "Image", expected: "docker.io/library/ubuntu"}, {field: "Image", expected: "docker.io/library/ubuntu"},
{field: "Command", expected: `"/bin/sh"`}, {field: "Command", expected: `"/bin/sh"`},
{field: "CreatedAt", expected: time.Unix(createdAtTime.Unix(), 0).String()}, {field: "CreatedAt", expected: time.Unix(createdAtTime.Unix(), 0).String()},
{field: "HealthStatus", expected: ""},
{field: "RunningFor", expected: "12 months ago"}, {field: "RunningFor", expected: "12 months ago"},
{field: "Ports", expected: "8080/tcp"}, {field: "Ports", expected: "8080/tcp"},
{field: "Status", expected: "running"}, {field: "Status", expected: "running"},
+17 -16
View File
@@ -395,22 +395,23 @@ template.
Valid placeholders for the Go template are listed below: Valid placeholders for the Go template are listed below:
| Placeholder | Description | | Placeholder | Description |
|:--------------|:------------------------------------------------------------------------------------------------| |:----------------|:------------------------------------------------------------------------------------------------|
| `.ID` | Container ID | | `.ID` | Container ID |
| `.Image` | Image ID | | `.Image` | Image ID |
| `.Command` | Quoted command | | `.Command` | Quoted command |
| `.CreatedAt` | Time when the container was created. | | `.CreatedAt` | Time when the container was created. |
| `.RunningFor` | Elapsed time since the container was started. | | `.RunningFor` | Elapsed time since the container was started. |
| `.Ports` | Exposed ports. | | `.Ports` | Exposed ports. |
| `.State` | Container status (for example; "created", "running", "exited"). | | `.State` | Container status (for example; "created", "running", "exited"). |
| `.Status` | Container status with details about duration and health-status. | | `.Status` | Container status with details about duration and health-status. |
| `.Size` | Container disk size. | | `.HealthStatus` | Container health status ("starting", "healthy", "unhealthy"; empty when unavailable). |
| `.Names` | Container names. | | `.Size` | Container disk size. |
| `.Labels` | All labels assigned to the container. | | `.Names` | Container names. |
| `.Label` | Value of a specific label for this container. For example `'{{.Label "com.docker.swarm.cpu"}}'` | | `.Labels` | All labels assigned to the container. |
| `.Mounts` | Names of the volumes mounted in this container. | | `.Label` | Value of a specific label for this container. For example `'{{.Label "com.docker.swarm.cpu"}}'` |
| `.Networks` | Names of the networks attached to this container. | | `.Mounts` | Names of the volumes mounted in this container. |
| `.Networks` | Names of the networks attached to this container. |
When using the `--format` option, the `ps` command will either output the data When using the `--format` option, the `ps` command will either output the data
exactly as the template declares or, when using the `table` directive, includes exactly as the template declares or, when using the `table` directive, includes