This guide provides production-ready Docker Compose configurations for m1/netcheck (Rust variant with Prometheus metrics). The shell script variant does not have an official Docker image.
| Aspect | Details |
|---|---|
| Project | m1/netcheck |
| Latest Version | v0.0.1 (March 2024) |
| Docker Image | ghcr.io/m1/netcheck:latest |
| Architecture | amd64, arm64 |
| Resource Usage | ~10-20 MB RAM, minimal CPU |
| Port | 8080 (metrics endpoint) |
For Docker installation, see Docker.
Create a directory and docker-compose.yml:
mkdir -p /opt/netcheck
cd /opt/netcheck
services:
netcheck:
image: ghcr.io/m1/netcheck:latest
container_name: netcheck
restart: unless-stopped
ports:
- "8080:8080"
command:
- run
- --target
- external=https://one.one.one.one,https://dns.google
- --timeout
- "5s"
- --connect-timeout
- "3s"
- --failure-threshold
- "3"
- --wait-time
- "10s"
Start the service:
docker compose up -d
Verify itβs running:
curl http://localhost:8080/metrics
docker logs netcheck
services:
netcheck:
image: ghcr.io/m1/netcheck:latest@sha256:<digest>
container_name: netcheck
restart: unless-stopped
ports:
- "127.0.0.1:8080:8080"
command:
- run
- --target
- external=https://one.one.one.one,https://dns.google,https://api.github.com
- --target
- internal=http://kubernetes.default.svc.cluster.local:443
- --timeout
- "5s"
- --connect-timeout
- "3s"
- --failure-threshold
- "3"
- --wait-time
- "10s"
# Security hardening
user: "1000:1000"
read_only: true
tmpfs:
- /tmp:noexec,nosuid,size=64m
cap_drop:
- ALL
security_opt:
- no-new-privileges:true
# Resource limits
deploy:
resources:
limits:
cpus: '0.5'
memory: 64M
reservations:
cpus: '0.1'
memory: 16M
# Health check
healthcheck:
test: ["CMD", "wget", "-q", "--spider", "http://localhost:8080/metrics"]
interval: 30s
timeout: 10s
retries: 3
start_period: 10s
# Logging
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
networks:
- monitoring
networks:
monitoring:
driver: bridge
ipam:
config:
- subnet: 172.28.0.0/16
| Setting | Purpose |
|---|---|
user: "1000:1000" |
Run as non-root user |
read_only: true |
Read-only root filesystem |
tmpfs |
Writable temp directory in memory |
cap_drop: ALL |
Drop all Linux capabilities |
no-new-privileges |
Prevent privilege escalation |
deploy.resources |
Limit CPU and memory usage |
127.0.0.1:8080 |
Bind to localhost only (use reverse proxy) |
Netcheck uses command-line arguments instead of environment variables. For Docker Compose, use command: to set options:
command:
- run
- --target
- external=https://one.one.one.one
- --timeout
- "5s"
| Option | Description | Default | Example |
|---|---|---|---|
--target |
Target URLs to check (can specify multiple) | Required | external=https://one.one.one.one |
--timeout |
Request timeout | 5s |
--timeout "10s" |
--connect-timeout |
Connection timeout | 3s |
--connect-timeout "5s" |
--failure-threshold |
Failures before marking down | 3 |
--failure-threshold "5" |
--wait-time |
Time between checks | 10s |
--wait-time "30s" |
services:
netcheck:
image: ghcr.io/m1/netcheck:latest
container_name: netcheck
restart: unless-stopped
command:
- run
- --target
- external=https://one.one.one.one,https://dns.google
networks:
- monitoring
prometheus:
image: prom/prometheus:v2.50.1
container_name: prometheus
restart: unless-stopped
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
- prometheus_data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
- '--web.console.libraries=/etc/prometheus/console_libraries'
- '--web.console.templates=/etc/prometheus/consoles'
- '--storage.tsdb.retention.time=15d'
- '--web.enable-lifecycle'
ports:
- "127.0.0.1:9090:9090"
networks:
- monitoring
depends_on:
- netcheck
grafana:
image: grafana/grafana:10.3.3
container_name: grafana
restart: unless-stopped
volumes:
- grafana_data:/var/lib/grafana
- ./grafana/provisioning:/etc/grafana/provisioning:ro
environment:
- GF_SECURITY_ADMIN_USER=admin
- GF_SECURITY_ADMIN_PASSWORD=change-me-strong-password
- GF_SERVER_ROOT_URL=https://grafana.example.com
- GF_AUTH_ANONYMOUS_ENABLED=false
ports:
- "127.0.0.1:3000:3000"
networks:
- monitoring
depends_on:
- prometheus
volumes:
prometheus_data:
grafana_data:
networks:
monitoring:
driver: bridge
prometheus.yml)global:
scrape_interval: 30s
evaluation_interval: 30s
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
- job_name: 'netcheck'
static_configs:
- targets: ['netcheck:8080']
metrics_path: /metrics
scrape_interval: 30s
scrape_timeout: 10s
| Metric | Query | Description |
|---|---|---|
| Target Status | netcheck_target_up |
1 = up, 0 = down |
| Response Time | histogram_quantile(0.95, rate(netcheck_response_time_seconds_bucket[5m])) |
95th percentile response time |
| Check Count | rate(netcheck_checks_total[5m]) |
Checks per second |
For secure public access with TLS:
server {
listen 80;
server_name netcheck.example.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name netcheck.example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
# Security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 30s;
proxy_connect_timeout 5s;
}
# Rate limiting
location /metrics {
limit_req zone=api burst=10 nodelay;
proxy_pass http://127.0.0.1:8080/metrics;
}
}
Netcheck is stateless β no backup required for the application. For persistent metrics:
# Stop Prometheus
docker compose stop prometheus
# Backup data volume
tar -czvf prometheus-backup-$(date +%Y%m%d).tar.gz \
/var/lib/docker/volumes/netcheck_prometheus_data/_data
# Restart
docker compose start prometheus
# Stop Prometheus
docker compose stop prometheus
# Restore data
tar -xzvf prometheus-backup-20260216.tar.gz \
-C /var/lib/docker/volumes/netcheck_prometheus_data/_data
# Fix permissions
chown -R 472:472 /var/lib/docker/volumes/netcheck_prometheus_data/_data
# Restart
docker compose start prometheus
# Check container status
docker ps -a --filter name=netcheck
# View resource usage
docker stats netcheck
# View logs
docker logs --tail 100 netcheck
docker logs -f netcheck
Add to prometheus.yml:
groups:
- name: netcheck_alerts
rules:
- alert: NetcheckTargetDown
expr: netcheck_target_up == 0
for: 2m
labels:
severity: critical
annotations:
summary: "Netcheck target is down"
description: "Target {{ $labels.target }} has been down for more than 2 minutes"
- alert: NetcheckHighLatency
expr: histogram_quantile(0.95, rate(netcheck_response_time_seconds_bucket[5m])) > 1
for: 5m
labels:
severity: warning
annotations:
summary: "Netcheck high latency detected"
description: "95th percentile response time is above 1 second"
| Issue | Solution |
|---|---|
| Container exits immediately | Check command syntax in Docker Compose; ensure valid target URLs |
| No metrics visible | Verify port binding; check firewall rules; test with curl localhost:8080/metrics |
| Targets show as down | Check network connectivity; verify target URLs are accessible from container |
| High memory usage | Adjust resource limits; check for memory leaks in logs |
| Prometheus canβt scrape | Ensure both containers are on same network; verify target in prometheus.yml |
Any questions?
Feel free to contact us. Find all contact information on our contact page.