Skip to content

Commit 51a73c4

Browse files
Merge pull request #1 from rishabhverma17/development-docker
feat: Complete Docker implementation with comprehensive documentation
2 parents 08e7345 + eb9157b commit 51a73c4

25 files changed

Lines changed: 5179 additions & 20 deletions

.dockerignore

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# Build artifacts
2+
bin/
3+
*.exe
4+
*.exe~
5+
*.dll
6+
*.so
7+
*.dylib
8+
hypercache
9+
main
10+
11+
# Test binary, built with `go test -c`
12+
*.test
13+
14+
# Output of the go coverage tool
15+
*.out
16+
17+
# Go workspace file
18+
go.work
19+
20+
# IDE
21+
.vscode/
22+
.idea/
23+
*.swp
24+
*.swo
25+
*~
26+
27+
# OS
28+
.DS_Store
29+
.DS_Store?
30+
._*
31+
.Spotlight-V100
32+
.Trashes
33+
ehthumbs.db
34+
Thumbs.db
35+
36+
# Logs and data
37+
logs/
38+
data/
39+
*.log
40+
41+
# Docker
42+
.dockerignore
43+
Dockerfile.*
44+
docker-compose*.yml
45+
46+
# Git
47+
.git/
48+
.gitignore
49+
50+
# Documentation
51+
docs/
52+
README.md
53+
*.md
54+
55+
# Scripts (except what we need in container)
56+
scripts/
57+
test-results/
58+
benchmark-results/
59+
60+
# Monitoring and config files we don't need in container
61+
grafana/
62+
filebeat*.yml
63+
docker-compose*.yml
64+
65+
# Examples and tests
66+
examples/
67+
tests/

.github/workflows/docker-build.yml

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
name: Build and Push to Docker Hub
2+
3+
on:
4+
push:
5+
branches: [ main, develop ]
6+
tags: [ 'v*' ]
7+
pull_request:
8+
branches: [ main ]
9+
10+
env:
11+
IMAGE_NAME: hypercache
12+
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
13+
14+
jobs:
15+
test:
16+
runs-on: ubuntu-latest
17+
steps:
18+
- uses: actions/checkout@v4
19+
20+
- name: Set up Go
21+
uses: actions/setup-go@v4
22+
with:
23+
go-version: '1.23.2'
24+
25+
- name: Cache Go modules
26+
uses: actions/cache@v3
27+
with:
28+
path: |
29+
~/.cache/go-build
30+
~/go/pkg/mod
31+
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
32+
restore-keys: |
33+
${{ runner.os }}-go-
34+
35+
- name: Run tests
36+
run: go test -v ./...
37+
38+
- name: Run build test
39+
run: go build -o /tmp/hypercache cmd/hypercache/main.go
40+
41+
build-and-push:
42+
needs: test
43+
runs-on: ubuntu-latest
44+
if: github.event_name != 'pull_request'
45+
46+
steps:
47+
- name: Checkout
48+
uses: actions/checkout@v4
49+
with:
50+
fetch-depth: 0
51+
52+
- name: Set up Docker Buildx
53+
uses: docker/setup-buildx-action@v3
54+
55+
- name: Log in to Docker Hub
56+
uses: docker/login-action@v3
57+
with:
58+
username: ${{ secrets.DOCKER_USERNAME }}
59+
password: ${{ secrets.DOCKER_PASSWORD }}
60+
61+
- name: Extract metadata
62+
id: meta
63+
uses: docker/metadata-action@v5
64+
with:
65+
images: ${{ env.DOCKER_USERNAME }}/${{ env.IMAGE_NAME }}
66+
tags: |
67+
type=ref,event=branch
68+
type=ref,event=pr
69+
type=semver,pattern={{version}}
70+
type=semver,pattern={{major}}.{{minor}}
71+
type=semver,pattern={{major}}
72+
type=sha,prefix={{branch}}-
73+
type=raw,value=latest,enable={{is_default_branch}}
74+
75+
- name: Build and push Docker image
76+
uses: docker/build-push-action@v5
77+
with:
78+
context: .
79+
platforms: linux/amd64,linux/arm64
80+
push: true
81+
tags: ${{ steps.meta.outputs.tags }}
82+
labels: ${{ steps.meta.outputs.labels }}
83+
build-args: |
84+
BUILD_DATE=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.created'] }}
85+
VCS_REF=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.revision'] }}
86+
VERSION=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.version'] }}
87+
cache-from: type=gha
88+
cache-to: type=gha,mode=max
89+
90+
- name: Update Docker Hub description
91+
uses: peter-evans/dockerhub-description@v3
92+
with:
93+
username: ${{ secrets.DOCKER_USERNAME }}
94+
password: ${{ secrets.DOCKER_PASSWORD }}
95+
repository: ${{ env.DOCKER_USERNAME }}/${{ env.IMAGE_NAME }}
96+
short-description: "High-performance Redis-compatible distributed cache with Cuckoo filters"
97+
readme-filepath: ./README.md
98+
99+
security-scan:
100+
needs: build-and-push
101+
runs-on: ubuntu-latest
102+
if: github.event_name != 'pull_request'
103+
104+
steps:
105+
- name: Run Trivy vulnerability scanner
106+
uses: aquasecurity/trivy-action@master
107+
with:
108+
image-ref: ${{ env.DOCKER_USERNAME }}/${{ env.IMAGE_NAME }}:latest
109+
format: 'sarif'
110+
output: 'trivy-results.sarif'
111+
112+
- name: Upload Trivy scan results to GitHub Security tab
113+
uses: github/codeql-action/upload-sarif@v2
114+
if: always()
115+
with:
116+
sarif_file: 'trivy-results.sarif'

Dockerfile

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# Multi-stage build for HyperCache
2+
# Stage 1: Build stage
3+
FROM golang:1.23.2-alpine AS builder
4+
5+
# Install necessary packages
6+
RUN apk add --no-cache git ca-certificates tzdata
7+
8+
# Set working directory
9+
WORKDIR /app
10+
11+
# Copy go mod files first (for better caching)
12+
COPY go.mod go.sum ./
13+
RUN go mod download
14+
15+
# Copy source code
16+
COPY . .
17+
18+
# Build the binary with optimizations
19+
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build \
20+
-ldflags='-w -s -extldflags "-static"' \
21+
-a -installsuffix cgo \
22+
-o hypercache \
23+
cmd/hypercache/main.go
24+
25+
# Stage 2: Final minimal image
26+
FROM alpine:3.18
27+
28+
# Install necessary runtime packages
29+
RUN apk add --no-cache ca-certificates tzdata wget net-tools
30+
31+
# Create non-root user and necessary directories
32+
RUN addgroup -g 1000 hypercache && \
33+
adduser -D -u 1000 -G hypercache hypercache && \
34+
mkdir -p /data /app/logs /config && \
35+
chown -R hypercache:hypercache /data /app /config && \
36+
chmod 755 /data /app /config /app/logs
37+
38+
# Copy the binary
39+
COPY --from=builder /app/hypercache /hypercache
40+
RUN chmod +x /hypercache
41+
42+
# Set working directory
43+
WORKDIR /app
44+
45+
# Switch to non-root user
46+
USER hypercache
47+
48+
# Expose ports
49+
# RESP Protocol
50+
EXPOSE 8080
51+
# HTTP API
52+
EXPOSE 9080
53+
# Gossip Protocol
54+
EXPOSE 7946
55+
56+
# Health check using the proper health endpoint
57+
HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \
58+
CMD wget --no-verbose --tries=1 --spider http://localhost:9080/health || exit 1
59+
60+
# Default command
61+
ENTRYPOINT ["/hypercache"]
62+
CMD ["--config", "/config/hypercache.yaml", "--protocol", "resp"]

README.md

Lines changed: 46 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -27,23 +27,48 @@
2727

2828
## 🚀 **Quick Start**
2929

30-
### Start Complete System (Recommended)
30+
### 🐳 Docker Deployment (Recommended)
31+
```bash
32+
# Build and start containerized cluster with monitoring
33+
./scripts/docker-deploy.sh deploy
34+
35+
# Or pull from Docker Hub and start
36+
docker-compose -f docker-compose.cluster.yml up -d
37+
38+
# Test the cluster
39+
./scripts/docker-deploy.sh test
40+
```
41+
42+
### 🔧 Local Development
3143
```bash
3244
# Start both cluster and monitoring stack
3345
./scripts/start-system.sh
3446

3547
# Or start with clean data
3648
./scripts/start-system.sh --clean
37-
38-
# Access points:
39-
# - Cluster nodes: http://localhost:9080, 9081, 9082
40-
# - Grafana: http://localhost:3000 (admin/admin123)
41-
# - Elasticsearch: http://localhost:9200
4249
```
4350

44-
### Start Individual Components
51+
### 📊 Access Points
52+
- **HyperCache Nodes**: http://localhost:9080, 9081, 9082
53+
- **Grafana Dashboards**: http://localhost:3000 (admin/admin123)
54+
- **Elasticsearch**: http://localhost:9200
55+
- **Docker Hub**: `docker pull hypercache/hypercache:latest`
56+
57+
## 🔥 **Deployment Options**
4558

46-
#### HyperCache Cluster Only
59+
### 🐳 **Docker (Production-Ready)**
60+
```bash
61+
# Pull from Docker Hub
62+
docker pull hypercache/hypercache:latest
63+
64+
# Start 3-node cluster with monitoring
65+
docker-compose -f docker-compose.cluster.yml up -d
66+
67+
# Kubernetes deployment
68+
kubectl apply -f k8s/hypercache-cluster.yaml
69+
```
70+
71+
### 🔧 **Local Development**
4772
```bash
4873
# Build and start 3-node cluster
4974
./scripts/build-and-run.sh cluster
@@ -52,7 +77,7 @@
5277
./scripts/build-and-run.sh run node-1
5378
```
5479

55-
#### Monitoring Stack Only
80+
### 📊 **Monitoring Stack Only**
5681
```bash
5782
# Start Elasticsearch, Grafana, and Filebeat
5883
docker-compose -f docker-compose.logging.yml up -d
@@ -100,6 +125,14 @@ curl http://localhost:9080/health
100125
- **Snapshot Support**: Point-in-time recovery with configurable intervals
101126
- **Durability Guarantees**: Configurable sync policies (fsync, async, periodic)
102127

128+
### **Containerized Deployment**
129+
- **Docker Hub Integration**: Pre-built multi-arch images (amd64, arm64)
130+
- **Docker Compose Support**: One-command cluster deployment with monitoring
131+
- **Kubernetes Ready**: StatefulSet manifests with service discovery
132+
- **Minimal Attack Surface**: Scratch-based images, non-root user
133+
- **Auto-scaling**: Dynamic cluster membership and load balancing
134+
- **CI/CD Pipeline**: Automated builds and security scanning
135+
103136
### **Advanced Memory Management**
104137
- **Per-Store Eviction Policies**: Independent LRU, LFU, or session-based eviction per store
105138
- **Smart Memory Pool**: Pressure monitoring with automatic cleanup
@@ -166,15 +199,15 @@ HyperCache/
166199
┌─────────────────────────────────────────────────┼─────────────────────────────────────────────────┐
167200
│ │ │
168201
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
169-
│ Memory Pool │ │ Data Storage │ │ Cuckoo Filter │ │ Hash Ring │ │ Gossip Node │
170-
│ (Pressure │ │ + Persistence │ │ (Probabilistic │ │ (Consistent │ │ Discovery │
171-
│ Monitoring) │ │ (AOF+Snapshot) │ │ Operations) │ │ Hashing) │ │ & Failover │
202+
│ Memory Pool │ │ Data Storage │ │ Cuckoo Filter │ │ Hash Ring │ │ Gossip Node
203+
│ (Pressure │ │ + Persistence │ │ (Probabilistic │ │ (Consistent │ │ Discovery
204+
│ Monitoring) │ │ (AOF+Snapshot) │ │ Operations) │ │ Hashing) │ │ & Failover
172205
└─────────────────┘ └──────────────────┘ └─────────────────┘ └──────────────────┘ └─────────────────┘
173206
│ │ │ │ │
174207
└─────────────────────────┼─────────────────────────┼─────────────────────────┼─────────────────────────┘
175208
│ │ │
176209
┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
177-
│ MONITORING STACK
210+
│ MONITORING STACK │
178211
├─────────────────┬──────────────────┬─────────────────┬──────────────────┬─────────────────┬─────────────────┤
179212
│ Filebeat │ Elasticsearch │ Grafana │ Health API │ Metrics │ Alerting │
180213
│ (Log Shipper) │ (Log Storage) │ (Dashboards) │ (Diagnostics) │ (Performance) │ (Monitoring) │

cmd/hypercache/main.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,35 @@ func startHTTPServer(ctx context.Context, coordinator cluster.CoordinatorService
332332
json.NewEncoder(w).Encode(response)
333333
})
334334

335+
// Cluster members endpoint
336+
mux.HandleFunc("/api/cluster/members", func(w http.ResponseWriter, r *http.Request) {
337+
// Extract correlation ID from context
338+
correlationID := logging.GetCorrelationID(r.Context())
339+
if correlationID == "" {
340+
correlationID = logging.NewCorrelationID()
341+
r = r.WithContext(logging.WithCorrelationID(r.Context(), correlationID))
342+
}
343+
344+
logging.Info(r.Context(), logging.ComponentHTTP, "cluster_members", "Cluster members requested")
345+
346+
membership := coordinator.GetMembership()
347+
if membership == nil {
348+
http.Error(w, "Cluster membership not available", http.StatusServiceUnavailable)
349+
return
350+
}
351+
352+
members := membership.GetMembers()
353+
response := map[string]interface{}{
354+
"members": members,
355+
"total_count": len(members),
356+
"node": nodeID,
357+
"correlation_id": correlationID,
358+
}
359+
w.Header().Set("Content-Type", "application/json")
360+
w.Header().Set("X-Correlation-ID", correlationID)
361+
json.NewEncoder(w).Encode(response)
362+
})
363+
335364
// Cache operations with middleware
336365
mux.Handle("/api/cache/", logging.HTTPMiddleware(http.HandlerFunc(handleCacheRequest(coordinator, store, nodeID))))
337366

0 commit comments

Comments
 (0)