DLIA is an AI-powered Docker log monitoring agent that uses Large Language Models (LLMs) to intelligently analyze container logs, detect anomalies, and provide contextual insights over time.
- π€ Semantic Log Analysis - Uses LLMs to understand log context, not just keyword matching.
- π Historical Context - Tracks trends over time to detect gradual degradation.
- π€« Natural Language Filtering - Ignore routine errors or expected noise by providing instructions in plain English (e.g., "Ignore 'connection refused' during nightly backups").
- π§ Self-Cleaning Knowledge Base - Automatically "forgets" issues based on a configurable retention period (default: 30 days), keeping the knowledge base relevant.
- π§ Customizable AI Prompts - Override the default AI instructions to tune the analysis process for your specific needs.
- π Privacy-First - Automatic anonymization of IPs, secrets, and sensitive data.
- π Flexible LLM Backend - Works with OpenAI, OpenRouter, Ollama, or any OpenAI-compatible API.
- π Markdown Reports - Human-readable persistent knowledge base.
- π Universal Notifications - Email, Discord, Slack, and more via Shoutrrr.
- π³ Docker Native - Direct Docker socket integration.
- β‘ Single Binary - No runtime dependencies except Docker.
- π¦ Multi-arch Docker Images - Available for amd64 and arm64.
- Docker installed and running
- LLM API access (OpenAI, OpenRouter, or local via Ollama)
# Run a one-time scan
docker run --rm \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
-v ./dlia-data:/data \
-e DLIA_LLM_API_KEY=your-key-here \
-e DLIA_LLM_MODEL=gpt-4o-mini \
zorak1103/dlia:latest scan
# Or use docker-compose
curl -O https://raw.githubusercontent.com/zorak1103/dlia/main/docker-compose.yml
export DLIA_LLM_API_KEY=your-key-here
docker compose run --rm dlia scanRequires Go 1.26 or higher.
# Clone the repository
git clone https://github.com/zorak1103/dlia.git
cd dlia
# Install dependencies
go mod download
# Build the binary
go build -o dlia.exe .
# Initialize configuration (creates config.yaml, .env, and default dirs)
./dlia.exe init
# Edit .env to add your API key
# DLIA_LLM_API_KEY=your-key-here
# Edit config.yaml with your LLM API settings
notepad config.yaml
# (Optional) Create custom prompts or ignore files (see Configuration section)
# Test with a dry run
./dlia.exe scan --dry-run
# Perform your first scan
./dlia.exe scanAnalyzes container logs once and exits. Perfect for cron jobs.
# Scan all containers
dlia scan
# Scan specific containers
dlia scan --filter "nginx.*"
# Analyze last 24 hours (ignore state)
dlia scan --lookback 24h
# Test without calling LLM
dlia scan --dry-run
# Enable LLM conversation logging for debugging
dlia scan --llmlogCreates default config.yaml, .env file, and the reports and knowledge_base directory structure (including knowledge_base/services/ subdirectory). It uses embedded templates, so the binary is fully self-contained.
# Create config and directories
dlia init
# Force overwrite existing configs
dlia init --forceManage log scan cursors.
# View current state
dlia state list
# Reset all containers
dlia state reset --force
# Reset specific containers
dlia state reset nginx --forceClean up storage for containers that no longer exist in Docker.
# List obsolete container data
dlia cleanup list
# Preview what would be deleted (dry-run)
dlia cleanup execute --dry-run
# Remove obsolete data with confirmation
dlia cleanup execute
# Remove obsolete data without confirmation
dlia cleanup execute --forceWhat gets cleaned:
- State file entries (
state.json) - Knowledge base files (
knowledge_base/services/*.md) - Report directories (
reports/*/) - LLM log directories (
logs/llm/*/)
cleanup list or use --dry-run before executing. Use --force only when you're certain.
--config- Path to config file (default:./config.yaml)--verbose,-v- Enable verbose logging
DLIA uses a config.yaml file with environment variable overrides.
llm:
base_url: "https://api.openai.com/v1" # or OpenRouter, Ollama, etc.
api_key: "" # Set via DLIA_LLM_API_KEY
model: "gpt-4o-mini"
max_tokens: 128000
docker:
socket_path: "" # Auto-detects for Linux, macOS, and Windows
notification:
shoutrrr_url: "" # smtp://, discord://, slack://, etc.
enabled: false
output:
reports_dir: "./reports"
knowledge_base_dir: "./knowledge_base"
state_file: "./state.json"
ignore_dir: "./config/ignore" # Directory for per-container ignore rules
llm_log_dir: "./logs/llm" # Directory for LLM request/response logs (--llmlog flag)
knowledge_retention_days: 30 # Retention period for knowledge base entries (1-365 days)
privacy:
anonymize_ips: true
anonymize_secrets: true
# Optional: Paths to custom prompt templates.
# Leave empty to use the built-in defaults.
prompts:
system_prompt: ""
analysis_prompt: ""
chunk_summary_prompt: ""
synthesis_prompt: ""
executive_summary_prompt: ""All config options can be overridden with environment variables:
DLIA_LLM_API_KEY=sk-xxx
DLIA_LLM_MODEL=gpt-4o
DLIA_LLM_BASE_URL=https://openrouter.ai/api/v1
DLIA_NOTIFICATION_SHOUTRRR_URL=smtp://user:[email protected]:587/?[email protected]&[email protected]
DLIA_PROMPTS_SYSTEM_PROMPT=./config/prompts/my_system_prompt.md
DLIA_OUTPUT_KNOWLEDGE_RETENTION_DAYS=90You can instruct the AI to ignore specific, known issues for a container by creating a Markdown file with natural language rules. This is more flexible than simple keyword or regex filtering.
- Create a directory named
config/ignore. - Inside, create a file named
{container_name}.md(e.g.,my-app.md). - Write your instructions in the file.
Example: config/ignore/backup-service.md
- Ignore any "connection refused" errors that happen between 2 AM and 4 AM, as this is the expected maintenance window.
- Disregard warnings about "disk space low" if the usage is below 95%.The agent will automatically load these instructions and use them during analysis.
DLIA supports pre-LLM filtering using regular expression patterns to reduce token costs by excluding irrelevant log entries before they reach the LLM. This is particularly useful for filtering out routine debug messages, health checks, or other high-volume noise.
Regexp filtering happens before logs are sent to the LLM, providing:
- Direct cost reduction - Fewer tokens = lower API bills
- Faster analysis - Less data to process
- Focused insights - AI concentrates on meaningful logs
Add regexp_filters to your config.yaml, with container-specific pattern lists:
regexp_filters:
my-app:
enabled: true
patterns:
- "^DEBUG:" # Exclude lines starting with "DEBUG:"
- "healthcheck" # Exclude lines containing "healthcheck"
- "GET /metrics" # Exclude metrics endpoint calls
nginx:
enabled: true
patterns:
- "\\[info\\]" # Exclude info-level logs
- "GET /health" # Exclude health check requestsEach pattern uses Go regexp syntax (documentation). Common examples:
^pattern- Match at start of linepattern$- Match at end of line.*pattern.*- Match anywhere in line (implicit in substring matches)\\[info\\]- Match literal brackets (escape with\\)
Use the --filter-stats flag to see filtering statistics:
dlia scan --filter-statsOutput shows lines filtered per container:
Container: my-app
Filtered: 1,234/5,000 lines (24.7%)
Container: nginx
Filtered: 890/2,100 lines (42.4%)
This helps you:
- Verify patterns are working correctly
- Estimate cost savings (fewer lines = fewer tokens)
- Tune patterns for optimal filtering
DLIA supports two complementary filtering mechanisms:
| Feature | Regexp Filters (This Section) | Natural Language Filtering (config/ignore/) |
|---|---|---|
| When Applied | Before LLM processing | During AI analysis |
| Purpose | Cost reduction (exclude logs) | Context refinement (ignore known issues) |
| Syntax | Regular expressions | Plain English instructions |
| Best For | High-volume noise (debug logs, health checks) | Contextual patterns (maintenance windows, expected errors) |
| Cost Impact | Reduces tokens sent to LLM | Logs still sent, AI instructed to ignore |
Best Practice: Use regexp filters for volume reduction, then use semantic filtering for nuanced context-aware filtering of remaining logs.
Example: Filter out debug logs with regexp (^DEBUG:), then use semantic filtering to ignore "connection timeout during nightly backup window."
You can override any of the default prompts the AI uses for its analysis. This allows you to fine-tune its behavior, focus, and output format.
- Create a directory (e.g.,
config/prompts). - Create a new Markdown file for the prompt you want to override (e.g.,
custom_system_prompt.md). - Update
config.yamlto point to your new file.
Example: config.yaml
prompts:
system_prompt: "./config/prompts/custom_system_prompt.md"
analysis_prompt: "./config/prompts/custom_analysis.md"If a path is specified but the file is not found, DLIA will log a warning and fall back to the internal default prompt.
DLIA automatically manages the knowledge base by removing old entries based on a configurable retention period. This keeps the knowledge base relevant and focused on recent issues.
Set the retention period in config.yaml:
output:
knowledge_retention_days: 30 # Keep entries for 30 days (default)Or via environment variable:
export DLIA_OUTPUT_KNOWLEDGE_RETENTION_DAYS=90Valid range: 1-365 days
- Each knowledge base entry includes a timestamp
- During every scan, entries older than the retention period are automatically removed
- Only affects service-specific knowledge base files (
knowledge_base/services/*.md) - Global summaries and reports are not affected
Short retention (7-14 days):
- Rapidly changing environments
- Development/staging systems
- Focus on very recent issues
Medium retention (30-60 days):
- Production systems (default)
- Balance between history and relevance
- Good for most use cases
Long retention (90-365 days):
- Compliance or audit requirements
- Long-term trend analysis
- Infrequent issues that need longer context
Example:
# Development environment - keep only recent issues
output:
knowledge_retention_days: 7
# Production - standard retention
output:
knowledge_retention_days: 30
# Compliance - long-term retention
output:
knowledge_retention_days: 180zorak1103/dlia:latest- Latest stable release (multi-arch)zorak1103/dlia:vX.Y.Z- Specific version (multi-arch)zorak1103/dlia:vX.Y.Z-amd64- Platform-specificzorak1103/dlia:vX.Y.Z-arm64- Platform-specific
# Basic scan
docker run --rm \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
-v ./dlia-data:/data \
-e DLIA_LLM_API_KEY=your-key-here \
zorak1103/dlia:latest scan
# With custom config file
docker run --rm \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
-v ./dlia-data:/data \
-v ./config.yaml:/data/config.yaml:ro \
-e DLIA_LLM_API_KEY=your-key-here \
zorak1103/dlia:latest scan --config /data/config.yaml
# Dry run (test without calling LLM)
docker run --rm \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
zorak1103/dlia:latest scan --dry-run
# View help
docker run --rm zorak1103/dlia:latest --helpservices:
dlia:
image: zorak1103/dlia:latest
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./dlia-data:/data
environment:
- DLIA_LLM_API_KEY=${DLIA_LLM_API_KEY}
- DLIA_LLM_MODEL=${DLIA_LLM_MODEL:-gpt-4o-mini}
command: scan# Add to crontab for hourly scans
0 * * * * docker run --rm -v /var/run/docker.sock:/var/run/docker.sock:ro -v /opt/dlia:/data -e DLIA_LLM_API_KEY=xxx zorak1103/dlia:latest scan- Mount Docker socket as read-only (
:ro) - Container runs as non-root user (UID 1000)
- Minimal Alpine base image (~10MB)
Contributions are welcome! Please feel free to submit issues and pull requests.