# Multi-stage build for ML Experiment Manager FROM golang:1.25-alpine AS go-builder # Install dependencies RUN apk add --no-cache git make podman redis # Set working directory WORKDIR /app # Copy go mod files COPY go.mod go.sum ./ # Download dependencies RUN go mod download # Copy source code COPY . . # Build Go binaries RUN make build # Zig CLI stage FROM alpine:3.19 AS zig-builder # Install dependencies RUN apk add --no-cache curl xz # Install Zig RUN curl -L https://ziglang.org/download/0.15.2/zig-linux-aarch64-0.15.2.tar.xz | tar -xJ -C /opt ENV PATH="/opt/zig-linux-aarch64-0.15.2:${PATH}" # Copy CLI source COPY cli/ /app/cli/ # Build Zig CLI WORKDIR /app/cli RUN zig build cross # Final stage FROM alpine:3.19 # Install runtime dependencies RUN apk add --no-cache ca-certificates rsync openssh-client redis # Create app user RUN addgroup -g 1001 -S appgroup && \ adduser -u 1001 -S appuser -G appgroup # Set working directory WORKDIR /app # Copy binaries from builders COPY --from=go-builder /app/bin/ /usr/local/bin/ COPY --from=zig-builder /app/cli/zig-out/bin/ml /usr/local/bin/ # Copy configs COPY --from=go-builder /app/configs/ /app/configs/ # Create directories RUN mkdir -p /data/experiments /data/datasets /data/snapshots /home/appuser/.ml && \ mkdir -p /app/data/experiments /app/data/datasets /app/data/snapshots /app/logs /app/ssl && \ chown -R appuser:appgroup /data /app /home/appuser # Switch to app user USER appuser # Expose ports EXPOSE 9101 # Health check HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ CMD wget --no-verbose --tries=1 --no-check-certificate --spider https://localhost:9101/health || exit 1 # Default command CMD ["/usr/local/bin/api-server", "-config", "/app/configs/api/dev.yaml"]