A lightweight, efficient background service that monitors Docker containers and notifies you when newer image versions are available. Designed for deployment in Coolify and other containerized environments.
- Automatic Detection: Monitors all running containers on the host
- Multiple Registries: Supports DockerHub and private registries
- Smart Filtering: Configurable include/exclude patterns for images
- Multiple Notification Channels: Email (SMTP) and Telegram Bot support
- Semantic Versioning: Intelligent version comparison for updates
- Rate Limiting: Respects registry API limits
- Scheduling: Configurable check intervals with cron-like scheduling
- Production Ready: Comprehensive logging, health checks, and error handling
- Resource Efficient: Minimal CPU and memory footprint
- Containerized: Ready for deployment in Docker/Kubernetes/Coolify
βββββββββββββββββββ ββββββββββββββββββββ βββββββββββββββββββ
β Scheduler βββββΆβ Docker Scanner βββββΆβ Registry Client β
βββββββββββββββββββ ββββββββββββββββββββ βββββββββββββββββββ
β β
βΌ βΌ
βββββββββββββββββββ ββββββββββββββββββββ βββββββββββββββββββ
β Notification ββββββ Controller ββββββ Version Comp. β
β System β ββββββββββββββββββββ βββββββββββββββββββ
βββββββββββββββββββ
The service follows a modular architecture:
- Docker Scanner: Detects running containers and extracts image information
- Registry Client: Queries DockerHub/registries for available updates
- Version Comparator: Intelligently compares semantic versions
- Notification System: Sends alerts via multiple channels
- Scheduler: Manages periodic checks and task execution
- Clone the repository:
git clone <repository-url>
cd docker-notify- Configure the service:
cp configs/config.yaml configs/config.local.yaml
# Edit configs/config.local.yaml with your settings- Set up environment variables:
# Create .env file
cat > .env << EOF
SMTP_HOST=smtp.gmail.com
SMTP_USERNAME=your-email@gmail.com
SMTP_PASSWORD=your-app-password
EMAIL_FROM=docker-notify@yourdomain.com
EMAIL_TO=admin@yourdomain.com
TELEGRAM_BOT_TOKEN=YOUR_BOT_TOKEN_HERE
EOF- Run with Docker Compose:
docker-compose up -d# Build the image
docker build -t docker-notify .
# Run the container
docker run -d \
--name docker-notify \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
-v ./configs/config.yaml:/etc/docker-notify/config.yaml:ro \
-e SMTP_HOST=smtp.gmail.com \
-e SMTP_USERNAME=your-email@gmail.com \
-e SMTP_PASSWORD=your-app-password \
-e EMAIL_TO=admin@yourdomain.com \
docker-notify# Build from source
go mod download
go build -o docker-notify ./cmd/main.go
# Run directly
./docker-notify -config configs/config.yamlCreate a config.yaml file with your settings:
# Application settings
app:
check_interval: "30m" # Check every 30 minutes
timezone: "UTC"
max_concurrency: 10
# Docker settings
docker:
socket_path: "unix:///var/run/docker.sock"
filters:
exclude:
- "*:latest" # Skip latest tags
- "scratch:*" # Skip scratch images
check_latest: false
check_private: true
# Notification settings
notifications:
channels:
- "email"
- "telegram"
email:
smtp:
host: "smtp.gmail.com"
port: 587
username: "your-email@gmail.com"
password: "your-app-password"
use_tls: true
from: "docker-notify@yourdomain.com"
to:
- "admin@yourdomain.com"
telegram:
bot_token: "YOUR_BOT_TOKEN_HERE"
chat_ids:
- 123456789
parse_mode: "HTML"
# Logging
logging:
level: "info"
format: "json"You can override ANY configuration value with environment variables. This provides multiple ways to configure the service:
| Variable | Description | Example |
|---|---|---|
CHECK_INTERVAL |
How often to check for updates | 30m, 1h, 24h |
TIMEZONE |
Timezone for scheduling | UTC, America/New_York |
MAX_CONCURRENCY |
Max concurrent registry calls | 10 |
REGISTRY_TIMEOUT |
Registry API timeout | 30s |
| Variable | Description | Example |
|---|---|---|
DOCKER_SOCKET |
Docker socket path | unix:///var/run/docker.sock |
DOCKER_API_VERSION |
Docker API version | 1.43 (empty for auto) |
| Variable | Description | Example |
|---|---|---|
CHECK_LATEST |
Check latest tags | true, false |
CHECK_PRIVATE |
Check private registries | true, false |
INCLUDE_PATTERNS |
Whitelist patterns (comma-separated) | nginx:*,postgres:* |
EXCLUDE_PATTERNS |
Blacklist patterns (comma-separated) | *:latest,scratch:* |
EXCLUDE_PRERELEASE |
Exclude pre-release versions | true, false |
EXCLUDE_WINDOWS |
Exclude Windows variants | true, false |
ONLY_STABLE |
Only stable semantic versions | true, false |
| Variable | Description | Example |
|---|---|---|
SMTP_HOST |
SMTP server hostname | smtp.gmail.com |
SMTP_PORT |
SMTP server port | 587 |
SMTP_USERNAME |
SMTP username | your-email@gmail.com |
SMTP_PASSWORD |
SMTP password | your-app-password |
SMTP_USE_TLS |
Use TLS encryption | true, false |
EMAIL_FROM |
From email address | docker-notify@yourdomain.com |
EMAIL_TO |
To email addresses (comma-separated) | admin@domain.com,ops@domain.com |
EMAIL_SUBJECT |
Email subject | Docker Image Updates |
| Variable | Description | Example |
|---|---|---|
TELEGRAM_BOT_TOKEN |
Bot token from @BotFather | 123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11 |
TELEGRAM_CHAT_IDS |
Chat IDs (comma-separated) | 123456789,-987654321 |
TELEGRAM_PARSE_MODE |
Message formatting | HTML, Markdown |
| Variable | Description | Example |
|---|---|---|
NOTIFICATION_CHANNELS |
Enabled channels (comma-separated) | email,telegram |
ONCE_PER_UPDATE |
Notify once per update | true, false |
COOLDOWN_PERIOD |
Min time between notifications | 24h, 1h |
GROUP_UPDATES |
Group multiple updates | true, false |
MAX_UPDATES_PER_NOTIFICATION |
Max updates per notification | 10 |
| Variable | Description | Example |
|---|---|---|
LOG_LEVEL |
Log level | debug, info, warn, error |
Create a .env file or export variables:
# Copy the example file
cp .env.example .env
# Edit .env with your values
# Or export directly
export CHECK_INTERVAL="1h"
export TELEGRAM_BOT_TOKEN="your_token_here"
export TELEGRAM_CHAT_IDS="123456789"
docker-compose up -dUse the YAML config file as base and override specific values:
# configs/config.yaml
app:
check_interval: "30m"
notifications:
channels: ["telegram"]
telegram:
bot_token: "placeholder"# Override bot token via environment
export TELEGRAM_BOT_TOKEN="real_token_here"
docker-compose up -dPass the entire configuration as YAML content:
export CONFIG_CONTENT='
app:
check_interval: "1h"
timezone: "America/New_York"
docker:
filters:
exclude: ["*:latest"]
notifications:
channels: ["telegram"]
telegram:
bot_token: "your_token"
chat_ids: [123456789]
'
docker-compose up -dThis method takes precedence over the config file, allowing complete dynamic configuration.
Pass variables directly to docker-compose:
CHECK_INTERVAL=1h TELEGRAM_BOT_TOKEN=your_token docker-compose up -dSee the following files for complete examples:
.env.example- Environment variables templatescripts/config-example.sh- Comprehensive configuration scriptconfigs/config.yaml- Full YAML configuration template
-
Gmail Setup:
- Enable 2-factor authentication
- Generate an App Password
- Use
smtp.gmail.com:587with TLS
-
Outlook Setup:
- Use
smtp-mail.outlook.com:587with TLS
- Use
-
Custom SMTP:
- Configure your SMTP server details
-
Create a Bot:
- Message @BotFather on Telegram
- Send
/newbotand follow instructions - Get your bot token
-
Get Chat ID:
- Message @userinfobot to get your chat ID
- For group chats, add the bot to the group and use negative chat ID
-
Test the Bot:
curl -X POST "https://api.telegram.org/bot<YOUR_BOT_TOKEN>/sendMessage" \ -H "Content-Type: application/json" \ -d '{"chat_id": "<YOUR_CHAT_ID>", "text": "Test message"}'
- Create a new service in Coolify
- Set the Docker image: Use the built image or build from source
- Configure environment variables in the Coolify dashboard
- Mount volumes:
/var/run/docker.sock:/var/run/docker.sock:ro./config.yaml:/etc/docker-notify/config.yaml:ro
- Deploy the service
apiVersion: apps/v1
kind: Deployment
metadata:
name: docker-notify
spec:
replicas: 1
selector:
matchLabels:
app: docker-notify
template:
metadata:
labels:
app: docker-notify
spec:
containers:
- name: docker-notify
image: docker-notify:latest
env:
- name: SMTP_HOST
value: "smtp.gmail.com"
- name: EMAIL_TO
value: "admin@yourdomain.com"
volumeMounts:
- name: docker-socket
mountPath: /var/run/docker.sock
readOnly: true
- name: config
mountPath: /etc/docker-notify/config.yaml
subPath: config.yaml
volumes:
- name: docker-socket
hostPath:
path: /var/run/docker.sock
- name: config
configMap:
name: docker-notify-configversion: '3.8'
services:
docker-notify:
image: docker-notify:latest
deploy:
replicas: 1
placement:
constraints:
- node.role == manager
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
environment:
- SMTP_HOST=smtp.gmail.com
- EMAIL_TO=admin@yourdomain.com
networks:
- docker-notify-net# Run with default config
./docker-notify
# Specify config file
./docker-notify -config /path/to/config.yaml
# Run a single check and exit
./docker-notify -check-once
# Test notifications and exit
./docker-notify -test
# Set log level
./docker-notify -log-level debug
# Show version
./docker-notify -versionThe service includes built-in health checks:
# Docker health check
docker exec docker-notify /docker-notify -test
# HTTP health endpoint (if enabled)
curl http://localhost:8080/healthLogs are structured in JSON format:
{
"level": "info",
"msg": "Found 3 image updates",
"time": "2024-01-01T12:00:00Z",
"updates_found": 3,
"checked_count": 15,
"duration": "2.5s"
}Key metrics tracked:
- Number of containers checked
- Updates found and notified
- Registry API call success rate
- Notification delivery status
- Task execution times
-
Docker Socket Permission Denied:
# Add user to docker group sudo usermod -aG docker $USER # Or run with appropriate permissions sudo ./docker-notify
-
Registry Rate Limits:
- Reduce
check_intervalfrequency - Adjust
rate_limitsettings in config - Use registry authentication
- Reduce
-
Email Not Sending:
- Check SMTP credentials
- Verify firewall/network settings
- Test with telnet:
telnet smtp.gmail.com 587
-
Telegram Bot Not Working:
- Verify bot token
- Check chat ID (use @userinfobot)
- Ensure bot can send messages to chat
Run with debug logging:
./docker-notify -log-level debug# Test all components
./docker-notify -test
# Test specific notification channel
curl -X POST localhost:8080/api/test/email
curl -X POST localhost:8080/api/test/telegram- Docker Socket: Read-only access to
/var/run/docker.sock - User: Run as non-root user (appuser) in container
- Network: Only outbound connections to registries and notification services
- Use environment variables for sensitive data
- Consider external secret management (Vault, K8s secrets)
- Rotate credentials regularly
- Run in isolated network
- Use TLS for all external communications
- Consider using registry mirrors/proxies
- Web Dashboard: Real-time monitoring interface
- More Notification Channels: Slack, Discord, Webhook support
- GitOps Integration: Automatic PR creation for updates
- Custom Update Policies: Skip patch versions, pre-release handling
- Multi-Host Support: Monitor multiple Docker hosts
- Metrics Export: Prometheus metrics endpoint
- Update Automation: Automatic image updates with rollback
- Security Scanning: Vulnerability alerts for images
Future REST API for:
- Manual trigger checks
- Configuration management
- Status and metrics
- Notification testing
- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-feature - Commit your changes:
git commit -m 'Add amazing feature' - Push to the branch:
git push origin feature/amazing-feature - Open a Pull Request
# Clone repository
git clone <repository-url>
cd docker-notify
# Install dependencies
go mod download
# Run tests
go test ./...
# Build
go build -o docker-notify ./cmd/main.go
# Run locally
./docker-notify -config configs/config.yamlThis project is licensed under the MIT License - see the LICENSE file for details.
- Docker API for container introspection
- DockerHub Registry API for image metadata
- Go community for excellent libraries:
- logrus for logging
- robfig/cron for scheduling
- go-telegram-bot-api for Telegram
- gomail for email notifications