diff --git a/Dockerfile b/Dockerfile index 1ba534b..740f36d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,87 +1,109 @@ FROM ghcr.io/astral-sh/uv:bookworm-slim AS uv -FROM python:3.12 as dev +# Build stage +FROM python:3.12-slim AS builder # Set environment variables -ENV PYTHONDONTWRITEBYTECODE 1 -ENV PYTHONUNBUFFERED 1 -ENV PYTHONPATH /app -ENV UV_CACHE_DIR /app/.cache/uv -ENV UV_VENV_DIRECTORY /app/.venv +ENV PYTHONDONTWRITEBYTECODE=1 +ENV PYTHONUNBUFFERED=1 +ENV PYTHONPATH=/app +ENV UV_CACHE_DIR=/tmp/.cache/uv +ENV UV_VENV_DIRECTORY=/app/.venv # Set work directory WORKDIR /app -# Copy pyproject.toml -COPY pyproject.toml uv.lock ./ - -# Install system dependencies and uv -RUN apt-get update && apt-get install -y \ +# Install build dependencies in one layer +RUN apt-get update && apt-get install -y --no-install-recommends \ build-essential \ - curl \ gcc \ nodejs \ npm \ gettext \ - && rm -rf /var/lib/apt/lists/* + && rm -rf /var/lib/apt/lists/* \ + && apt-get clean +# Copy uv binary COPY --from=uv /usr/local/bin/uv /usr/local/bin/uv +# Copy dependency files first for better caching +COPY pyproject.toml uv.lock ./ + +# Install Python dependencies RUN uv sync --no-dev --frozen --no-install-project -# Copy project -COPY . . +# Copy only necessary project files +COPY manage.py ./ +COPY core/ ./core/ +COPY links/ ./links/ +COPY new_theme/ ./new_theme/ +COPY templates/ ./templates/ +COPY locale/ ./locale/ +COPY tailwind.config.js ./ -# Install Tailwind CSS dependencies -RUN uv run manage.py tailwind install -# Build Tailwind CSS -RUN uv run manage.py tailwind build -# Collect static files -RUN uv run manage.py collectstatic --noinput -# Compile translation messages -RUN uv run manage.py compilemessages --locale=zh_Hans -# Create data directory for SQLite database -RUN mkdir -p /app/data && chmod 777 /app/data +# Build static assets and translations +RUN uv run manage.py tailwind install \ + && uv run manage.py tailwind build \ + && uv run manage.py collectstatic --noinput \ + && uv run manage.py compilemessages --locale=zh_Hans +# Clean up build cache and unnecessary files +RUN rm -rf /tmp/.cache/uv ~/.npm ~/.cache \ + && find /app -name "*.pyc" -delete \ + && find /app -name "__pycache__" -type d -exec rm -rf {} + || true + +# Production stage FROM python:3.12-slim -ENV PYTHONDONTWRITEBYTECODE 1 -ENV PYTHONUNBUFFERED 1 -ENV PYTHONPATH /app -ENV UV_CACHE_DIR /app/.cache/uv -ENV UV_VENV_DIRECTORY /app/.venv - -COPY --from=uv /usr/local/bin/uv /usr/local/bin/uv -COPY --from=dev /app /app +# Set environment variables +ENV PYTHONDONTWRITEBYTECODE=1 +ENV PYTHONUNBUFFERED=1 +ENV PYTHONPATH=/app +ENV VIRTUAL_ENV=/app/.venv +ENV PATH="/app/.venv/bin:$PATH" +# Set work directory WORKDIR /app -RUN apt-get update && apt-get install -y \ +# Install only runtime dependencies +RUN apt-get update && apt-get install -y --no-install-recommends \ curl \ - wget \ - gnupg \ chromium \ chromium-driver \ fonts-arphic-ukai \ - && rm -rf /var/lib/apt/lists/* + && rm -rf /var/lib/apt/lists/* \ + && apt-get clean -# Create a non-root user -RUN mkdir -p /app/data/media/screenshots \ - && useradd -m -u 1000 appuser \ +# Create non-root user and directories +RUN useradd -m -u 1000 appuser \ + && mkdir -p /app/data/media/screenshots \ && chown -R appuser:appuser /app +# Copy only the virtual environment and built assets +COPY --from=builder --chown=appuser:appuser /app/.venv /app/.venv +COPY --from=builder --chown=appuser:appuser /app/staticfiles /app/staticfiles +COPY --from=builder --chown=appuser:appuser /app/locale /app/locale + +# Copy application code +COPY --chown=appuser:appuser manage.py ./ +COPY --chown=appuser:appuser core/ ./core/ +COPY --chown=appuser:appuser links/ ./links/ +COPY --chown=appuser:appuser new_theme/ ./new_theme/ +COPY --chown=appuser:appuser templates/ ./templates/ + +# Clean up any Python cache files +RUN find /app -name "*.pyc" -delete \ + && find /app -name "__pycache__" -type d -exec rm -rf {} + || true + +# Switch to non-root user USER appuser -# Install dependencies using uv -RUN uv venv /app/.venv - -ENV PATH="/app/.venv/bin:$PATH" -ENV VIRTUAL_ENV=/app/.venv - -RUN uv sync --no-dev --frozen --no-install-project - # Expose port 8000 EXPOSE 8000 +# Health check +HEALTHCHECK --interval=30s --timeout=30s --start-period=5s --retries=3 \ + CMD curl -f http://localhost:8000/ || exit 1 + # Run the application -CMD ["uv", "run", "gunicorn", "--chdir", "/app", "core.wsgi:application", "--bind", "0.0.0.0:8000"] +CMD ["gunicorn", "--chdir", "/app", "core.wsgi:application", "--bind", "0.0.0.0:8000"]