| # --- Stage 1: Build Stage --- | |
| # Use a specific Python version to ensure consistency. | |
| FROM python:3.11-slim as builder | |
| # Set the working directory | |
| WORKDIR /usr/src/app | |
| # Upgrade pip and install wheel to build dependencies efficiently | |
| RUN pip install --upgrade pip wheel | |
| # Copy only the requirements file to leverage Docker's layer caching. | |
| # This step will only be re-run if requirements.txt changes. | |
| COPY ./requirements.txt . | |
| # Build wheel files for all dependencies. This is faster and more reliable | |
| # for the final stage than a simple 'pip install'. | |
| RUN pip wheel --no-cache-dir --wheel-dir /usr/src/app/wheels -r requirements.txt | |
| # --- Stage 2: Runtime Stage --- | |
| # Use the same slim Python base image for a smaller final image size. | |
| FROM python:3.11-slim | |
| # Set a non-root user for better security | |
| RUN addgroup --system app && adduser --system --group app | |
| # Set the working directory | |
| WORKDIR /home/app | |
| # Copy the pre-built wheel dependencies from the builder stage | |
| COPY --from=builder /usr/src/app/wheels /wheels | |
| COPY --from=builder /usr/src/app/requirements.txt . | |
| # Install the dependencies from local wheel files without needing to rebuild them. | |
| # --no-index and --find-links ensure pip only uses the local wheels. | |
| RUN pip install --no-cache /wheels/* | |
| # Copy the application code into the container | |
| COPY --chown=app:app . . | |
| # Switch to the non-root user | |
| USER app | |
| # Expose the port Gunicorn will listen on | |
| EXPOSE 8000 | |
| # The command to start the Gunicorn server | |
| CMD ["gunicorn", "-c", "gunicorn_config.py", "main:app"] |