🐳 clair

Vulnerability Static Analysis for Containers

Docker Ready 16 Services Ports: 6060, 8080, 8443, 5432 11,025 stars
1. Pull Image docker pull library/*quay-image
2. 1-Click Launch Command docker run -d -p 6060:6060 --name clair *quay-image
3. Compose Deployment docker compose up -d
docker-compose.yaml
Download .yml
---
# This is just to hold a bunch of yaml anchors and try to consolidate parts of
# the config.
x-anchors:
  go: &go-image quay.io/projectquay/golang:1.25
  grafana: &grafana-image docker.io/grafana/grafana:10.3.1
  jaeger: &jaeger-image docker.io/jaegertracing/all-in-one:1
  pgadmin: &pgadmin-image docker.io/dpage/pgadmin4:5.7
  postgres: &postgres-image docker.io/library/postgres:15
  postgres-exporter: &postgres-exporter-image docker.io/prometheuscommunity/postgres-exporter:latest
  prom: &prom-image docker.io/prom/prometheus:latest
  pyroscope: &pyroscope-image docker.io/grafana/pyroscope:latest
  quay: &quay-image quay.io/projectquay/quay:latest
  rabbitmq: &rabbitmq-image docker.io/library/rabbitmq:3
  redis: &redis-image docker.io/library/redis:6
  skopeo: &skopeo-image quay.io/skopeo/stable:latest
  traefik: &traefik-image docker.io/library/traefik:v3.0
  clair-service: &clair-service
    image: *go-image
    depends_on:
      clair-database:
        condition: service_healthy
    volumes:
      - "./local-dev/clair:/etc/clair:ro"
      - ".:/src"
    # Can't specify the config via environment because maps are not recursively
    # merged.
    command:
      - go
      - run
      - .
      - -conf
      - /etc/clair/${CLAIR_CONFIG:-config.yaml}
    restart: unless-stopped
    working_dir: /src/cmd/clair

services:
  indexer:
    <<: *clair-service
    container_name: clair-indexer
    environment:
      CLAIR_MODE: "indexer"
  matcher:
    <<: *clair-service
    container_name: clair-matcher
    environment:
      CLAIR_MODE: "matcher"
  clair-database:
    container_name: clair-database
    image: *postgres-image
    environment:
      POSTGRES_HOST_AUTH_METHOD: trust
    volumes:
      - type: bind
        source: ./local-dev/clair/init.sql
        target: /docker-entrypoint-initdb.d/init.sql
    healthcheck:
      test:
        - CMD-SHELL
        - "pg_isready -U postgres"
      interval: 5s
      timeout: 4s
      retries: 12
      start_period: 10s
  traefik:
    container_name: clair-traefik
    image: *traefik-image
    depends_on:
      - matcher
      - indexer
    ports:
      - '6060:6060'
      - '8080:8080'
      - '8443'
      - '5432'
    volumes:
      - './local-dev/traefik/:/etc/traefik/:ro'

  # Debugging services -- use profile 'debug'
  pgadmin:
    container_name: clair-pgadmin
    profiles:
      - debug
    image: *pgadmin-image
    environment:
      PGADMIN_DEFAULT_EMAIL: [email protected]
      PGADMIN_DEFAULT_PASSWORD: clair
      PGADMIN_SERVER_JSON_FILE: /pgadmin4/config/servers.json
      SCRIPT_NAME: /pgadmin
    volumes:
      - "./local-dev/pgadmin:/pgadmin4/config"
    depends_on:
      - clair-database
  jaeger:
    container_name: clair-jaeger
    profiles:
      - debug
    image: *jaeger-image
    environment:
      QUERY_BASE_PATH: '/jaeger'
      COLLECTOR_OTLP_ENABLED: 'true'
  prometheus:
    container_name: clair-prometheus
    profiles:
      - debug
    image: *prom-image
    volumes:
      - "./local-dev/prometheus:/etc/prometheus/"
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.path=/prometheus'
      - '--web.external-url=http://localhost:8080/prom/'
      - '--web.console.libraries=/usr/share/prometheus/console_libraries'
      - '--web.console.templates=/usr/share/prometheus/consoles'
  pyroscope:
    container_name: clair-pyroscope
    profiles:
      - debug
    image: *pyroscope-image
    volumes:
      - ./local-dev/pyroscope:/etc/pyroscope/
    command:
      - server
    environment:
      PYROSCOPE_LOG_LEVEL: info
      PYROSCOPE_WAIT_AFTER_STOP: 'true'
  grafana:
    container_name: clair-grafana
    profiles:
      - debug
    image: *grafana-image
    user: "472"
    environment:
      GF_SERVER_ROOT_URL: /grafana
      GF_SERVER_SERVE_FROM_SUB_PATH: 'true'
      GF_INSTALL_PLUGINS: 'pyroscope-datasource,pyroscope-panel'
    volumes:
      - ./local-dev/grafana/provisioning/:/etc/grafana/provisioning/
    depends_on:
      - prometheus
      - pyroscope
  postgres-exporter:
    container_name: clair-postgres-exporter
    profiles:
      - debug
    image: *postgres-exporter-image
    environment:
      DATA_SOURCE_NAME: "postgresql://postgres@clair-database:5432/postgres?sslmode=disable"
    depends_on:
      clair-database:
        condition: service_healthy

  # Notifier services -- use profile 'notifier'
  notifier: &notifier
    <<: *clair-service
    container_name: clair-notifier
    profiles:
      - notifier
    environment:
      CLAIR_MODE: "notifier"
      NOTIFIER_TEST_MODE: "true"
  webhook-target:
    <<: *clair-service
    container_name: webhook-target
    profiles:
      - notifier
    working_dir: /src
    depends_on: {}
    command:
      - go
      - run
      - ./notifier/webhook/cmd/webhookd
      - -D
      - -key
      - c2VjcmV0
  rabbitmq:
    # This provides STOMP and AMQP on the usual ports.
    # The web UI is available on /rabbitmq
    container_name: clair-rabbitmq
    profiles:
      - notifier
    image: *rabbitmq-image
    command:
      - sh
      - -c
      - |
        set -e
        rabbitmq-plugins enable rabbitmq_stomp rabbitmq_management >/dev/null
        exec rabbitmq-server

  # Quay -- starts a Quay stack for integration testing.
  # Use profile 'quay'
  quay:
    container_name: clair-quay
    profiles:
      - quay
    image: *quay-image
    volumes:
      - "./local-dev/quay:/quay-registry/conf/stack"
    environment:
      DEBUGLOG: "true"
      IGNORE_VALIDATION: "true"
    depends_on:
      - redis
      - clair-database
  redis:
    container_name: quay-redis
    profiles:
      - quay
    image: *redis-image
  quay-notifier:
    <<: *notifier
    profiles:
      - quay
    environment:
      CLAIR_MODE: "notifier"
  skopeo:
    container_name: quay-skopeo
    profiles:
      - quay
    image: *skopeo-image
    entrypoint:
      - sleep
      - inf