Add Docker support with multi-arch builds
- Multi-stage Dockerfile (Alpine base, ~174MB) - All runtime dependencies: ffmpeg, ffprobe, ca-certificates, tzdata, wget - Camera database included in image (17MB) - Security: non-root user (strix:1000) - Healthcheck on /api/v1/health - docker-compose.yml for simple deployment - docker-compose.full.yml with go2rtc and Frigate integration - GitHub Actions workflow for automated multi-arch builds (amd64, arm64) - Auto-publish to Docker Hub (eduard256/strix) - DOCKER.md documentation
This commit is contained in:
@@ -0,0 +1,52 @@
|
|||||||
|
# Git
|
||||||
|
.git
|
||||||
|
.gitignore
|
||||||
|
.github
|
||||||
|
|
||||||
|
# IDE
|
||||||
|
.vscode
|
||||||
|
.idea
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
*~
|
||||||
|
|
||||||
|
# Build artifacts
|
||||||
|
bin/
|
||||||
|
dist/
|
||||||
|
*.exe
|
||||||
|
*.dll
|
||||||
|
*.so
|
||||||
|
*.dylib
|
||||||
|
|
||||||
|
# Test files
|
||||||
|
*.test
|
||||||
|
*_test.go
|
||||||
|
coverage.*
|
||||||
|
*.out
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
*.log
|
||||||
|
strix.log
|
||||||
|
|
||||||
|
# Config files (user-specific)
|
||||||
|
strix.yaml
|
||||||
|
test_*.yaml
|
||||||
|
config.yaml
|
||||||
|
|
||||||
|
# Temporary files
|
||||||
|
tmp/
|
||||||
|
temp/
|
||||||
|
*.dump
|
||||||
|
*_output.txt
|
||||||
|
|
||||||
|
# Documentation (included in image metadata instead)
|
||||||
|
*.md
|
||||||
|
!README.md
|
||||||
|
|
||||||
|
# OS files
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
|
# Development
|
||||||
|
.env
|
||||||
|
.env.local
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
name: Docker Build and Push
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
tags:
|
||||||
|
- 'v*'
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
|
||||||
|
env:
|
||||||
|
REGISTRY: docker.io
|
||||||
|
IMAGE_NAME: eduard256/strix
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-and-push:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
packages: write
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v3
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
|
- name: Log in to Docker Hub
|
||||||
|
if: github.event_name != 'pull_request'
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKER_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKER_TOKEN }}
|
||||||
|
|
||||||
|
- name: Extract metadata
|
||||||
|
id: meta
|
||||||
|
uses: docker/metadata-action@v5
|
||||||
|
with:
|
||||||
|
images: ${{ env.IMAGE_NAME }}
|
||||||
|
tags: |
|
||||||
|
type=ref,event=branch
|
||||||
|
type=ref,event=pr
|
||||||
|
type=semver,pattern={{version}}
|
||||||
|
type=semver,pattern={{major}}.{{minor}}
|
||||||
|
type=semver,pattern={{major}}
|
||||||
|
type=raw,value=latest,enable={{is_default_branch}}
|
||||||
|
|
||||||
|
- name: Build and push
|
||||||
|
uses: docker/build-push-action@v5
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
push: ${{ github.event_name != 'pull_request' }}
|
||||||
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
|
cache-from: type=gha
|
||||||
|
cache-to: type=gha,mode=max
|
||||||
|
build-args: |
|
||||||
|
VERSION=${{ steps.meta.outputs.version }}
|
||||||
|
|
||||||
|
- name: Docker Hub Description
|
||||||
|
if: github.event_name != 'pull_request'
|
||||||
|
uses: peter-evans/dockerhub-description@v4
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKER_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKER_TOKEN }}
|
||||||
|
repository: ${{ env.IMAGE_NAME }}
|
||||||
|
readme-filepath: ./README.md
|
||||||
|
short-description: "Smart IP Camera Stream Discovery System"
|
||||||
@@ -0,0 +1,164 @@
|
|||||||
|
# 🐳 Docker Setup for Strix
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
### Using Docker Compose (Recommended)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Start Strix
|
||||||
|
docker-compose up -d
|
||||||
|
|
||||||
|
# View logs
|
||||||
|
docker-compose logs -f strix
|
||||||
|
|
||||||
|
# Stop Strix
|
||||||
|
docker-compose down
|
||||||
|
```
|
||||||
|
|
||||||
|
Access: http://localhost:4567
|
||||||
|
|
||||||
|
### Using Docker Run
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker run -d \
|
||||||
|
--name strix \
|
||||||
|
-p 4567:4567 \
|
||||||
|
eduard256/strix:latest
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
### Using Environment Variables
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker run -d \
|
||||||
|
--name strix \
|
||||||
|
-p 8080:8080 \
|
||||||
|
-e STRIX_API_LISTEN=:8080 \
|
||||||
|
-e STRIX_LOG_LEVEL=debug \
|
||||||
|
eduard256/strix:latest
|
||||||
|
```
|
||||||
|
|
||||||
|
### Using Config File
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Create strix.yaml
|
||||||
|
cat > strix.yaml <<EOF
|
||||||
|
api:
|
||||||
|
listen: ":8080"
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Run with mounted config
|
||||||
|
docker run -d \
|
||||||
|
--name strix \
|
||||||
|
-p 8080:8080 \
|
||||||
|
-v $(pwd)/strix.yaml:/app/strix.yaml:ro \
|
||||||
|
eduard256/strix:latest
|
||||||
|
```
|
||||||
|
|
||||||
|
## Full Stack (Strix + go2rtc + Frigate)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker-compose -f docker-compose.full.yml up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
Services:
|
||||||
|
- Strix: http://localhost:4567
|
||||||
|
- go2rtc: http://localhost:1984
|
||||||
|
- Frigate: http://localhost:5000
|
||||||
|
|
||||||
|
## Building Locally
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Build for your platform
|
||||||
|
docker build -t strix:local .
|
||||||
|
|
||||||
|
# Build for multiple platforms
|
||||||
|
docker buildx build --platform linux/amd64,linux/arm64 -t strix:multi .
|
||||||
|
```
|
||||||
|
|
||||||
|
## Image Information
|
||||||
|
|
||||||
|
- **Image**: `eduard256/strix:latest`
|
||||||
|
- **Platforms**: linux/amd64, linux/arm64
|
||||||
|
- **Size**: ~80-90MB
|
||||||
|
- **Base**: Alpine Linux
|
||||||
|
- **User**: Non-root (strix:1000)
|
||||||
|
|
||||||
|
## Included Dependencies
|
||||||
|
|
||||||
|
- ffmpeg/ffprobe (stream validation)
|
||||||
|
- ca-certificates (HTTPS support)
|
||||||
|
- tzdata (timezone support)
|
||||||
|
- wget (healthcheck)
|
||||||
|
- Camera database (3600+ models)
|
||||||
|
|
||||||
|
## Health Check
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check container health
|
||||||
|
docker inspect --format='{{.State.Health.Status}}' strix
|
||||||
|
|
||||||
|
# Manual health check
|
||||||
|
docker exec strix wget -q -O- http://localhost:4567/api/v1/health
|
||||||
|
```
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### View logs
|
||||||
|
```bash
|
||||||
|
docker logs strix
|
||||||
|
docker logs -f strix # Follow logs
|
||||||
|
```
|
||||||
|
|
||||||
|
### Check if ffprobe works
|
||||||
|
```bash
|
||||||
|
docker exec strix ffprobe -version
|
||||||
|
```
|
||||||
|
|
||||||
|
### Inspect container
|
||||||
|
```bash
|
||||||
|
docker exec -it strix sh
|
||||||
|
```
|
||||||
|
|
||||||
|
### Restart container
|
||||||
|
```bash
|
||||||
|
docker restart strix
|
||||||
|
```
|
||||||
|
|
||||||
|
## Security
|
||||||
|
|
||||||
|
- Runs as non-root user (UID 1000)
|
||||||
|
- Minimal attack surface (Alpine base)
|
||||||
|
- No unnecessary packages
|
||||||
|
- Health checks enabled
|
||||||
|
|
||||||
|
## Environment Variables
|
||||||
|
|
||||||
|
| Variable | Default | Description |
|
||||||
|
|----------|---------|-------------|
|
||||||
|
| `STRIX_API_LISTEN` | `:4567` | Server listen address |
|
||||||
|
| `STRIX_LOG_LEVEL` | `info` | Log level (debug, info, warn, error) |
|
||||||
|
| `STRIX_LOG_FORMAT` | `json` | Log format (json, text) |
|
||||||
|
| `STRIX_DATA_PATH` | `./data` | Camera database path |
|
||||||
|
|
||||||
|
## Volumes
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Optional: Custom configuration
|
||||||
|
-v ./strix.yaml:/app/strix.yaml:ro
|
||||||
|
|
||||||
|
# Optional: Custom camera database
|
||||||
|
-v ./data:/app/data:ro
|
||||||
|
```
|
||||||
|
|
||||||
|
## Docker Hub
|
||||||
|
|
||||||
|
Pre-built images available at: https://hub.docker.com/r/eduard256/strix
|
||||||
|
|
||||||
|
Tags:
|
||||||
|
- `latest` - Latest stable release
|
||||||
|
- `v0.1.0` - Specific version
|
||||||
|
- `0.1` - Minor version
|
||||||
|
- `0` - Major version
|
||||||
|
- `main` - Development branch
|
||||||
+67
@@ -0,0 +1,67 @@
|
|||||||
|
# Strix - Smart IP Camera Stream Discovery System
|
||||||
|
# Multi-stage Dockerfile for minimal image size
|
||||||
|
|
||||||
|
# Stage 1: Builder
|
||||||
|
FROM golang:1.24-alpine AS builder
|
||||||
|
|
||||||
|
WORKDIR /build
|
||||||
|
|
||||||
|
# Install build dependencies
|
||||||
|
RUN apk add --no-cache git
|
||||||
|
|
||||||
|
# Copy go mod files
|
||||||
|
COPY go.mod go.sum ./
|
||||||
|
RUN go mod download
|
||||||
|
|
||||||
|
# Copy source code
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# Build static binary
|
||||||
|
RUN CGO_ENABLED=0 GOOS=linux GOARCH=${TARGETARCH} go build \
|
||||||
|
-ldflags="-s -w -X main.Version=docker" \
|
||||||
|
-o strix \
|
||||||
|
cmd/strix/main.go
|
||||||
|
|
||||||
|
# Stage 2: Runtime
|
||||||
|
FROM alpine:latest
|
||||||
|
|
||||||
|
# Install runtime dependencies
|
||||||
|
# - ffmpeg/ffprobe: Required for RTSP stream validation
|
||||||
|
# - ca-certificates: Required for HTTPS requests to cameras
|
||||||
|
# - tzdata: Required for correct timestamps
|
||||||
|
# - wget: Required for healthcheck
|
||||||
|
RUN apk add --no-cache \
|
||||||
|
ffmpeg \
|
||||||
|
ca-certificates \
|
||||||
|
tzdata \
|
||||||
|
wget \
|
||||||
|
&& rm -rf /var/cache/apk/*
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Copy binary from builder
|
||||||
|
COPY --from=builder /build/strix .
|
||||||
|
|
||||||
|
# Copy camera database (CRITICAL - app won't work without it)
|
||||||
|
COPY --from=builder /build/data ./data
|
||||||
|
|
||||||
|
# Create directory for optional config
|
||||||
|
RUN mkdir -p /app/config
|
||||||
|
|
||||||
|
# Create non-root user for security
|
||||||
|
RUN addgroup -g 1000 strix && \
|
||||||
|
adduser -D -u 1000 -G strix strix && \
|
||||||
|
chown -R strix:strix /app
|
||||||
|
|
||||||
|
# Switch to non-root user
|
||||||
|
USER strix
|
||||||
|
|
||||||
|
# Expose default port
|
||||||
|
EXPOSE 4567
|
||||||
|
|
||||||
|
# Health check
|
||||||
|
HEALTHCHECK --interval=30s --timeout=10s --start-period=10s --retries=3 \
|
||||||
|
CMD wget --no-verbose --tries=1 --spider http://localhost:4567/api/v1/health || exit 1
|
||||||
|
|
||||||
|
# Start application
|
||||||
|
CMD ["./strix"]
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
version: '3.8'
|
||||||
|
|
||||||
|
# Full home automation stack: Strix + go2rtc + Frigate
|
||||||
|
# This configuration shows how to use Strix together with go2rtc and Frigate
|
||||||
|
|
||||||
|
services:
|
||||||
|
# Strix - Camera Stream Discovery
|
||||||
|
strix:
|
||||||
|
image: eduard256/strix:latest
|
||||||
|
container_name: strix
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "4567:4567"
|
||||||
|
environment:
|
||||||
|
- STRIX_LOG_LEVEL=info
|
||||||
|
- STRIX_LOG_FORMAT=json
|
||||||
|
networks:
|
||||||
|
- cameras
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:4567/api/v1/health"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 3
|
||||||
|
start_period: 10s
|
||||||
|
|
||||||
|
# go2rtc - Universal Stream Server
|
||||||
|
go2rtc:
|
||||||
|
image: alexxit/go2rtc:latest
|
||||||
|
container_name: go2rtc
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "1984:1984" # Web UI
|
||||||
|
- "8554:8554" # RTSP
|
||||||
|
- "8555:8555" # WebRTC
|
||||||
|
volumes:
|
||||||
|
- ./go2rtc.yaml:/config/go2rtc.yaml:ro
|
||||||
|
networks:
|
||||||
|
- cameras
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:1984"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 3
|
||||||
|
|
||||||
|
# Frigate - NVR with Object Detection
|
||||||
|
frigate:
|
||||||
|
image: ghcr.io/blakeblackshear/frigate:stable
|
||||||
|
container_name: frigate
|
||||||
|
restart: unless-stopped
|
||||||
|
privileged: true
|
||||||
|
shm_size: "256mb"
|
||||||
|
ports:
|
||||||
|
- "5000:5000" # Web UI
|
||||||
|
- "8971:8971" # Go2RTC internal
|
||||||
|
- "1935:1935" # RTMP
|
||||||
|
volumes:
|
||||||
|
- ./frigate.yml:/config/config.yml:ro
|
||||||
|
- frigate-media:/media/frigate
|
||||||
|
- /etc/localtime:/etc/localtime:ro
|
||||||
|
environment:
|
||||||
|
- FRIGATE_RTSP_PASSWORD=password
|
||||||
|
networks:
|
||||||
|
- cameras
|
||||||
|
depends_on:
|
||||||
|
- go2rtc
|
||||||
|
|
||||||
|
networks:
|
||||||
|
cameras:
|
||||||
|
driver: bridge
|
||||||
|
ipam:
|
||||||
|
config:
|
||||||
|
- subnet: 172.25.0.0/24
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
frigate-media:
|
||||||
|
driver: local
|
||||||
|
|
||||||
|
# Usage workflow:
|
||||||
|
# 1. Use Strix to discover camera streams: http://localhost:4567
|
||||||
|
# 2. Copy discovered stream URLs to go2rtc.yaml
|
||||||
|
# 3. Configure go2rtc streams: http://localhost:1984
|
||||||
|
# 4. Add streams to Frigate config: frigate.yml
|
||||||
|
# 5. View recordings and detections: http://localhost:5000
|
||||||
|
#
|
||||||
|
# Network communication:
|
||||||
|
# - Strix discovers streams from cameras (external network)
|
||||||
|
# - go2rtc receives streams from cameras and re-streams
|
||||||
|
# - Frigate receives streams from go2rtc (internal network)
|
||||||
|
#
|
||||||
|
# All services can communicate using container names:
|
||||||
|
# - http://strix:4567
|
||||||
|
# - http://go2rtc:1984
|
||||||
|
# - http://frigate:5000
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
version: '3'
|
||||||
|
|
||||||
|
services:
|
||||||
|
strix:
|
||||||
|
image: eduard256/strix:latest
|
||||||
|
# Or build locally:
|
||||||
|
# build: .
|
||||||
|
container_name: strix
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
ports:
|
||||||
|
- "4567:4567"
|
||||||
|
|
||||||
|
environment:
|
||||||
|
# Logging configuration
|
||||||
|
- STRIX_LOG_LEVEL=info
|
||||||
|
- STRIX_LOG_FORMAT=json
|
||||||
|
|
||||||
|
# Optional: Override default port
|
||||||
|
# - STRIX_API_LISTEN=:4567
|
||||||
|
|
||||||
|
# Optional: Custom data path
|
||||||
|
# - STRIX_DATA_PATH=/app/data
|
||||||
|
|
||||||
|
# volumes:
|
||||||
|
# Optional: Mount custom configuration
|
||||||
|
# - ./strix.yaml:/app/strix.yaml:ro
|
||||||
|
|
||||||
|
# Optional: Mount custom camera database
|
||||||
|
# - ./data:/app/data:ro
|
||||||
|
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:4567/api/v1/health"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 3
|
||||||
|
start_period: 10s
|
||||||
|
|
||||||
|
# Optional: Resource limits
|
||||||
|
# deploy:
|
||||||
|
# resources:
|
||||||
|
# limits:
|
||||||
|
# cpus: '1.0'
|
||||||
|
# memory: 512M
|
||||||
|
# reservations:
|
||||||
|
# cpus: '0.5'
|
||||||
|
# memory: 256M
|
||||||
|
|
||||||
|
# Usage:
|
||||||
|
# 1. Start: docker-compose up -d
|
||||||
|
# 2. View logs: docker-compose logs -f strix
|
||||||
|
# 3. Stop: docker-compose down
|
||||||
|
# 4. Restart: docker-compose restart strix
|
||||||
|
#
|
||||||
|
# Access WebUI: http://localhost:4567
|
||||||
|
# Access API: http://localhost:4567/api/v1/health
|
||||||
Reference in New Issue
Block a user