# syntax=docker/dockerfile:1 # Multi-stage build for StarPunk production container # Podman and Docker compatible # ============================================================================ # Build Stage - Install dependencies in virtual environment # ============================================================================ FROM python:3.11-slim AS builder # Install uv for fast dependency installation COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv WORKDIR /build # Copy dependency files COPY requirements.txt . # Create virtual environment and install dependencies # Using uv for fast, reproducible installs RUN uv venv /opt/venv && \ . /opt/venv/bin/activate && \ uv pip install --no-cache -r requirements.txt # ============================================================================ # Runtime Stage - Minimal production image # ============================================================================ FROM python:3.11-slim # Create non-root user for security # UID/GID 1000 is standard for first user on most systems RUN useradd --uid 1000 --create-home --shell /bin/bash starpunk && \ mkdir -p /app /data/notes && \ chown -R starpunk:starpunk /app /data # Copy virtual environment from builder stage COPY --from=builder /opt/venv /opt/venv # Set environment variables ENV PATH="/opt/venv/bin:$PATH" \ PYTHONUNBUFFERED=1 \ PYTHONDONTWRITEBYTECODE=1 \ FLASK_APP=app.py \ DATA_PATH=/data \ NOTES_PATH=/data/notes \ DATABASE_PATH=/data/starpunk.db WORKDIR /app # Copy application code COPY --chown=starpunk:starpunk . . # Switch to non-root user USER starpunk # Expose application port EXPOSE 8000 # Health check # Uses httpx (already in requirements) to verify app is responding HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \ CMD python3 -c "import httpx; httpx.get('http://localhost:8000/health', timeout=2.0)" || exit 1 # Run gunicorn WSGI server # - 4 workers for concurrency (adjust based on CPU cores) # - Sync worker class (simple, reliable) # - Worker tmp dir in /dev/shm (shared memory, faster) # - Worker recycling to prevent memory leaks # - 30s timeout for slow requests # - Log to stdout/stderr for container log collection CMD ["gunicorn", \ "--bind", "0.0.0.0:8000", \ "--workers", "4", \ "--worker-class", "sync", \ "--worker-tmp-dir", "/dev/shm", \ "--max-requests", "1000", \ "--max-requests-jitter", "50", \ "--timeout", "30", \ "--graceful-timeout", "30", \ "--access-logfile", "-", \ "--error-logfile", "-", \ "--log-level", "info", \ "app:app"]