Anchore Enterprise and the open-source Anchore Engine run continuous vulnerability scans against your container images. When the scanning service goes down — because the PostgreSQL database is unreachable, the catalog API crashes, or the analysis worker stops — new images get deployed without being checked. Teams find out at audit time or after an exploit, not in real time.
This tutorial covers production-grade uptime monitoring for Anchore deployments using Vigilmon. We will walk through:
- Monitoring the Anchore API health endpoints
- Monitoring the PostgreSQL database backing Anchore
- Monitoring Anchore's feed sync service
- Webhook alerts for DOWN/UP events
Prerequisites
- Anchore Engine or Anchore Enterprise running (Docker Compose or Kubernetes)
- Anchore API accessible on a host and port
- A free account at vigilmon.online
Part 1: Anchore health endpoints
Anchore exposes a standard health API. All Anchore services (catalog, analyzer, policy engine, API) serve a /health endpoint that returns HTTP 200 when healthy.
Verify the API health endpoint
# Default Anchore API port is 8228
curl http://localhost:8228/health
Expected response:
{
"hoststatus": "active",
"up": true,
"available": true,
"busy": false,
"message": "",
"detail": {},
"version": "v2"
}
Check the full system status
curl -u admin:foobar http://localhost:8228/v2/system/status
This returns the status of every Anchore sub-service: catalog, analyzer, simplequeue, policy-engine. Use this endpoint in your monitoring if you want full-stack visibility.
Part 2: Set up HTTP monitoring in Vigilmon
Monitor the Anchore API
- Log in to vigilmon.online and click Add Monitor.
- Choose HTTP(S) monitor.
- Enter:
http://your-anchore-host:8228/health - Set interval to 1 minute.
- Add a keyword check: must contain
"up":true. - Add your alert channel.
- Click Save.
The keyword check is critical. Anchore returns HTTP 200 even during degraded states — only the "up":true field confirms the service is actually operational.
Monitor individual Anchore services
For Anchore Enterprise deployments where services run as separate containers, add monitors for each:
| Service | Default Port | Health URL |
|---------|-------------|-----------|
| API Gateway | 8228 | http://host:8228/health |
| Catalog | 8082 | http://host:8082/health |
| Policy Engine | 8087 | http://host:8087/health |
| Analyzer | 8084 | http://host:8084/health |
| Notifications | 8668 | http://host:8668/health |
Add one Vigilmon monitor per service with the appropriate keyword check.
Part 3: Monitor the PostgreSQL database
Anchore stores all image metadata, policy results, and vulnerability mappings in PostgreSQL. A database failure means new scans cannot be persisted and policy evaluations return errors.
Create a PostgreSQL health endpoint
# pg_health.py — lightweight PostgreSQL probe for Vigilmon
import os
import psycopg2
from fastapi import FastAPI, Response
app = FastAPI()
DB_URL = os.environ.get("ANCHORE_DB_URL", "postgresql://anchore:anchore@localhost:5432/anchore")
@app.get("/health/db")
def db_health(response: Response):
try:
conn = psycopg2.connect(DB_URL, connect_timeout=5)
cursor = conn.cursor()
cursor.execute("SELECT 1")
cursor.close()
conn.close()
return {"status": "ok", "database": "connected"}
except Exception as e:
response.status_code = 503
return {"status": "error", "database": str(e)}
Run it alongside Anchore:
pip install fastapi uvicorn psycopg2-binary
uvicorn pg_health:app --host 0.0.0.0 --port 8091
Add a Vigilmon HTTP monitor for http://your-host:8091/health/db with keyword check "status":"ok".
Docker Compose setup
If Anchore runs via Docker Compose, add the probe as a sidecar:
# docker-compose.yml
version: "3.8"
services:
anchore-api:
image: anchore/enterprise:latest
ports:
- "8228:8228"
environment:
ANCHORE_DB_HOST: anchore-db
ANCHORE_DB_USER: anchore
ANCHORE_DB_PASSWORD: anchore
ANCHORE_DB_NAME: anchore
anchore-db:
image: postgres:14
environment:
POSTGRES_USER: anchore
POSTGRES_PASSWORD: anchore
POSTGRES_DB: anchore
volumes:
- anchore-db-data:/var/lib/postgresql/data
anchore-probe:
image: python:3.12-slim
command: >
sh -c "pip install -q fastapi uvicorn psycopg2-binary &&
uvicorn pg_health:app --host 0.0.0.0 --port 8091"
volumes:
- ./pg_health.py:/app/pg_health.py
working_dir: /app
ports:
- "8091:8091"
environment:
ANCHORE_DB_URL: "postgresql://anchore:anchore@anchore-db:5432/anchore"
depends_on:
- anchore-db
volumes:
anchore-db-data:
Part 4: Monitor feed sync
Anchore pulls vulnerability data from feeds (NVD, GitHub Advisory, OS vendor feeds). If feed sync fails for more than 24 hours, vulnerability data goes stale and scans miss newly disclosed CVEs.
Check feed sync status via the API
curl -u admin:foobar http://localhost:8228/v2/system/feeds
Response includes each feed's last sync time:
[
{
"name": "vulnerabilities",
"groups": [
{
"name": "alpine:3.17",
"last_sync": "2026-07-02T04:15:00Z",
"record_count": 2148
}
]
}
]
Build a feed-freshness endpoint
# anchore_feed_health.py
import os
import requests
from datetime import datetime, timezone, timedelta
from fastapi import FastAPI, Response
app = FastAPI()
ANCHORE_API = os.environ.get("ANCHORE_API_URL", "http://localhost:8228")
ANCHORE_USER = os.environ.get("ANCHORE_USER", "admin")
ANCHORE_PASS = os.environ.get("ANCHORE_PASS", "foobar")
MAX_FEED_AGE_HOURS = int(os.environ.get("MAX_FEED_AGE_HOURS", "26"))
@app.get("/health/feeds")
def feed_health(response: Response):
try:
resp = requests.get(
f"{ANCHORE_API}/v2/system/feeds",
auth=(ANCHORE_USER, ANCHORE_PASS),
timeout=10,
)
resp.raise_for_status()
feeds = resp.json()
except Exception as e:
response.status_code = 503
return {"status": "error", "detail": str(e)}
stale = []
now = datetime.now(timezone.utc)
threshold = timedelta(hours=MAX_FEED_AGE_HOURS)
for feed in feeds:
for group in feed.get("groups", []):
last_sync_str = group.get("last_sync")
if last_sync_str:
last_sync = datetime.fromisoformat(last_sync_str.replace("Z", "+00:00"))
if now - last_sync > threshold:
stale.append({
"feed": feed["name"],
"group": group["name"],
"last_sync": last_sync_str,
"age_hours": round((now - last_sync).total_seconds() / 3600, 1),
})
if stale:
response.status_code = 503
return {"status": "stale", "stale_feeds": stale}
return {"status": "ok", "feeds_checked": sum(len(f.get("groups", [])) for f in feeds)}
Add a Vigilmon monitor for http://your-host:8092/health/feeds with keyword "status":"ok" and a 30-minute check interval.
Part 5: Kubernetes deployment monitoring
For Anchore running in Kubernetes, add readiness probes and expose the health endpoint as a dedicated service:
# anchore-monitor-service.yaml
apiVersion: v1
kind: Service
metadata:
name: anchore-health
namespace: anchore
spec:
selector:
app: anchore-api
ports:
- name: health
port: 8228
targetPort: 8228
type: LoadBalancer
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: anchore-api
namespace: anchore
spec:
template:
spec:
containers:
- name: anchore-api
image: anchore/enterprise:latest
livenessProbe:
httpGet:
path: /health
port: 8228
initialDelaySeconds: 60
periodSeconds: 30
failureThreshold: 3
readinessProbe:
httpGet:
path: /health
port: 8228
initialDelaySeconds: 30
periodSeconds: 10
Point Vigilmon at the LoadBalancer IP or hostname once the service is assigned an external IP.
Part 6: Webhook alerts
Configure Vigilmon to call your incident management system when Anchore goes down:
// Example: Node.js webhook receiver
import express from 'express';
const app = express();
app.use(express.json());
app.post('/webhook/vigilmon', async (req, res) => {
const { monitor_name, status, url, checked_at, response_code } = req.body;
if (status === 'down') {
console.error('[VIGILMON] Anchore monitor DOWN', {
monitor: monitor_name,
url,
code: response_code,
at: checked_at,
});
// Block deployments — no Anchore means no policy evaluation
await setDeploymentGate('blocked', {
reason: `Anchore unavailable: ${monitor_name}`,
since: checked_at,
});
await notifySecurityTeam({ monitor: monitor_name, url });
} else if (status === 'up') {
console.info('[VIGILMON] Anchore monitor recovered', { monitor: monitor_name });
await setDeploymentGate('open', { reason: 'Anchore restored' });
}
res.sendStatus(204);
});
Vigilmon sends this payload on DOWN and UP transitions:
{
"monitor_id": "mon_anchore01",
"monitor_name": "Anchore API Health",
"status": "down",
"url": "http://anchore.internal:8228/health",
"checked_at": "2026-07-02T10:00:00Z",
"response_code": 503,
"response_time_ms": 5001
}
Part 7: SSL monitoring for Anchore Enterprise
Anchore Enterprise deployments typically run behind TLS. Monitor each certificate:
- In Vigilmon, click Add Monitor.
- Choose SSL monitor.
- Enter:
anchore.example.com(and any other HTTPS domains Anchore serves). - Set alert threshold to 14 days before expiry.
- Add your alert channel.
An expired certificate blocks all Anchore API calls from scanners and CI pipelines without any clear error message.
Summary
Your Anchore deployment now has layered monitoring:
- API health monitor — confirms the Anchore API is up and responding, checked every minute by Vigilmon.
- Service-level monitors — individual checks for catalog, policy engine, and analyzer so you know exactly which component failed.
- PostgreSQL probe — catches database failures before Anchore silently stops persisting scan results.
- Feed freshness monitor — alerts when vulnerability data goes stale and scans start missing CVEs.
- SSL monitors — alerts before certificate expiry breaks API access from scanners and CI.
Vigilmon handles check scheduling, multi-region polling, and alert routing. When Anchore goes down, you know within 60 seconds — before unscanned images reach production.
Monitor your Anchore deployment free at vigilmon.online
#anchore #containersecurity #vulnerability #devops #monitoring