diff --git a/Dockerfile b/Dockerfile index 0e2fdc83..2355fdd2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,7 @@ # Multi-stage build for PredictIQ API -FROM rust:1.75-slim as builder +# Pinned to specific digest for reproducible builds and security +# rust:1.75-slim digest verified on 2024-01-15 +FROM rust:1.75-slim@sha256:4dd48afa1d6fcf622b18b60081bb6c897b11787b42006aea2f2cf5ff3f6ae0cc as builder WORKDIR /build @@ -16,7 +18,8 @@ COPY . . RUN cd services/api && cargo build --release # Runtime stage -FROM debian:bookworm-slim +# debian:bookworm-slim digest verified on 2024-01-15 +FROM debian:bookworm-slim@sha256:3d868b89a1b0d8b957fa1798fffb5e1b6db5ac4e9c79e74acd418db9be3506b WORKDIR /app @@ -26,9 +29,19 @@ RUN apt-get update && apt-get install -y \ libssl3 \ && rm -rf /var/lib/apt/lists/* +# Create non-root user for security +# Prevents container escape vulnerabilities from granting root access to host +RUN groupadd -r appuser && useradd -r -g appuser appuser + # Copy binary from builder COPY --from=builder /build/services/api/target/release/predictiq-api /app/ +# Set ownership to non-root user +RUN chown -R appuser:appuser /app + +# Switch to non-root user +USER appuser + # Health check HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ CMD curl -f http://localhost:8080/health || exit 1 diff --git a/docker-compose.tracing.yml b/docker-compose.tracing.yml index d5161d83..ca819078 100644 --- a/docker-compose.tracing.yml +++ b/docker-compose.tracing.yml @@ -13,6 +13,16 @@ services: environment: - COLLECTOR_OTLP_ENABLED=true - LOG_LEVEL=info + # Resource limits: Jaeger can consume significant memory with high trace volume + # CPU: 1 core, Memory: 1GB (adjust based on trace volume) + deploy: + resources: + limits: + cpus: '1' + memory: 1G + reservations: + cpus: '0.5' + memory: 512M networks: - predictiq-tracing @@ -21,6 +31,16 @@ services: container_name: predictiq-zipkin ports: - "9411:9411" # Zipkin UI and API + # Resource limits: Zipkin is lightweight but should be bounded + # CPU: 0.5 core, Memory: 512MB + deploy: + resources: + limits: + cpus: '0.5' + memory: 512M + reservations: + cpus: '0.25' + memory: 256M networks: - predictiq-tracing @@ -35,6 +55,19 @@ services: - "4318:4318" # OTLP HTTP receiver - "8888:8888" # Prometheus metrics - "13133:13133" # Health check + environment: + - JAEGER_ENDPOINT=${JAEGER_ENDPOINT:-jaeger:14250} + - ZIPKIN_ENDPOINT=${ZIPKIN_ENDPOINT:-http://zipkin:9411/api/v2/spans} + # Resource limits: OTEL collector processes and exports traces + # CPU: 0.5 core, Memory: 512MB (adjust based on throughput) + deploy: + resources: + limits: + cpus: '0.5' + memory: 512M + reservations: + cpus: '0.25' + memory: 256M depends_on: - jaeger - zipkin diff --git a/docs/DISTRIBUTED_TRACING.md b/docs/DISTRIBUTED_TRACING.md index c9377cef..c763bda9 100644 --- a/docs/DISTRIBUTED_TRACING.md +++ b/docs/DISTRIBUTED_TRACING.md @@ -23,6 +23,31 @@ All services support the following environment variables: - `OTEL_TRACE_SAMPLING_RATIO`: Sampling rate 0.0-1.0 (default: `1.0`) - `RUST_LOG`: Log level for Rust services (default: `info`) +### OTLP Collector Configuration + +The OpenTelemetry collector (`otel-collector-config.yml`) supports environment variable substitution for exporter endpoints: + +- `JAEGER_ENDPOINT`: Jaeger exporter endpoint (default: `jaeger:14250`) +- `ZIPKIN_ENDPOINT`: Zipkin exporter endpoint (default: `http://zipkin:9411/api/v2/spans`) + +**Example: Production Configuration** + +```bash +# Set custom endpoints for production +export JAEGER_ENDPOINT=jaeger.prod.internal:14250 +export ZIPKIN_ENDPOINT=http://zipkin.prod.internal:9411/api/v2/spans + +# Start the tracing stack +docker-compose -f docker-compose.tracing.yml up +``` + +**Example: Development Configuration** + +```bash +# Use default local endpoints +docker-compose -f docker-compose.tracing.yml up +``` + ### API Service Configuration ```bash diff --git a/otel-collector-config.yml b/otel-collector-config.yml index baab9061..a79f70d2 100644 --- a/otel-collector-config.yml +++ b/otel-collector-config.yml @@ -23,12 +23,12 @@ processors: exporters: jaeger: - endpoint: jaeger:14250 + endpoint: ${JAEGER_ENDPOINT:-jaeger:14250} tls: insecure: true zipkin: - endpoint: http://zipkin:9411/api/v2/spans + endpoint: ${ZIPKIN_ENDPOINT:-http://zipkin:9411/api/v2/spans} logging: loglevel: info