# Multi-stage build for smaller final image FROM python:3.13-slim AS builder # Install uv for fast dependency management COPY --from=ghcr.io/astral-sh/uv:latest /uv /bin/uv # Set working directory WORKDIR /app # Copy dependency files COPY pyproject.toml uv.lock README.md ./ ARG CI_TOKEN # Install dependencies in a virtual environment RUN uv sync --frozen --no-cache # Production stage FROM python:3.13-slim # Create non-root user for security RUN groupadd -r appuser && useradd -r -g appuser -u 1000 appuser # Install uv in production image COPY --from=ghcr.io/astral-sh/uv:latest /uv /bin/uv # Set working directory WORKDIR /app # Copy virtual environment from builder stage COPY --from=builder /app/.venv /app/.venv # Copy application code COPY src/ ./src/ # Create directories and set permissions RUN mkdir -p /app/logs && \ chown -R appuser:appuser /app # Switch to non-root user USER appuser # Set environment variables ENV PATH="/app/.venv/bin:$PATH" \ PYTHONPATH="/app/src" \ PYTHONUNBUFFERED=1 \ PYTHONDONTWRITEBYTECODE=1 # Expose port (non-privileged port) EXPOSE 8000 # Health check HEALTHCHECK --interval=120s --timeout=10s --start-period=60s --retries=3 \ CMD python -c "import requests; requests.get('http://localhost:8000/api/health', timeout=5)" # Run the application with uvicorn WORKDIR /app/src CMD uvicorn alpine_bits_python.api:app \ --host 0.0.0.0 \ --port 8000 \ --workers 4 \ --log-level info \ --access-log \ --forwarded-allow-ips "${FORWARDED_ALLOW_IPS:-127.0.0.1}" \ --proxy-headers \ --no-server-header