RCA-2026-03-17-001: Kroki Orphan Containers
Executive Summary
Kroki diagram rendering containers (4 total) were found running 13+ hours after an Antora build, consuming system resources. Root cause: direct builds from spoke repos (domus-captures) bypass the domus-docs Makefile which has auto-stop logic. Resolution: manual cleanup with docker stop via xargs pattern, plus documentation of the cleanup command.
Timeline
| Time | Event |
|---|---|
2026-03-16 ~18:00 |
Antora build executed (likely from domus-captures or direct npx) |
2026-03-17 07:58 |
Containers still running 13+ hours later |
2026-03-17 08:15 |
Discovered via |
2026-03-17 08:16 |
Cleanup executed via xargs pattern |
Problem Statement
Symptoms
-
docker psshowed 4 Kroki containers running:-
domus-kroki(main) -
domus-kroki-bpmn -
domus-kroki-excalidraw -
domus-kroki-mermaid
-
-
All containers up for 13+ hours
-
Unnecessary resource consumption
Expected Behavior
Kroki containers should stop automatically after Antora build completes.
Actual Behavior
Containers remained running indefinitely.
Root Cause
5 Whys Analysis
| Why # | Question and Answer |
|---|---|
1 |
Why were containers still running? |
2 |
Why was no stop command issued? |
3 |
Why was build run outside domus-docs? |
4 |
Why doesn’t spoke repo stop containers? |
5 |
Why isn’t this documented? |
Root Cause Statement
|
Kroki containers are started by Antora but only stopped by the domus-docs Makefile. Direct builds from spoke repos or |
Resolution
Immediate Actions
Cleanup command using xargs:
# List running Kroki containers
docker ps --filter "name=domus-kroki"
# Stop all Kroki containers in one command
docker ps -q --filter "name=domus-kroki" | xargs docker stop
xargs Pattern Breakdown
docker ps -q --filter "name=domus-kroki" | xargs docker stop
# β β β
# β β ββ xargs: pass container IDs as args to docker stop
# β ββ filter: only containers matching "domus-kroki"
# ββ -q: quiet mode, output only container IDs
Why xargs here:
-
docker stopaccepts multiple container IDs -
xargs batches the IDs from stdin into a single command
-
Avoids loop:
for id in $(docker ps -q …); do docker stop $id; done -
One process instead of N processes
Alternative (explicit names)
docker stop domus-kroki domus-kroki-bpmn domus-kroki-excalidraw domus-kroki-mermaid
Less flexible - requires knowing all container names.
Verification
docker ps --filter "name=domus-kroki"
# Should return empty (no containers)
Preventive Measures
Short-term
| Action | Owner | Status |
|---|---|---|
Document cleanup command in CLAUDE.md |
Evan |
[x] Done (this RCA) |
Add alias for quick cleanup |
Evan |
[ ] Pending |
Suggested alias:
alias kroki-stop='docker ps -q --filter "name=domus-kroki" | xargs -r docker stop'
Note: -r prevents xargs from running if input is empty.
Long-term
| Action | Owner | Status |
|---|---|---|
Add kroki-stop to spoke repo Makefiles |
Evan |
[ ] Pending |
Consider using --rm flag when starting containers |
Evan |
[ ] Investigate |
Detection
How was it detected?
Manual observation via docker ps.
Detection Gap
Could add periodic check:
# Add to cron or shell startup
docker ps --filter "name=domus-kroki" --format "WARNING: {{.Names}} running for {{.RunningFor}}" | grep -q "hours\|days" && echo "Orphan Kroki containers detected"
Lessons Learned
What went well
-
Quick identification via docker ps
-
Clean one-liner solution with xargs
Key Takeaways
|
CLI Mastery: xargs Patterns for Docker
# Stop containers by pattern
docker ps -q --filter "name=prefix" | xargs docker stop
# Remove stopped containers by pattern
docker ps -aq --filter "name=prefix" | xargs docker rm
# Remove images by pattern
docker images -q "*/pattern*" | xargs docker rmi
# Prune with confirmation bypass
docker ps -q --filter "status=exited" | xargs -r docker rm
# Parallel stop (faster for many containers)
docker ps -q --filter "name=prefix" | xargs -P 4 -I {} docker stop {}
Metadata
| Field | Value |
|---|---|
RCA ID |
RCA-2026-03-17-001 |
Author |
Evan Rosado |
Date Created |
2026-03-17 |
Status |
Final |
Category |
Operations / Container Management |