-
Notifications
You must be signed in to change notification settings - Fork 3
Docker Deployment
This guide covers deploying LogLynx using Docker and Docker Compose.
- Prerequisites
- Quick Start
- Docker Run
- Docker Compose
- Volume Mounts
- Environment Variables
- Building the Image
- Multi-Container Setup
- Traefik Integration
- Reverse Proxy
- Monitoring and Logs
- Backup and Restore
- Troubleshooting
- Production Deployment
# Update package index
sudo apt update
# Install Docker
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
# Add user to docker group
sudo usermod -aG docker $USER
# Start Docker
sudo systemctl start docker
sudo systemctl enable docker
# Verify
docker --version# Download Docker Desktop from:
# https://www.docker.com/products/docker-desktop
# Or using Homebrew
brew install --cask docker
# Start Docker Desktop
open /Applications/Docker.app
# Verify
docker --version- Download Docker Desktop from https://www.docker.com/products/docker-desktop
- Run the installer
- Start Docker Desktop
- Open PowerShell and verify:
docker --version
Docker Compose is included with Docker Desktop (macOS/Windows). For Linux:
# Download Docker Compose
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
# Make executable
sudo chmod +x /usr/local/bin/docker-compose
# Verify
docker-compose --versionThe fastest way to get LogLynx running with Docker:
# Clone repository
git clone https://github.com/K0lin/loglynx.git
cd loglynx
# Build image
docker build -t loglynx:latest .
# Create directories
mkdir -p data geoip traefik/logs
# Run container
docker run -d \
--name loglynx \
-p 8080:8080 \
-v $(pwd)/data:/data \
-v $(pwd)/geoip:/app/geoip:ro \
-v /var/log/traefik:/traefik/logs:ro \
loglynx:latest
# Access dashboard
# Open http://localhost:8080docker run -d \
--name loglynx \
-p 8080:8080 \
loglynx:latestdocker run -d \
--name loglynx \
-p 8080:8080 \
-v /path/to/data:/data \
-v /path/to/geoip:/app/geoip:ro \
-v /var/log/traefik:/traefik/logs:ro \
loglynx:latestdocker run -d \
--name loglynx \
-p 8080:8080 \
-e DB_PATH=/data/loglynx.db \
-e DB_RETENTION_DAYS=90 \
-e GEOIP_ENABLED=true \
-e TRAEFIK_LOG_PATH=/traefik/logs/access.log \
-e LOG_LEVEL=info \
-v /path/to/data:/data \
-v /path/to/geoip:/app/geoip:ro \
-v /var/log/traefik:/traefik/logs:ro \
loglynx:latest# Create env file
cat > loglynx.env <<EOF
DB_PATH=/data/loglynx.db
DB_RETENTION_DAYS=90
GEOIP_ENABLED=true
GEOIP_CITY_DB=/app/geoip/GeoLite2-City.mmdb
GEOIP_COUNTRY_DB=/app/geoip/GeoLite2-Country.mmdb
GEOIP_ASN_DB=/app/geoip/GeoLite2-ASN.mmdb
TRAEFIK_LOG_PATH=/traefik/logs/access.log
SERVER_PORT=8080
LOG_LEVEL=info
EOF
# Run with env file
docker run -d \
--name loglynx \
-p 8080:8080 \
--env-file loglynx.env \
-v /path/to/data:/data \
-v /path/to/geoip:/app/geoip:ro \
-v /var/log/traefik:/traefik/logs:ro \
loglynx:latest# View logs
docker logs -f loglynx
# Stop container
docker stop loglynx
# Start container
docker start loglynx
# Restart container
docker restart loglynx
# Remove container
docker rm -f loglynx
# View stats
docker stats loglynx
# Inspect container
docker inspect loglynx
# Execute command inside container
docker exec -it loglynx shDocker Compose simplifies multi-container deployments.
Create docker-compose.yml:
version: '3.8'
services:
loglynx:
image: K0lin/loglynx:latest
container_name: loglynx
restart: unless-stopped
ports:
- "8080:8080"
environment:
- DB_PATH=/data/loglynx.db
- DB_RETENTION_DAYS=60
- GEOIP_ENABLED=true
- GEOIP_CITY_DB=/app/geoip/GeoLite2-City.mmdb
- GEOIP_COUNTRY_DB=/app/geoip/GeoLite2-Country.mmdb
- GEOIP_ASN_DB=/app/geoip/GeoLite2-ASN.mmdb
- TRAEFIK_LOG_PATH=/traefik/logs/access.log
- SERVER_PORT=8080
- LOG_LEVEL=info
volumes:
- ./data:/data
- ./geoip:/app/geoip:ro
- /var/log/traefik:/traefik/logs:roversion: '3.8'
services:
loglynx:
build:
context: .
dockerfile: Dockerfile
container_name: loglynx
restart: unless-stopped
ports:
- "8080:8080"
env_file:
- .env
volumes:
- ./data:/data
- ./geoip:/app/geoip:ro
- /var/log/traefik:/traefik/logs:ro# Start services
docker-compose up -d
# View logs
docker-compose logs -f
# Stop services
docker-compose down
# Restart services
docker-compose restart
# Build and start
docker-compose up -d --build
# View running services
docker-compose ps
# Execute command
docker-compose exec loglynx shLogLynx uses three main volumes:
Stores the SQLite database.
volumes:
- ./data:/dataPermissions: Read/write Important: Back up this directory regularly
Contains MaxMind GeoIP databases.
volumes:
- ./geoip:/app/geoip:roPermissions: Read-only (:ro)
Files needed:
GeoLite2-City.mmdbGeoLite2-Country.mmdbGeoLite2-ASN.mmdb
Access to Traefik log files.
volumes:
- /var/log/traefik:/traefik/logs:roPermissions: Read-only (:ro)
Note: Path must match your Traefik log location
For persistent data with Docker-managed storage:
version: '3.8'
services:
loglynx:
image: K0lin/loglynx:latest
volumes:
- loglynx-data:/data
- ./geoip:/app/geoip:ro
- /var/log/traefik:/traefik/logs:ro
volumes:
loglynx-data:
driver: localCreate .env in the same directory as docker-compose.yml:
# Database
DB_PATH=/data/loglynx.db
DB_MAX_OPEN_CONNS=10
DB_MAX_IDLE_CONNS=3
DB_CONN_MAX_LIFE=1h
DB_RETENTION_DAYS=60
DB_CLEANUP_INTERVAL=1h
DB_CLEANUP_TIME=02:00
DB_VACUUM_ENABLED=true
# GeoIP
GEOIP_ENABLED=true
GEOIP_CITY_DB=/app/geoip/GeoLite2-City.mmdb
GEOIP_COUNTRY_DB=/app/geoip/GeoLite2-Country.mmdb
GEOIP_ASN_DB=/app/geoip/GeoLite2-ASN.mmdb
GEOIP_CACHE_SIZE=10000
# Log Sources
TRAEFIK_LOG_PATH=/traefik/logs/access.log
TRAEFIK_LOG_FORMAT=auto
LOG_AUTO_DISCOVER=true
INITIAL_IMPORT_DAYS=60
INITIAL_IMPORT_ENABLE=true
# Server
SERVER_HOST=0.0.0.0
SERVER_PORT=8080
SERVER_PRODUCTION=true
# Logging
LOG_LEVEL=info
# Performance
METRICS_INTERVAL=5s
BATCH_SIZE=1000
WORKER_POOL_SIZE=4version: '3.8'
services:
loglynx:
image: loglynx:latest
env_file:
- .env
volumes:
- ./data:/dataFor detailed environment variable documentation, see Environment Variables.
The project includes a multi-stage Dockerfile:
# Build image
docker build -t loglynx:latest .
# Build with custom tag
docker build -t loglynx:v1.0.0 .
# Build with no cache
docker build --no-cache -t loglynx:latest .# Build for specific Go version
docker build --build-arg GO_VERSION=1.25 -t loglynx:latest .# Enable buildx
docker buildx create --use
# Build for multiple platforms
docker buildx build \
--platform linux/amd64,linux/arm64 \
-t loglynx:latest \
--push .# List images
docker images | grep loglynx
# Inspect image
docker inspect loglynx:latest
# View image layers
docker history loglynx:latestversion: '3.8'
services:
traefik:
image: traefik:v2.10
container_name: traefik
restart: unless-stopped
ports:
- "80:80"
- "443:443"
- "8081:8080" # Traefik dashboard
command:
- "--api.dashboard=true"
- "--providers.docker=true"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--accesslog=true"
- "--accesslog.filepath=/var/log/traefik/access.log"
- "--accesslog.format=json"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- traefik-logs:/var/log/traefik
loglynx:
image: K0lin/loglynx:latest
container_name: loglynx
restart: unless-stopped
depends_on:
- traefik
environment:
- TRAEFIK_LOG_PATH=/traefik/logs/access.log
- DB_PATH=/data/loglynx.db
- GEOIP_ENABLED=true
volumes:
- ./data:/data
- ./geoip:/app/geoip:ro
- traefik-logs:/traefik/logs:ro
labels:
- "traefik.enable=true"
- "traefik.http.routers.loglynx.rule=Host(`loglynx.example.com`)"
- "traefik.http.routers.loglynx.entrypoints=websecure"
- "traefik.http.services.loglynx.loadbalancer.server.port=8080"
volumes:
traefik-logs:
driver: localversion: '3.8'
services:
traefik:
image: traefik:v2.10
ports:
- "80:80"
command:
- "--providers.docker=true"
- "--entrypoints.web.address=:80"
- "--accesslog=true"
- "--accesslog.filepath=/var/log/traefik/access.log"
- "--accesslog.format=json"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- traefik-logs:/var/log/traefik
whoami:
image: traefik/whoami
labels:
- "traefik.enable=true"
- "traefik.http.routers.whoami.rule=Host(`whoami.localhost`)"
loglynx:
image: K0lin/loglynx:latest
ports:
- "8080:8080"
volumes:
- ./data:/data
- ./geoip:/app/geoip:ro
- traefik-logs:/traefik/logs:ro
environment:
- TRAEFIK_LOG_PATH=/traefik/logs/access.log
volumes:
traefik-logs:services:
loglynx:
image: K0lin/loglynx:latest
labels:
# Enable Traefik
- "traefik.enable=true"
# HTTP router
- "traefik.http.routers.loglynx.rule=Host(`loglynx.example.com`)"
- "traefik.http.routers.loglynx.entrypoints=websecure"
- "traefik.http.routers.loglynx.tls=true"
- "traefik.http.routers.loglynx.tls.certresolver=letsencrypt"
# Service
- "traefik.http.services.loglynx.loadbalancer.server.port=8080"
# Middleware (optional)
- "traefik.http.routers.loglynx.middlewares=auth"
- "traefik.http.middlewares.auth.basicauth.users=admin:$$apr1$$..."version: '3.8'
services:
traefik:
image: traefik:v2.10
container_name: traefik
restart: unless-stopped
ports:
- "80:80"
- "443:443"
command:
- "--api.dashboard=true"
- "--providers.docker=true"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--certificatesresolvers.letsencrypt.acme.email=you@example.com"
- "--certificatesresolvers.letsencrypt.acme.storage=/acme.json"
- "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web"
- "--accesslog=true"
- "--accesslog.filepath=/var/log/traefik/access.log"
- "--accesslog.format=json"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./acme.json:/acme.json
- traefik-logs:/var/log/traefik
loglynx:
image: K0lin/loglynx:latest
container_name: loglynx
restart: unless-stopped
environment:
- TRAEFIK_LOG_PATH=/traefik/logs/access.log
- DB_PATH=/data/loglynx.db
volumes:
- ./data:/data
- ./geoip:/app/geoip:ro
- traefik-logs:/traefik/logs:ro
labels:
- "traefik.enable=true"
- "traefik.http.routers.loglynx.rule=Host(`loglynx.example.com`)"
- "traefik.http.routers.loglynx.entrypoints=websecure"
- "traefik.http.routers.loglynx.tls=true"
- "traefik.http.routers.loglynx.tls.certresolver=letsencrypt"
- "traefik.http.services.loglynx.loadbalancer.server.port=8080"
volumes:
traefik-logs:server {
listen 80;
server_name loglynx.example.com;
location / {
proxy_pass http://localhost:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
# For SSE streaming
proxy_buffering off;
proxy_read_timeout 86400;
}
}loglynx.example.com {
reverse_proxy localhost:8080
}# Follow logs
docker logs -f loglynx
# Last 100 lines
docker logs --tail 100 loglynx
# Since timestamp
docker logs --since 2025-11-04T10:00:00 loglynx
# With timestamps
docker logs -t loglynx# All services
docker-compose logs -f
# Specific service
docker-compose logs -f loglynx
# Last 50 lines
docker-compose logs --tail 50# Real-time stats
docker stats loglynx
# All containers
docker stats
# Format output
docker stats --format "table {{.Container}}\t{{.CPUPerc}}\t{{.MemUsage}}"Add health check to Compose:
services:
loglynx:
image: K0lin/loglynx:latest
healthcheck:
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:8080/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s# Stop container
docker-compose down
# Backup data directory
tar -czf loglynx-backup-$(date +%Y%m%d).tar.gz data/
# Or use docker cp
docker cp loglynx:/data/loglynx.db ./loglynx-backup.db
# Restart container
docker-compose up -d# Stop container
docker-compose down
# Restore data directory
tar -xzf loglynx-backup-20251104.tar.gz
# Or use docker cp
docker cp ./loglynx-backup.db loglynx:/data/loglynx.db
# Restart container
docker-compose up -dCreate backup script:
#!/bin/bash
# backup-loglynx.sh
BACKUP_DIR="/backups/loglynx"
DATE=$(date +%Y%m%d-%H%M%S)
# Create backup directory
mkdir -p $BACKUP_DIR
# Stop container (optional)
# docker-compose stop loglynx
# Backup database
docker cp loglynx:/data/loglynx.db $BACKUP_DIR/loglynx-$DATE.db
# Restart container (if stopped)
# docker-compose start loglynx
# Keep only last 7 days
find $BACKUP_DIR -name "loglynx-*.db" -mtime +7 -delete
echo "Backup completed: $BACKUP_DIR/loglynx-$DATE.db"Schedule with cron:
# Edit crontab
crontab -e
# Add daily backup at 3 AM
0 3 * * * /path/to/backup-loglynx.sh# Check logs
docker logs loglynx
# Inspect container
docker inspect loglynx
# Check port conflicts
sudo lsof -i :8080
# Verify volumes exist
ls -la data/ geoip/# Fix data directory permissions
sudo chown -R 1000:1000 data/
# Or use current user
sudo chown -R $(id -u):$(id -g) data/# Check for multiple containers
docker ps -a | grep loglynx
# Remove duplicate containers
docker rm -f loglynx
# Reduce connection pool
# In .env:
DB_MAX_OPEN_CONNS=5# Verify log path
docker exec loglynx ls -lh /traefik/logs/
# Check permissions
docker exec loglynx cat /traefik/logs/access.log
# Verify mount
docker inspect loglynx | grep Mounts -A 20# Check stats
docker stats loglynx
# Limit memory
docker run -d \
--name loglynx \
--memory="1g" \
--memory-swap="2g" \
loglynx:latest
# Or in Compose:
services:
loglynx:
image: K0lin/loglynx:latest
deploy:
resources:
limits:
memory: 1G
reservations:
memory: 512Mversion: '3.8'
services:
loglynx:
image: K0lin/loglynx:latest
container_name: loglynx
restart: always
environment:
- DB_PATH=/data/loglynx.db
- DB_MAX_OPEN_CONNS=50
- DB_MAX_IDLE_CONNS=20
- DB_RETENTION_DAYS=90
- DB_CLEANUP_TIME=03:00
- DB_VACUUM_ENABLED=true
- GEOIP_ENABLED=true
- GEOIP_CITY_DB=/app/geoip/GeoLite2-City.mmdb
- GEOIP_COUNTRY_DB=/app/geoip/GeoLite2-Country.mmdb
- GEOIP_ASN_DB=/app/geoip/GeoLite2-ASN.mmdb
- TRAEFIK_LOG_PATH=/traefik/logs/access.log
- TRAEFIK_LOG_FORMAT=json
- SERVER_HOST=0.0.0.0
- SERVER_PORT=8080
- SERVER_PRODUCTION=true
- LOG_LEVEL=info
- METRICS_INTERVAL=5s
- BATCH_SIZE=2000
- WORKER_POOL_SIZE=8
volumes:
- /opt/loglynx/data:/data
- /opt/loglynx/geoip:/app/geoip:ro
- /var/log/traefik:/traefik/logs:ro
deploy:
resources:
limits:
cpus: '4'
memory: 4G
reservations:
cpus: '2'
memory: 2G
healthcheck:
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:8080/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
labels:
- "traefik.enable=true"
- "traefik.http.routers.loglynx.rule=Host(`loglynx.example.com`)"
- "traefik.http.routers.loglynx.entrypoints=websecure"
- "traefik.http.routers.loglynx.tls=true"
- "traefik.http.routers.loglynx.tls.certresolver=letsencrypt"
- "traefik.http.services.loglynx.loadbalancer.server.port=8080"- Use read-only volumes where possible
- Limit container resources
- Enable health checks
- Use secrets for sensitive data
- Run as non-root user (already configured in Dockerfile)
- Enable TLS/SSL
- Implement authentication (via reverse proxy)
Set up monitoring with Prometheus and Grafana:
version: '3.8'
services:
loglynx:
image: K0lin/loglynx:latest
# ... configuration ...
prometheus:
image: prom/prometheus
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus-data:/prometheus
ports:
- "9090:9090"
grafana:
image: grafana/grafana
ports:
- "3000:3000"
volumes:
- grafana-data:/var/lib/grafana
volumes:
prometheus-data:
grafana-data:- Configure Environment Variables
- Explore the API Documentation
- Set up SSL/TLS certificates
- Configure authentication
- Set up automated backups
- Monitor performance and logs
Last Updated: November 2025
- Home - Introduction and overview
- API Documentation - Complete API reference
- Environment Variables - Configuration guide
- Standalone Deployment - Native installation
- Docker Deployment - Container deployment