diff --git a/docker/Dockerfile b/docker/Dockerfile deleted file mode 100644 index cf615d7..0000000 --- a/docker/Dockerfile +++ /dev/null @@ -1,148 +0,0 @@ -# Multi-stage Dockerfile for Attune Rust services -# This Dockerfile can build any of the Attune services by specifying a build argument -# Usage: DOCKER_BUILDKIT=1 docker build --build-arg SERVICE=api -f docker/Dockerfile -t attune-api . -# -# BuildKit cache mounts are used to speed up incremental builds by persisting: -# - Cargo registry and git cache (with sharing=locked to prevent race conditions) -# - Rust incremental compilation artifacts -# -# This dramatically reduces rebuild times from ~5 minutes to ~30 seconds for code-only changes. - -ARG RUST_VERSION=1.92 -ARG DEBIAN_VERSION=bookworm - -# ============================================================================ -# Stage 1: Builder - Compile the Rust services -# ============================================================================ -FROM rust:${RUST_VERSION}-${DEBIAN_VERSION} AS builder - -# Install build dependencies -RUN apt-get update && apt-get install -y \ - pkg-config \ - libssl-dev \ - ca-certificates \ - && rm -rf /var/lib/apt/lists/* - -WORKDIR /build - -# Increase rustc stack size to prevent SIGSEGV during release builds -ENV RUST_MIN_STACK=67108864 - -# Copy workspace manifests and source code -COPY Cargo.toml Cargo.lock ./ -COPY crates/ ./crates/ -COPY migrations/ ./migrations/ -COPY .sqlx/ ./.sqlx/ - -# Build argument to specify which service to build -ARG SERVICE=api - -# Build the specified service with BuildKit cache mounts -# Cache mount sharing modes prevent race conditions during parallel builds: -# - sharing=locked: Only one build can access the cache at a time (prevents file conflicts) -# - cargo registry/git: Locked to prevent "File exists" errors when extracting dependencies -# - target: Locked to prevent compilation artifact conflicts -# -# This is slower than parallel builds but eliminates race conditions. -# Alternative: Use docker-compose --build with --no-parallel flag, or build sequentially. -# -# First build: ~5-6 minutes -# Incremental builds (code changes only): ~30-60 seconds -RUN --mount=type=cache,target=/usr/local/cargo/registry,sharing=locked \ - --mount=type=cache,target=/usr/local/cargo/git,sharing=locked \ - --mount=type=cache,target=/build/target,sharing=locked \ - cargo build --release --bin attune-${SERVICE} && \ - cp /build/target/release/attune-${SERVICE} /build/attune-service-binary - -# ============================================================================ -# Stage 2: Pack Binaries Builder - Build native pack binaries with GLIBC 2.36 -# ============================================================================ -FROM rust:${RUST_VERSION}-${DEBIAN_VERSION} AS pack-builder - -# Install build dependencies -RUN apt-get update && apt-get install -y \ - pkg-config \ - libssl-dev \ - ca-certificates \ - && rm -rf /var/lib/apt/lists/* - -WORKDIR /build - -# Increase rustc stack size to prevent SIGSEGV during release builds -ENV RUST_MIN_STACK=67108864 - -# Copy workspace files -COPY Cargo.toml Cargo.lock ./ -COPY crates/ ./crates/ -COPY .sqlx/ ./.sqlx/ - -# Build pack binaries (sensors, etc.) with GLIBC 2.36 for maximum compatibility -# These binaries will work on any system with GLIBC 2.36 or newer -# IMPORTANT: Copy binaries WITHIN the cache mount, before it's unmounted -RUN --mount=type=cache,target=/usr/local/cargo/registry,sharing=locked \ - --mount=type=cache,target=/usr/local/cargo/git,sharing=locked \ - --mount=type=cache,target=/build/target,sharing=locked \ - mkdir -p /build/pack-binaries && \ - cargo build --release --bin attune-core-timer-sensor && \ - cp /build/target/release/attune-core-timer-sensor /build/pack-binaries/attune-core-timer-sensor && \ - ls -lh /build/pack-binaries/ - -# Verify binaries were copied successfully (after cache unmount) -RUN ls -lah /build/pack-binaries/ && \ - test -f /build/pack-binaries/attune-core-timer-sensor && \ - echo "Timer sensor binary built successfully" - -# ============================================================================ -# Stage 3: Runtime - Create minimal runtime image -# ============================================================================ -FROM debian:${DEBIAN_VERSION}-slim AS runtime - -# Install runtime dependencies -RUN apt-get update && apt-get install -y \ - ca-certificates \ - libssl3 \ - curl \ - && rm -rf /var/lib/apt/lists/* - -# Create non-root user -RUN useradd -m -u 1000 attune && \ - mkdir -p /opt/attune/packs /opt/attune/logs /opt/attune/config && \ - chown -R attune:attune /opt/attune - -WORKDIR /opt/attune - -# Copy the service binary from builder -# Note: We copy from /build/attune-service-binary because the cache mount is not available in COPY -COPY --from=builder /build/attune-service-binary /usr/local/bin/attune-service - -# Copy migrations for services that need them. -# Runtime config is mounted via Docker Compose. -COPY migrations/ ./migrations/ - -# Copy packs directory (excluding binaries that will be overwritten) -COPY packs/ ./packs/ - -# Overwrite pack binaries with ones built with compatible GLIBC from pack-builder stage -# Copy individual files to ensure they overwrite existing ones -COPY --from=pack-builder /build/pack-binaries/attune-core-timer-sensor ./packs/core/sensors/attune-core-timer-sensor - -# Make binaries executable and set ownership -RUN chmod +x ./packs/core/sensors/attune-core-timer-sensor && \ - chown -R attune:attune /opt/attune - -# Switch to non-root user -USER attune - -# Environment variables (can be overridden at runtime) -ENV RUST_LOG=info -ENV ATTUNE_CONFIG=/opt/attune/config/config.yaml - -# Health check (will be overridden per service in docker-compose) -HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \ - CMD curl -f http://localhost:8080/health || exit 1 - -# Expose default port (override per service) -EXPOSE 8080 - -# Run the service -CMD ["/usr/local/bin/attune-service"] diff --git a/docker/Dockerfile.pack-builder b/docker/Dockerfile.pack-builder deleted file mode 100644 index 905ec21..0000000 --- a/docker/Dockerfile.pack-builder +++ /dev/null @@ -1,104 +0,0 @@ -# Dockerfile for building Attune pack binaries with maximum GLIBC compatibility -# -# This builds native pack binaries (sensors, etc.) using an older GLIBC version -# to ensure forward compatibility across different deployment environments. -# -# GLIBC compatibility: -# - Binaries built with GLIBC 2.36 work on 2.36, 2.38, 2.39, etc. (forward compatible) -# - Binaries built with GLIBC 2.39 only work on 2.39+ (not backward compatible) -# -# Usage: -# docker build -f docker/Dockerfile.pack-builder -t attune-pack-builder . -# docker run --rm -v $(pwd)/packs:/output attune-pack-builder -# -# This will build all pack binaries and copy them to ./packs with GLIBC 2.36 compatibility - -ARG RUST_VERSION=1.92 -ARG DEBIAN_VERSION=bookworm - -# ============================================================================ -# Stage 1: Build Environment -# ============================================================================ -FROM rust:${RUST_VERSION}-${DEBIAN_VERSION} AS builder - -# Install build dependencies -RUN apt-get update && apt-get install -y \ - pkg-config \ - libssl-dev \ - ca-certificates \ - && rm -rf /var/lib/apt/lists/* - -WORKDIR /build - -# Increase rustc stack size to prevent SIGSEGV during release builds -ENV RUST_MIN_STACK=67108864 - -# Copy workspace files -COPY Cargo.toml Cargo.lock ./ -COPY crates/ ./crates/ - -# Build all pack binaries in release mode with BuildKit cache -RUN --mount=type=cache,target=/usr/local/cargo/registry,sharing=locked \ - --mount=type=cache,target=/usr/local/cargo/git,sharing=locked \ - --mount=type=cache,target=/build/target,sharing=locked \ - cargo build --release --bin attune-core-timer-sensor && \ - cargo build --release --bin attune-timer-sensor && \ - mkdir -p /build/binaries && \ - cp /build/target/release/attune-core-timer-sensor /build/binaries/ && \ - cp /build/target/release/attune-timer-sensor /build/binaries/ - -# Verify GLIBC version used -RUN ldd --version | head -1 && \ - echo "Binaries built with the above GLIBC version for maximum compatibility" - -# ============================================================================ -# Stage 2: Output Stage -# ============================================================================ -FROM debian:${DEBIAN_VERSION}-slim AS output - -WORKDIR /output - -# Copy built binaries -COPY --from=builder /build/binaries/* ./ - -# Create a script to copy binaries to the correct pack locations -RUN cat > /copy-to-packs.sh << 'EOF' -#!/bin/bash -set -e - -OUTPUT_DIR=${OUTPUT_DIR:-/output} -PACKS_DIR=${PACKS_DIR:-/packs} - -echo "Copying pack binaries from /build to $PACKS_DIR..." - -# Copy timer sensor binaries -if [ -f /build/attune-core-timer-sensor ]; then - mkdir -p "$PACKS_DIR/core/sensors" - cp /build/attune-core-timer-sensor "$PACKS_DIR/core/sensors/" - chmod +x "$PACKS_DIR/core/sensors/attune-core-timer-sensor" - echo "✓ Copied attune-core-timer-sensor to core pack" -fi - -if [ -f /build/attune-timer-sensor ]; then - mkdir -p "$PACKS_DIR/core/sensors" - cp /build/attune-timer-sensor "$PACKS_DIR/core/sensors/" - chmod +x "$PACKS_DIR/core/sensors/attune-timer-sensor" - echo "✓ Copied attune-timer-sensor to core pack" -fi - -# Verify GLIBC requirements -echo "" -echo "Verifying GLIBC compatibility..." -ldd /build/attune-core-timer-sensor 2>/dev/null | grep GLIBC || echo "Built with GLIBC $(ldd --version | head -1)" - -echo "" -echo "Pack binaries built successfully with GLIBC 2.36 compatibility" -echo "These binaries will work on any system with GLIBC 2.36 or newer" -EOF - -RUN chmod +x /copy-to-packs.sh - -# Copy binaries to /build for the script -COPY --from=builder /build/binaries/* /build/ - -CMD ["/copy-to-packs.sh"] diff --git a/docker/Dockerfile.worker b/docker/Dockerfile.worker deleted file mode 100644 index c58671c..0000000 --- a/docker/Dockerfile.worker +++ /dev/null @@ -1,288 +0,0 @@ -# Multi-stage Dockerfile for Attune workers -# Supports building different worker variants with different runtime capabilities -# -# Usage: -# docker build --target worker-base -t attune-worker:base -f docker/Dockerfile.worker . -# docker build --target worker-python -t attune-worker:python -f docker/Dockerfile.worker . -# docker build --target worker-node -t attune-worker:node -f docker/Dockerfile.worker . -# docker build --target worker-full -t attune-worker:full -f docker/Dockerfile.worker . -# -# BuildKit cache mounts are used to speed up incremental builds. - -ARG RUST_VERSION=1.92 -ARG DEBIAN_VERSION=bookworm -ARG NODE_VERSION=20 - -# ============================================================================ -# Stage 1: Builder - Compile the worker binary -# ============================================================================ -FROM rust:${RUST_VERSION}-${DEBIAN_VERSION} AS builder - -# Install build dependencies -RUN apt-get update && apt-get install -y \ - pkg-config \ - libssl-dev \ - ca-certificates \ - && rm -rf /var/lib/apt/lists/* - -WORKDIR /build - -# Increase rustc stack size to prevent SIGSEGV during release builds -ENV RUST_MIN_STACK=67108864 - -# Copy workspace manifests and source code -COPY Cargo.toml Cargo.lock ./ -COPY crates/ ./crates/ -COPY migrations/ ./migrations/ -COPY .sqlx/ ./.sqlx/ - -# Build the worker binary with BuildKit cache mounts -# sharing=locked prevents race conditions during parallel builds -RUN --mount=type=cache,target=/usr/local/cargo/registry,sharing=locked \ - --mount=type=cache,target=/usr/local/cargo/git,sharing=locked \ - --mount=type=cache,target=/build/target,sharing=locked \ - cargo build --release --bin attune-worker && \ - cp /build/target/release/attune-worker /build/attune-worker - -# Verify the binary was built -RUN ls -lh /build/attune-worker && \ - file /build/attune-worker && \ - /build/attune-worker --version || echo "Version check skipped" - -# ============================================================================ -# Stage 2a: Base Worker (Shell only) -# Runtime capabilities: shell -# Use case: Lightweight workers for shell scripts and basic automation -# ============================================================================ -FROM debian:${DEBIAN_VERSION}-slim AS worker-base - -# Install runtime dependencies -RUN apt-get update && apt-get install -y \ - ca-certificates \ - libssl3 \ - curl \ - bash \ - procps \ - && rm -rf /var/lib/apt/lists/* - -# Create worker user and directories -RUN useradd -m -u 1000 attune && \ - mkdir -p /opt/attune/packs /opt/attune/logs /opt/attune/config && \ - chown -R attune:attune /opt/attune - -WORKDIR /opt/attune - -# Copy worker binary from builder -COPY --from=builder /build/attune-worker /usr/local/bin/attune-worker - -# Copy packs directory -COPY packs/ ./packs/ - -# Set ownership -RUN chown -R attune:attune /opt/attune - -# Switch to non-root user -USER attune - -# Environment variables -ENV ATTUNE_WORKER_RUNTIMES="shell" -ENV ATTUNE_WORKER_TYPE="container" -ENV RUST_LOG=info -ENV ATTUNE_CONFIG=/opt/attune/config/config.yaml - -# Health check -HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \ - CMD pgrep -f attune-worker || exit 1 - -# Run the worker -CMD ["/usr/local/bin/attune-worker"] - -# ============================================================================ -# Stage 2b: Python Worker (Shell + Python) -# Runtime capabilities: shell, python -# Use case: Python actions and scripts with dependencies -# -# Uses debian-slim + apt python3 (NOT the python: Docker image) so that -# python3 lives at /usr/bin/python3 — the same path as worker-full. -# This avoids broken venv symlinks when multiple workers share the -# runtime_envs volume. -# ============================================================================ -FROM debian:${DEBIAN_VERSION}-slim AS worker-python - -# Install system dependencies including Python -RUN apt-get update && apt-get install -y \ - ca-certificates \ - libssl3 \ - curl \ - build-essential \ - python3 \ - python3-pip \ - python3-venv \ - procps \ - && rm -rf /var/lib/apt/lists/* - -# Create python symlink for convenience -RUN ln -sf /usr/bin/python3 /usr/bin/python - -# Install common Python packages -# Use --break-system-packages for Debian 12+ pip-in-system-python restrictions -RUN pip3 install --no-cache-dir --break-system-packages \ - requests>=2.31.0 \ - pyyaml>=6.0 \ - jinja2>=3.1.0 \ - python-dateutil>=2.8.0 - -# Create worker user and directories -RUN useradd -m -u 1000 attune && \ - mkdir -p /opt/attune/packs /opt/attune/logs /opt/attune/runtime_envs /opt/attune/config && \ - chown -R attune:attune /opt/attune - -WORKDIR /opt/attune - -# Copy worker binary from builder -COPY --from=builder /build/attune-worker /usr/local/bin/attune-worker - -# Copy packs directory -COPY packs/ ./packs/ - -# Set ownership -RUN chown -R attune:attune /opt/attune - -# Switch to non-root user -USER attune - -# Environment variables -ENV ATTUNE_WORKER_RUNTIMES="shell,python" -ENV ATTUNE_WORKER_TYPE="container" -ENV RUST_LOG=info -ENV ATTUNE_CONFIG=/opt/attune/config/config.yaml - -# Health check -HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \ - CMD pgrep -f attune-worker || exit 1 - -# Run the worker -CMD ["/usr/local/bin/attune-worker"] - -# ============================================================================ -# Stage 2c: Node Worker (Shell + Node.js) -# Runtime capabilities: shell, node -# Use case: JavaScript/TypeScript actions and npm packages -# -# Uses debian-slim + NodeSource apt repo (NOT the node: Docker image) so that -# node lives at /usr/bin/node — the same path as worker-full. -# This avoids path mismatches when multiple workers share volumes. -# ============================================================================ -FROM debian:${DEBIAN_VERSION}-slim AS worker-node - -# Install system dependencies -RUN apt-get update && apt-get install -y \ - ca-certificates \ - libssl3 \ - curl \ - procps \ - && rm -rf /var/lib/apt/lists/* - -# Install Node.js from NodeSource (same method as worker-full) -RUN curl -fsSL https://deb.nodesource.com/setup_${NODE_VERSION}.x | bash - && \ - apt-get install -y nodejs && \ - rm -rf /var/lib/apt/lists/* - -# Create worker user and directories -RUN useradd -m -u 1000 attune && \ - mkdir -p /opt/attune/packs /opt/attune/logs /opt/attune/runtime_envs /opt/attune/config && \ - chown -R attune:attune /opt/attune - -WORKDIR /opt/attune - -# Copy worker binary from builder -COPY --from=builder /build/attune-worker /usr/local/bin/attune-worker - -# Copy packs directory -COPY packs/ ./packs/ - -# Set ownership -RUN chown -R attune:attune /opt/attune - -# Switch to non-root user -USER attune - -# Environment variables -ENV ATTUNE_WORKER_RUNTIMES="shell,node" -ENV ATTUNE_WORKER_TYPE="container" -ENV RUST_LOG=info -ENV ATTUNE_CONFIG=/opt/attune/config/config.yaml - -# Health check -HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \ - CMD pgrep -f attune-worker || exit 1 - -# Run the worker -CMD ["/usr/local/bin/attune-worker"] - -# ============================================================================ -# Stage 2d: Full Worker (All runtimes) -# Runtime capabilities: shell, python, node, native -# Use case: General-purpose automation with multi-language support -# ============================================================================ -FROM debian:${DEBIAN_VERSION} AS worker-full - -# Install system dependencies including Python and Node.js -RUN apt-get update && apt-get install -y \ - ca-certificates \ - libssl3 \ - curl \ - build-essential \ - python3 \ - python3-pip \ - python3-venv \ - procps \ - && rm -rf /var/lib/apt/lists/* - -# Install Node.js from NodeSource (same method and version as worker-node) -RUN curl -fsSL https://deb.nodesource.com/setup_${NODE_VERSION}.x | bash - && \ - apt-get install -y nodejs && \ - rm -rf /var/lib/apt/lists/* - -# Create python symlink for convenience -RUN ln -sf /usr/bin/python3 /usr/bin/python - -# Install common Python packages -# Use --break-system-packages for Debian 12+ pip-in-system-python restrictions -RUN pip3 install --no-cache-dir --break-system-packages \ - requests>=2.31.0 \ - pyyaml>=6.0 \ - jinja2>=3.1.0 \ - python-dateutil>=2.8.0 - -# Create worker user and directories -RUN useradd -m -u 1000 attune && \ - mkdir -p /opt/attune/packs /opt/attune/logs /opt/attune/runtime_envs /opt/attune/config && \ - chown -R attune:attune /opt/attune - -WORKDIR /opt/attune - -# Copy worker binary from builder -COPY --from=builder /build/attune-worker /usr/local/bin/attune-worker - -# Copy packs directory -COPY packs/ ./packs/ - -# Set ownership -RUN chown -R attune:attune /opt/attune - -# Switch to non-root user -USER attune - -# Environment variables -ENV ATTUNE_WORKER_RUNTIMES="shell,python,node,native" -ENV ATTUNE_WORKER_TYPE="container" -ENV RUST_LOG=info -ENV ATTUNE_CONFIG=/opt/attune/config/config.yaml - -# Health check -HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \ - CMD pgrep -f attune-worker || exit 1 - -# Run the worker -CMD ["/usr/local/bin/attune-worker"]