tutorial

Uptime monitoring for Anchore container security scanning

--- Anchore Enterprise and the open-source Anchore Engine run continuous vulnerability scans against your container images. When the scanning service goes d...


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

  1. Log in to vigilmon.online and click Add Monitor.
  2. Choose HTTP(S) monitor.
  3. Enter: http://your-anchore-host:8228/health
  4. Set interval to 1 minute.
  5. Add a keyword check: must contain "up":true.
  6. Add your alert channel.
  7. 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:

  1. In Vigilmon, click Add Monitor.
  2. Choose SSL monitor.
  3. Enter: anchore.example.com (and any other HTTPS domains Anchore serves).
  4. Set alert threshold to 14 days before expiry.
  5. 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:

  1. API health monitor — confirms the Anchore API is up and responding, checked every minute by Vigilmon.
  2. Service-level monitors — individual checks for catalog, policy engine, and analyzer so you know exactly which component failed.
  3. PostgreSQL probe — catches database failures before Anchore silently stops persisting scan results.
  4. Feed freshness monitor — alerts when vulnerability data goes stale and scans start missing CVEs.
  5. 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

Monitor your app with Vigilmon

Free plan — 5 monitors, no credit card required. Up and running in 60 seconds.

Start free →