The CyberController Container Watchdog is a lightweight, autonomous monitoring service that continuously tracks the health of all Docker containers on the host. It detects failures — including crashes, out-of-memory kills, prolonged unhealthy states, and restart loops — and dispatches real-time alerts through one or more configurable channels (Slack, SMTP, SNMP Traps, or Syslog). It also sends a one-time INFO recovered alert through the same channels once a previously-alarmed container returns to normal operation.
- How It Works
- System Overview
- Configuration
- Supported Alert Channels
- Deployment Instructions
- Failure Types & Severities
- Testing
- Troubleshooting
- Container Probe Map (This Deployment)
- Version History
The watchdog runs two parallel monitoring paths:
| Path | Mechanism | What It Catches |
|---|---|---|
| Event stream | docker events (real-time) |
Crashes (die), OOM-kills (oom), health status changes |
| Active Probes | docker ps + Probes |
Integrity: Periodic verification of liveness, stuck states, and restart-loops |
The watchdog selects one of 4 active probe types per container, chosen automatically based on the container's configuration. Probe selection is cached for the container's lifetime and re-discovered on restart.
-
Docker HEALTHCHECK (passive) — for containers that have a
Docker HEALTHCHECKdirective in their Dockerfile. The watchdog reads the result fromcontainer.attrs["State"]["Health"]rather than running its own probe. When Docker reportshealth_status: unhealthy3 consecutive times, an alert fires. The last health check output is included in the alert's Detection field. -
HTTP GET (active) — for containers with no
Docker HEALTHCHECKthat expose HTTP ports. Auto-discovers a working endpoint by trying common paths (/-/healthy,/health,/healthz,/metrics,/) on each exposed internal port, and across all internal IPs when the container is attached to multiple Docker networks (configurable viaauto_health_check.pathsinwatchdog-config.yaml). Returns healthy ifstatus_code < 500. The discovered URL is cached for the container's lifetime. -
TCP connect (active) — if no HTTP path responds on a port, falls back to a raw
socket.create_connection()on that port. A successful connect confirms the service is listening; a refused or timed-out connection triggers anunhealthyalert. Used by databases, message brokers, and any non-HTTP service. -
/procalive check (active) — last resort when the container exposes no ports at all, or all TCP connects fail during initial discovery. Reads/proc/1/statusinside the container viaexec_runand checks that PID 1 is in a live state (R/S/D). A zombie (Z) or stopped (T) PID 1 triggers anunhealthyalert.
Alerts are deduplicated via a cooldown — once an alert fires for a container, the same failure type is suppressed for cooldown_minutes minutes. The cooldown resets automatically when the container recovers.
Two additional deduplication rules suppress redundant alerts at the event level:
- OOM → die suppression: when a container is OOM-killed, Docker emits both an
oomevent and an immediately followingdieevent. The watchdog fires theoomCRITICAL alert and suppresses the subsequentcrashedalert to avoid a duplicate for the same incident. - Restart-loop → die suppression: once a
restart-loopHIGH alert is active for a container, subsequent per-cycledieevents are suppressed — the restart-loop alert is the primary signal until the container stabilises.
Recovery alerts: once a container that was previously alarmed (crashed, oom, unhealthy, or restart-loop) is observed running and healthy again, the watchdog dispatches a one-time INFO recovered alert through the same channels and clears its alarm state. Controlled by alert_on_recovery (default true). Detection depends on the same probe path used for the original failure — a container with a Docker HEALTHCHECK recovers via the health_status: healthy event; containers on active probes (HTTP/TCP//proc) recover on the next successful poll cycle.
.
├── watchdog.py # Main monitor script
├── watchdog-config.yaml # All configuration (no secrets)
├── docker-compose.yaml # Production / offline runtime (image only)
├── docker-compose.build.yaml # Developer / online build
├── Dockerfile # Image build definition (python:3.11-slim)
├── requirements-watchdog.txt # Python dependencies (reference; Dockerfile pip-installs inline)
├── install.sh # Offline install script
├── uninstall.sh # Stop + remove script
├── VERSION # Release version — drives the image tag and installer
├── watchdog.tar # Pre-built Docker image (provided, no internet needed)
└── .env # Secrets — NOT committed to git
| Item | Size |
|---|---|
Docker image (watchdog:<VERSION>) |
~180 MB (python:3.11-slim base + dependencies) |
| Running container (memory) | ~50–80 MB baseline; capped at mem_limit: 256m in docker-compose.yaml |
watchdog.tar export |
~170 MB |
Note: The values above are approximate and may vary depending on the host operating system, Docker version, and installed dependencies. If usage approaches the 256 MB limit (check with
docker stats docker-container-watchdog), raisemem_limit/mem_reservationindocker-compose.yamlrather than removing the limit — and raisememswap_limitto at least the newmem_limitin bothdocker-compose.yamlanddocker-compose.build.yaml, since Docker rejects a config wherememswap_limitis lower thanmem_limit.
By default the container runs as root so docker compose up works with zero configuration — no host-specific group setup needed to read /var/run/docker.sock. install.sh instead auto-detects the socket's GID and opts into running the container as non-root UID/GID 1000 (joined to that group via group_add), with no manual input required; manual installs can do the same by setting WATCHDOG_UID/WATCHDOG_GID/DOCKER_GID in .env (see DEPLOYMENT.md). Either way, the container is constrained by a read-only root filesystem, no extra Linux capabilities (cap_drop: ALL), no-new-privileges, and CPU/memory/PID caps (cpus: "0.50", pids_limit: 200, mem_limit: 256m), which contain a leak or runaway condition to this container instead of the host. Note that access to /var/run/docker.sock is effectively host-root-equivalent for any user (root or not): anything that can reach the socket can create privileged containers or bind-mount the host filesystem, so a compromise of the watchdog process is not contained by these controls — treat docker.sock access as the primary trust boundary when deciding who/what can reach this host.
docker==7.1.0
requests==2.32.3
PyYAML==6.0.2
pysnmp>=6.2
pysnmp 6.2+ uses the modern
pysnmp.hlapi.v3arch.asyncioAPI. pysnmp 4.x is no longer supported — its synchronous generator API was removed in 5.x.pyasn1is a transitive dependency managed by pysnmp itself and no longer needs to be pinned separately.
Runtime (in container): Python 3.11+
All non-secret settings live in watchdog-config.yaml. Secrets (webhook URLs, passwords) are stored in .env and never committed to version control. Restart the container after editing either file — no image rebuild is needed.
| Key | Default | Description |
|---|---|---|
alert_channels |
["slack"] |
Active destinations: slack, smtp, snmp_trap |
check_interval_seconds |
60 |
How often the poll loop runs |
cooldown_minutes |
5 |
Suppress duplicate alerts per container per failure type |
restart_threshold |
5 |
Restart count within window that triggers a restart-loop alert |
restart_window_minutes |
10 |
Rolling window for restart counting |
unhealthy_cycles_threshold |
3 |
Consecutive unhealthy cycles before alerting |
alert_on_recovery |
true |
Send an INFO "recovered" alert once a previously-alarmed container returns to normal |
excluded_containers |
[] |
Container names to never alert on |
ignored_container_events |
MariaDB syntax-check label rule | Label-based event suppressions for intentional temporary containers |
auto_health_check |
enabled | Probe containers reporting health=none by discovering an HTTP/TCP endpoint |
container_health_checks |
{} |
Per-container probe overrides (type: http or type: exec) for health=none containers; takes precedence over auto_health_check |
log_level |
INFO |
DEBUG / INFO / WARNING / ERROR |
log_file |
/var/log/watchdog/watchdog.log |
Bind-mounted to ./watchdog/watchdog.log on host. Rotates at 10 MB, 5 backups. Set to null to disable |
state_file |
/var/log/watchdog/state.json |
Persists open alerts and the host boot time so recovery and reboot reporting survive a restart. Set to "" to disable |
boot_grace_seconds |
180 |
After a detected host reboot, hold alerts this long while services start, then send one reboot-summary. 0 alerts immediately and sends the summary on the first poll |
runbook_base_url |
— | URL included in every alert |
Preferred suppression: Temporary MariaDB HA syntax-check containers should be created with Docker label com.radware.cybercontroller.role=mariadb-ha-syntax-check. The watchdog ignores only configured events for containers carrying that explicit label; normal service containers still alert.
Temporary fallback: until that label exists, dynamic MariaDB dump helper containers are not alerted as crashes only when all identifying signals match together: image kvision_infra_mariadb, container name is not config_kvision-infra-mariadb_1, Docker AutoRemove is true, a mount contains /mnt/cli/tmp/mariadb_dump.sql.gz, and the exit code is 137. The primary MariaDB container remains monitored.
| Variable | Required | Description |
|---|---|---|
SLACK_WEBHOOK_URL |
Yes (if Slack enabled) | Slack incoming webhook URL |
SMTP_USERNAME |
Yes (if SMTP enabled) | SMTP username or login email used for login |
SMTP_PASSWORD |
Yes (if SMTP enabled) | SMTP account password or api key value |
SNMP_V3_AUTH_KEY |
Yes (if SNMPv3 enabled) | SNMPv3 authentication passphrase — minimum 8 characters (RFC 3414) |
SNMP_V3_PRIV_KEY |
Yes (if SNMPv3 authPriv) | SNMPv3 privacy passphrase — minimum 8 characters; requires auth key also set |
WATCHDOG_CONFIG |
No | Path to config file (default: /etc/watchdog/watchdog-config.yaml) |
WATCHDOG_HOST |
No | Hostname shown in alerts (default: system hostname) |
Configure at least one channel and add its identifier to alert_channels in watchdog-config.yaml. Multiple channels can be active simultaneously.
Add slack to alert_channels and set SLACK_WEBHOOK_URL in .env:
slack:
enabled: true
webhook_url_env: SLACK_WEBHOOK_URLsyslog:
enabled: true
host: <syslog-server-ip>
port: 514
protocol: udp # udp or tcp
facility: local0Add smtp to alert_channels to enable.
smtp:
enabled: true
host: smtp.radware.com
port: 587
sender: noc-alerts@radware.com
username_env: SMTP_USERNAME # env var: SMTP username or app token
recipients:
- ops-team@radware.com
- oncall@radware.com
tls: true
password_env: SMTP_PASSWORD # env var: SMTP password or app tokenAdd snmp_trap to alert_channels to enable. Sends SNMP traps (v1, v2c, or v3) to your NMS/SIEM on every alert.
snmp_trap:
enabled: true
host: 155.1.1.4 # IP or hostname of your SNMP trap receiver
port: 162 # Standard SNMP trap port
version: v2c # SNMP version: v1, v2c, or v3
community: public # SNMPv1/v2c community string (ignored for v3)
trap_oid: "1.3.6.1.4.1.89.110.0.1" # Radware enterprise container-alert notification OID
# SNMPv3 only — add SNMP_V3_AUTH_KEY / SNMP_V3_PRIV_KEY to .env
# v3_username: watchdog-user
# v3_auth_protocol: SHA # MD5 | SHA | SHA256 | SHA384 | SHA512
# v3_auth_key_env: SNMP_V3_AUTH_KEY # min 8 chars
# v3_priv_protocol: AES # AES (recommended) | AES192 | AES256 | DES (weak)
# v3_priv_key_env: SNMP_V3_PRIV_KEY # min 8 chars; requires auth key also set
# v3_local_engine_id: "" # hex engine ID pinned from first-run log; see DEPLOYMENT.mdEach trap carries five var-binds, all under the Radware enterprise OID arc (1.3.6.1.4.1.89.110):
| OID | Object | Value |
|---|---|---|
1.3.6.1.4.1.89.110.1.1.0 |
cwHost |
Hostname of the alerting node |
1.3.6.1.4.1.89.110.1.2.0 |
cwSummary |
Human-readable alert summary |
1.3.6.1.4.1.89.110.1.3.0 |
cwContainerName |
Container name |
1.3.6.1.4.1.89.110.1.4.0 |
cwFailureType |
crashed / oom / unhealthy / restart-loop / recovered |
1.3.6.1.4.1.89.110.1.5.0 |
cwProbeDetail |
Probe failure detail |
For full deployment instructions — including alert channel setup, offline installation, developer builds, and troubleshooting — see DEPLOYMENT.md.
Quick start (automated):
bash install.sh| Failure | Severity | Trigger |
|---|---|---|
crashed |
CRITICAL | Container exited with non-zero exit code |
oom |
CRITICAL | Container was OOM-killed by the kernel |
unhealthy |
HIGH | Health probe failing for N consecutive cycles |
restart-loop |
HIGH | Container restarted ≥ threshold times within window |
recovered |
INFO | Previously-alarmed container (crashed/oom/unhealthy/restart-loop) is healthy/running again. Fires once per incident; controlled by alert_on_recovery (default true) |
reboot-summary |
INFO / HIGH | Sent once after a host reboot is detected, when the boot_grace_seconds window closes. Reports boot time, how many containers are running, which recovered, and which are still failing. Always sent after a reboot — an INFO summary confirms the node came back cleanly. HIGH if any container is still failing |
OOM alerts include memory stats (usage / limit / peak) prepended to the log snippet.
Every alert includes two probe fields that identify exactly how and why the failure was detected:
- Probe Type — short label classifying the detection mechanism
- Detection — full detail string with path, status code, or error message
| Failure | Probe Type | Example Detection value |
|---|---|---|
crashed |
Docker event (crash) |
Crash probe failed — container exited with exit code 1 |
oom |
Docker event (OOM) |
OOM probe failed — container was OOM-killed by the kernel |
unhealthy (Docker native HEALTHCHECK) |
Docker HEALTHCHECK |
Docker health probe failed — exit code 1, output: connection refused |
unhealthy (HTTP auto-probe) |
HTTP GET |
HTTP probe failed — error response 503 Service Unavailable, URI http://172.18.0.5:8080/health |
unhealthy (TCP connect) |
TCP connect |
TCP probe failed — connection refused or timed out on 172.18.0.5:6379 (Connection refused) |
unhealthy (/proc fallback) |
/proc alive check |
/proc alive check failed — PID 1 is zombie/stopped (exit code 1) |
Restart-loop detection is not a probe — it is tracked by the Poll loop path and fires when a container restarts ≥
restart_thresholdtimes withinrestart_window_minutes. See the Poll loop row in the monitoring paths table above.
The sections below describe optional manual tests that validate the watchdog's detection and alerting paths. Each creates a temporary Docker container and cleans up after itself.
Two options — choose based on whether the host has internet access.
Pulls
polinux/stressfrom Docker Hub.
# --memory-swap=32m disables swap so the kernel is forced to OOM-kill rather than swap out
# Note: the polinux/stress entrypoint IS the stress binary — do not repeat "stress" in the args
docker run -d --name oom-test --memory=32m --memory-swap=32m polinux/stress \
--vm 1 --vm-bytes 64M --vm-keep# Clean up
docker rm -f oom-test
docker rmi polinux/stressUses the Watchdog image that is already present on the host, avoiding the need to pull the image during deployment.
docker run -d --name oom-test --memory=32m --memory-swap=32m watchdog:latest \
python3 -c "x = b'\xff' * (64 * 1024 * 1024)"# Clean up — container only (keep the watchdog image)
docker rm -f oom-testDocker kills the container with exit code 137 and emits an oom event. The watchdog captures memory stats and the last 20 log lines, then dispatches a CRITICAL alert — all within seconds of the kill.
If the container exits cleanly (exit code 0) instead of being OOM-killed, cgroup memory accounting may be disabled on this host. Verify with:
docker info 2>&1 | grep -i "memory limit"
WARNING: No memory limit supportmeans the--memoryflag is silently ignored. Enable cgroup memory accounting by addingcgroup_enable=memory swapaccount=1toGRUB_CMDLINE_LINUXin/etc/default/grub, then runsudo update-gruband reboot.
Optional — requires internet access. These tests pull images from Docker Hub and create temporary containers on the host. Each section includes full cleanup instructions (container + image).
# Start a container where every HTTP path returns 503
# Note: the full server { } block is required — a bare location { } directive is not valid nginx config
docker run -d --name http-probe-test \
nginx:alpine \
sh -c "printf 'server { listen 80; location / { return 503; } }' > /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'"
# Verify the container is running:
docker ps | grep http-probe-test
# Wait one poll cycle (60s), then check watchdog detected it:
grep "http-probe-test" /opt/radware/storage/scripts/Alert_Container/watchdog/watchdog.log
# Clean up
docker rm -f http-probe-test
docker rmi nginx:alpineDuring auto-discovery the watchdog sends an HTTP GET to /-/healthy on port 80. Nginx returns 503, so the watchdog immediately caches that endpoint as failing and reports unhealthy. After unhealthy_cycles_threshold consecutive unhealthy cycles an alert fires with Detection value HTTP probe failed — error response 503 Service Unavailable, URI http://<ip>:80/-/healthy.
# Expose port 9999 but run nothing on it — TCP connect will be refused
docker run -d --name tcp-probe-test \
--expose 9999 \
alpine \
sh -c "sleep infinity"
# Watch the watchdog fall through HTTP → TCP and alert:
grep "tcp-probe-test" /opt/radware/storage/scripts/Alert_Container/watchdog/watchdog.log
# Clean up
docker rm -f tcp-probe-test
docker rmi alpineAfter unhealthy_cycles_threshold consecutive failed cycles an alert fires with Detection value TCP probe failed — connection refused or timed out on <ip>:9999.
# No EXPOSE — watchdog falls straight to /proc alive check
docker run -d --name proc-probe-test \
alpine \
sleep infinity
# Verify the container is running:
docker ps | grep proc-probe-test
# After one poll cycle, confirm the watchdog selected /proc as the probe type:
grep "proc-probe-test" /opt/radware/storage/scripts/Alert_Container/watchdog/watchdog.log
# Clean up
docker rm -f proc-probe-test
docker rmi alpineWith no exposed ports, auto-discovery skips HTTP and TCP and falls back to reading /proc/1/status inside the container via exec_run. Since sleep is PID 1 in a live S (sleeping) state, no alert fires. The log will show falling back to /proc alive-check confirming the probe type was selected. In production, this probe fires when PID 1 enters zombie (Z) or stopped (T) state.
Validates the INFO recovered alert fires once a previously-alarmed container is healthy again. Use any real, already-monitored container — no throwaway container needed.
# 1. Force a failure (SIGKILL → non-zero exit code → CRITICAL "crashed" alert)
docker kill <container-name>
# 2. Confirm the crashed alert was logged/dispatched
grep "<container-name>" /opt/radware/storage/scripts/Alert_Container/watchdog/watchdog.log | grep CRITICAL
# 3. Bring it back
docker start <container-name>
# 4. Wait for it to report healthy again, then confirm the recovery alert:
grep "<container-name>" /opt/radware/storage/scripts/Alert_Container/watchdog/watchdog.log | grep -i recoveredExpected log line: ALERT [INFO] <container-name> — recovered (channels: [...]).
- Containers with a Docker
HEALTHCHECKrecover via thehealth_status: healthyevent — near-instant once Docker reports healthy (subject to the image's ownstart_period/interval). - Containers on HTTP/TCP/
/procactive probes recover on the next poll cycle (check_interval_seconds). - No alert fires if
alert_on_recovery: falseis set, or if the container was never in an alarmed state (state.alerted_forempty).
docker compose logs docker-container-watchdogCommon causes:
- Missing
.envfile — runcp .env.example .envand fill in credentials - Docker socket not accessible — ensure
/var/run/docker.sockexists and the container has read access - Image not loaded — run
docker images watchdog; if empty, setWATCHDOG_VERSION=$(cat VERSION)and build withWATCHDOG_VERSION="$WATCHDOG_VERSION" docker compose -f docker-compose.build.yaml build(see DEPLOYMENT.md for details)
- Check
alert_channelsinwatchdog-config.yaml— ensure at least one channel is listed and configured - Check watchdog logs for errors:
grep -E "ERROR|CRITICAL" /opt/radware/storage/scripts/Alert_Container/watchdog/watchdog.log - For Slack: verify
SLACK_WEBHOOK_URLis set in.envand test manually:Expected response:curl -X POST -H 'Content-type: application/json' \ --data '{"text":"Watchdog test"}' "$SLACK_WEBHOOK_URL"
ok
Recovery alert (recovered) specifically not received:
- Confirm
alert_on_recoveryis not set tofalsein the livewatchdog-config.yaml. - Confirm the container was actually alarmed first —
state.alerted_formust be non-empty; a container that was never flagged won't generate a recovery alert. - For containers with a Docker
HEALTHCHECK, confirm Docker actually reportshealthy—docker inspect <name> --format '{{json .State.Health}}'. If it's stuck onstarting, the watchdog is waiting on Docker, not the other way around. - For containers on active probes (HTTP/TCP/
/proc), confirm the poll loop reportshealth=healthyfor the container in the log — if it staysunhealthy, the probe (oftenauto_health_check) is misjudging the service; add a manual entry undercontainer_health_checksinstead.
Increase cooldown_minutes in watchdog-config.yaml (default: 5 minutes per container per failure type). To silence a noisy container entirely, add it to excluded_containers:
excluded_containers:
- debug-shell
- load-test
- my-noisy-containerCheck which probe was cached at startup:
grep -E "auto-discover|falling back" /opt/radware/storage/scripts/Alert_Container/watchdog/watchdog.logLog destinations (simultaneous):
- stdout — always on; captured by
docker compose logs - file —
./watchdog/watchdog.logon the host (bind-mounted), rotates at 10 MB, keeps 5 backups - syslog — remote server if
syslog.enabled: truein config
# Live tail (preferred — host path, no need to exec into the container)
tail -f /opt/radware/storage/scripts/Alert_Container/watchdog/watchdog.log
# Last 100 lines
tail -100 /opt/radware/storage/scripts/Alert_Container/watchdog/watchdog.log
# Alerts and errors only
grep -E "ALERT|ERROR|CRITICAL" /opt/radware/storage/scripts/Alert_Container/watchdog/watchdog.log
# Filter by container name
grep "my-container" /opt/radware/storage/scripts/Alert_Container/watchdog/watchdog.log
# Search across rotated logs
grep "CRITICAL" /opt/radware/storage/scripts/Alert_Container/watchdog/watchdog.log \
/opt/radware/storage/scripts/Alert_Container/watchdog/watchdog.log.1
# Via Docker (stdout only)
docker compose logs -f docker-container-watchdogProbe selection is automatic: containers with a Docker HEALTHCHECK are monitored passively via events; all others get an active probe auto-discovered on the first poll and cached for the container's lifetime.
| Container | Probe Type | Endpoint | Why |
|---|---|---|---|
config_kvision-infra-fluentd_1 |
Docker HEALTHCHECK | Docker managed | Image has HEALTHCHECK directive |
config_kvision-dp-inline-config_1 |
Docker HEALTHCHECK | Docker managed | Image has HEALTHCHECK directive |
config_kvision-collector_1 |
Docker HEALTHCHECK | Docker managed | Image has HEALTHCHECK directive |
config_kvision-configuration-service_1 |
Docker HEALTHCHECK | Docker managed | Image has HEALTHCHECK directive |
config_kvision-anomaly-detection-engine_1 |
Docker HEALTHCHECK | Docker managed | Image has HEALTHCHECK directive |
config_kvision-data-persist-service_1 |
Docker HEALTHCHECK | Docker managed | Image has HEALTHCHECK directive |
config_kvision-rt-alert_1 |
Docker HEALTHCHECK | Docker managed | Image has HEALTHCHECK directive |
config_policy-editor_1 |
Docker HEALTHCHECK | Docker managed | Image has HEALTHCHECK directive |
config_kvision-alerts_1 |
Docker HEALTHCHECK | Docker managed | Image has HEALTHCHECK directive |
config_kvision-reporter_1 |
Docker HEALTHCHECK | Docker managed | Image has HEALTHCHECK directive |
config_kvision-vrm_1 |
Docker HEALTHCHECK | Docker managed | Image has HEALTHCHECK directive |
config_kvision-infra-redis_1 |
Docker HEALTHCHECK | Docker managed | Image has HEALTHCHECK directive |
config_kvision-health_1 |
Docker HEALTHCHECK | Docker managed | Image has HEALTHCHECK directive |
config_kvision-webui_1 |
Docker HEALTHCHECK | Docker managed | Image has HEALTHCHECK directive |
config_kvision-tor-feed_1 |
Docker HEALTHCHECK | Docker managed | Image has HEALTHCHECK directive |
config_kvision-infra-efk_1 |
Docker HEALTHCHECK | Docker managed | Image has HEALTHCHECK directive |
config_kvision-data-polling-mgr_1 |
Docker HEALTHCHECK | Docker managed | Image has HEALTHCHECK directive |
config_kvision-formatter_1 |
Docker HEALTHCHECK | Docker managed | Image has HEALTHCHECK directive |
config_kvision-data-polling-scheduler_1 |
Docker HEALTHCHECK | Docker managed | Image has HEALTHCHECK directive |
config_kvision-infra-cadvisor_1 |
Docker HEALTHCHECK | Docker managed | Image has HEALTHCHECK directive |
config_kvision-scheduler_1 |
Docker HEALTHCHECK | Docker managed | Image has HEALTHCHECK directive |
config_kvision-vdirect_1 |
Docker HEALTHCHECK | Docker managed | Image has HEALTHCHECK directive |
config_kvision-help_1 |
Docker HEALTHCHECK | Docker managed | Image has HEALTHCHECK directive |
config_kvision-ted_1 |
Docker HEALTHCHECK | Docker managed | Image has HEALTHCHECK directive |
config_postgres_1 |
Docker HEALTHCHECK | Docker managed | Image has HEALTHCHECK directive |
config_kvision-snmp-trap-collector_1 |
Docker HEALTHCHECK | Docker managed | Image has HEALTHCHECK directive |
config_kvision-auto-engine_1 |
Docker HEALTHCHECK | Docker managed | Image has HEALTHCHECK directive |
config_kvision-lls_1 |
Docker HEALTHCHECK | Docker managed | Image has HEALTHCHECK directive |
config_kvision-assist-service_1 |
HTTP | :3005 (path auto-discovered) |
No Docker HEALTHCHECK; Node.js service; path cached on first successful response |
config_kvision-infra-rabbitmq_1 |
Docker HEALTHCHECK | Docker managed | Image has HEALTHCHECK directive |
config_kvision-ha-operator_1 |
HTTP | :8080 (path auto-discovered) |
No Docker HEALTHCHECK; Java HTTP service; path cached on first successful response |
config_kvision-dc-nginx_1 |
Docker HEALTHCHECK | Docker managed | Image has HEALTHCHECK directive |
process-exporter |
HTTP | :9256/metrics |
No Docker HEALTHCHECK; Prometheus exporter — /metrics returns 200 |
prometheus |
HTTP | :9090/-/ready |
No Docker HEALTHCHECK; standard Prometheus readiness endpoint |
alertmanager |
HTTP | :9093/-/healthy |
No Docker HEALTHCHECK; standard Alertmanager health endpoint |
postgres-exporter |
HTTP | :9187/metrics |
No Docker HEALTHCHECK; Prometheus exporter — /metrics returns 200 |
mysql-exporter |
HTTP | :9104/metrics |
No Docker HEALTHCHECK; Prometheus exporter — /metrics returns 200 |
es-exporter |
HTTP | :9114/metrics |
No Docker HEALTHCHECK; port 7979 HTTP fails; port 9114 serves /metrics |
node-exporter |
HTTP | :9100/metrics |
No Docker HEALTHCHECK; Prometheus exporter — /metrics returns 200 |
grafana |
HTTP | :3000/api/health |
No Docker HEALTHCHECK; Grafana health endpoint returns 200 |
config_kvision-infra-mariadb_1 |
Docker HEALTHCHECK | Docker managed | Image has HEALTHCHECK directive |
Verify what was actually cached after startup:
grep -E "auto-discover|falling back" /opt/radware/storage/scripts/Alert_Container/watchdog/watchdog.log
| Version | Date | Author | Changes |
|---|---|---|---|
| 1.5.4 | 2026-09-23 | Rahul Kumar | Versioned Docker image (watchdog:<VERSION>) driven by the root VERSION file; installer loads the packaged watchdog.tar, rejects an archive that does not carry the release tag, aborts on Compose failures, and verifies the running image; restart-loop detection now uses Docker RestartCount instead of counting poll observations; container_health_checks overrides implemented; fixed .env migration on root-owned files; watchdog-config.yaml made readable by the non-root container user |
| 1.5.3 | 2026-09-16 | Rahul Kumar | Resource Limits Enforced |
| 1.5.2 | 2026-08-31 | Rahul Kumar | Updated error message"Suppressing expected Cyber Controller SQL dump syntax-check container termination (exit 137) alert" |
| 1.5.1 | 2026-08-31 | Rahul Kumar | fixed ignore Dynamic container crash alert |
| 1.5.0 | 2026-08-27 | Rahul Kumar | Added ignore Dynamic container crash alert |
| 1.4.0 | 2026-08-17 | Rahul Kumar | Added INFO "recovered" alert |
| 1.3.3 | 2026-08-05 | Rahul Kumar | Added Auth True/false |
| 1.3.2 | 2026-07-28 | Rahul Kumar | Fixed SMTP Auth issue |
| 1.3.1 | 2026-07-21 | Egor Egorov | Updated Readme and Deployment guides |
| 1.3.0 | 2026-07-16 | Rahul Kumar | Added Upgrade Guide |
| 1.2.0 | 2026-07-16 | Rahul Kumar | Removed sudo and renamed the container |
| 1.1.0 | 2026-07-09 | Rahul Kumar | Added SNMPv3 support |
| 1.0.0 | 2026-06-25 | Rahul Kumar | Added Slack notifications and bug fixes |