Skip to content

Commit 2a8f99d

Browse files
committed
Address PR comments
Signed-off-by: Arjun Raja Yogidas <[email protected]>
1 parent 5eb08bc commit 2a8f99d

File tree

4 files changed

+61
-24
lines changed

4 files changed

+61
-24
lines changed

cmd/nerdctl/container/container_health_check_linux_test.go

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package container
1919
import (
2020
"encoding/json"
2121
"errors"
22+
"fmt"
2223
"strings"
2324
"testing"
2425
"time"
@@ -37,9 +38,6 @@ import (
3738
)
3839

3940
func TestContainerHealthCheckBasic(t *testing.T) {
40-
if rootlessutil.IsRootless() {
41-
t.Skip("healthcheck tests are skipped in rootless environment")
42-
}
4341

4442
testCase := nerdtest.Setup()
4543

@@ -138,10 +136,6 @@ func TestContainerHealthCheckBasic(t *testing.T) {
138136
}
139137

140138
func TestContainerHealthCheckAdvance(t *testing.T) {
141-
if rootlessutil.IsRootless() {
142-
t.Skip("healthcheck tests are skipped in rootless environment")
143-
}
144-
145139
testCase := nerdtest.Setup()
146140

147141
// Docker CLI does not provide a standalone healthcheck command.
@@ -399,6 +393,43 @@ func TestContainerHealthCheckAdvance(t *testing.T) {
399393
}
400394
},
401395
},
396+
{
397+
Description: "Healthcheck emits large output repeatedly",
398+
Setup: func(data test.Data, helpers test.Helpers) {
399+
helpers.Ensure("run", "-d", "--name", data.Identifier(),
400+
"--health-cmd", "yes X | head -c 60000",
401+
"--health-interval", "1s", "--health-timeout", "2s",
402+
testutil.CommonImage, "sleep", nerdtest.Infinity)
403+
nerdtest.EnsureContainerStarted(helpers, data.Identifier())
404+
},
405+
Cleanup: func(data test.Data, helpers test.Helpers) {
406+
helpers.Anyhow("rm", "-f", data.Identifier())
407+
},
408+
Command: func(data test.Data, helpers test.Helpers) test.TestableCommand {
409+
for i := 0; i < 3; i++ {
410+
helpers.Ensure("container", "healthcheck", data.Identifier())
411+
time.Sleep(2 * time.Second)
412+
}
413+
return helpers.Command("inspect", data.Identifier())
414+
},
415+
Expected: func(data test.Data, helpers test.Helpers) *test.Expected {
416+
return &test.Expected{
417+
ExitCode: 0,
418+
Output: expect.All(func(_ string, t tig.T) {
419+
inspect := nerdtest.InspectContainer(helpers, data.Identifier())
420+
h := inspect.State.Health
421+
debug, _ := json.MarshalIndent(h, "", " ")
422+
t.Log(string(debug))
423+
assert.Assert(t, h != nil, "expected health state")
424+
assert.Equal(t, h.Status, healthcheck.Healthy)
425+
assert.Assert(t, len(h.Log) >= 3, "expected at least 3 health log entries")
426+
for _, log := range h.Log {
427+
assert.Assert(t, len(log.Output) >= 1024, fmt.Sprintf("each output should be >= 1024 bytes, was: %s", log.Output))
428+
}
429+
}),
430+
}
431+
},
432+
},
402433
{
403434
Description: "Health log in inspect keeps only the latest 5 entries",
404435
Setup: func(data test.Data, helpers test.Helpers) {

docs/healthchecks.md

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Health Check Support in nerdctl
22

3-
`nerdctl` supports Docker-compatible health checks for containers, allowing you to monitor container health through user-defined commands.
3+
`nerdctl` supports Docker-compatible health checks for containers, allowing users to monitor container health via a user-defined command.
44

55
## Configuration Options
66

@@ -15,7 +15,8 @@ Health checks can be configured in multiple ways:
1515
- `--no-healthcheck`: Disable any container-specified HEALTHCHECK
1616

1717
2. At image build time using HEALTHCHECK in a Dockerfile
18-
3. In docker-compose.yaml files when using nerdctl compose
18+
19+
**Note:** The `--health-start-interval` option is currently not supported by nerdctl.
1920

2021
## Configuration Priority
2122

@@ -25,6 +26,25 @@ When a container is created, nerdctl determines the health check configuration b
2526
2. If no CLI flags are set, nerdctl will use any health check defined in the image
2627
3. If neither is present, no health check will be configured
2728

29+
### Disabling Health Checks
30+
31+
You can disable health checks using the following flag during container create/run:
32+
33+
```bash
34+
--no-healthcheck
35+
```
36+
37+
### Running Health Checks Manually
38+
39+
nerdctl provides a container healthcheck command that can be manually triggered by the user. This command runs the
40+
configured health check inside the container and reports the result. It serves as the entry point for executing
41+
health checks, especially in scenarios where external scheduling is used.
42+
43+
Example:
44+
```
45+
nerdctl container healthcheck <container-id>
46+
```
47+
2848
## Automatic Health Checks with systemd
2949

3050
On Linux systems with systemd, nerdctl automatically creates and manages systemd timer units to execute health checks at the configured intervals. This provides reliable scheduling and execution of health checks without requiring a persistent daemon.
@@ -71,4 +91,4 @@ nerdctl run -d --name app \
7191
3. Disable health checks:
7292
```bash
7393
nerdctl run --no-healthcheck myapp
74-
```
94+
```

pkg/containerutil/containerutil.go

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -359,11 +359,6 @@ func Stop(ctx context.Context, container containerd.Container, timeout *time.Dur
359359
}
360360
}()
361361

362-
// Clean up healthcheck units if configured.
363-
// if err := healthcheck.RemoveTransientHealthCheckFiles(ctx, container); err != nil {
364-
// return fmt.Errorf("failed to clean up healthcheck units for container %s", container.ID())
365-
// }
366-
367362
if timeout == nil {
368363
t, ok := l[labels.StopTimeout]
369364
if !ok {
@@ -502,11 +497,6 @@ func Pause(ctx context.Context, client *containerd.Client, id string) error {
502497
return err
503498
}
504499

505-
// Clean up healthcheck units if configured.
506-
// if err := healthcheck.RemoveTransientHealthCheckFiles(ctx, container); err != nil {
507-
// return fmt.Errorf("failed to clean up healthcheck units for container %s", container.ID())
508-
// }
509-
510500
switch status.Status {
511501
case containerd.Paused:
512502
return fmt.Errorf("container %s is already paused", id)

pkg/healthcheck/healthcheck_manager_linux.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,6 @@ func CreateTimer(ctx context.Context, container containerd.Container) error {
5050
logrus.Debugf("Creating healthcheck timer unit: %s", hcName)
5151

5252
cmd := []string{}
53-
if rootlessutil.IsRootless() {
54-
cmd = append(cmd, "--user")
55-
}
5653
if path := os.Getenv("PATH"); path != "" {
5754
cmd = append(cmd, "--setenv=PATH="+path)
5855
}
@@ -81,7 +78,6 @@ func CreateTimer(ctx context.Context, container containerd.Container) error {
8178
}
8279

8380
// StartTimer starts the healthcheck timer unit.
84-
// TODO if we persist hcName to container state, pass that to this function.
8581
func StartTimer(ctx context.Context, container containerd.Container) error {
8682
hc := extractHealthcheck(ctx, container)
8783
if hc == nil {

0 commit comments

Comments
 (0)