fix(entrypoint): exec memcached so docker stop is graceful #4

Merged
jknapp merged 1 commits from fix/graceful-stop into trunk 2026-10-21 00:01:35 +00:00
Owner

Problem

scripts/entrypoint.sh ran memcached in the foreground under bash. bash as PID 1 has no SIGTERM handler, so the kernel dropped docker stop's SIGTERM. Docker waited the full 10s and then SIGKILLed the container (exit 137) on every stop and restart.

Change

The script now execs memcached, so memcached becomes PID 1. It installs its own SIGTERM/SIGINT handlers. Everything else is unchanged (sleep 5, -u memcached -l 0.0.0.0).

Test results (.148, measured)

  • The image under test is the current cmc:latest with only this entrypoint.sh copied on top; the image's /entrypoint.sh md5-matches trunk.
  • Hardening baseline (B:256), throwaway network.
  • Before: restart 10.3s, stop 10.1s, exit 137.
  • After: restart 1.6s, stop 1.6s, exit 0. memcached set/get works after cold start and after restart, and runs as the memcached uid (994).

Not tested: a from-scratch CI build, which re-runs dnf update on almalinux/9-base and can pull a newer memcached. Known edge, not measured: a stop that arrives during the 5s sleep (before the exec) still waits the full 10s.

Do not merge without a deploy plan: a merge to trunk rebuilds and pushes cmc:latest.

🤖 Generated with Claude Code

## Problem `scripts/entrypoint.sh` ran memcached in the foreground under bash. bash as PID 1 has no SIGTERM handler, so the kernel dropped `docker stop`'s SIGTERM. Docker waited the full 10s and then SIGKILLed the container (exit 137) on every stop and restart. ## Change The script now `exec`s memcached, so memcached becomes PID 1. It installs its own SIGTERM/SIGINT handlers. Everything else is unchanged (`sleep 5`, `-u memcached -l 0.0.0.0`). ## Test results (.148, measured) - The image under test is the current `cmc:latest` with only this `entrypoint.sh` copied on top; the image's `/entrypoint.sh` md5-matches `trunk`. - Hardening baseline (`B:256`), throwaway network. - Before: restart 10.3s, stop 10.1s, exit 137. - After: restart 1.6s, stop 1.6s, exit 0. memcached set/get works after cold start and after restart, and runs as the `memcached` uid (994). Not tested: a from-scratch CI build, which re-runs `dnf update` on almalinux/9-base and can pull a newer memcached. Known edge, not measured: a stop that arrives during the 5s `sleep` (before the `exec`) still waits the full 10s. **Do not merge without a deploy plan:** a merge to `trunk` rebuilds and pushes `cmc:latest`. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
jknapp added 1 commit 2026-10-20 23:59:15 +00:00
entrypoint.sh ran memcached in the foreground under bash. bash as PID 1 has no
SIGTERM handler, so the kernel dropped docker stop's SIGTERM; docker waited the
full 10s timeout and SIGKILLed the container (exit 137). exec memcached so it
becomes PID 1; it installs its own SIGTERM/SIGINT handlers and exits at once.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
jknapp merged commit 0f46d8ad86 into trunk 2026-10-21 00:01:35 +00:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: cloud-hosting-platform/cloud-memcached-container#4