|
1 | | -# - Stage 1: Build dependencies into wheels ------------------------------------ |
| 1 | +# - Stage 1: Builder ----------------------------------------------------------- |
2 | 2 |
|
3 | | - FROM python:3.13.3-slim-bookworm AS build |
| 3 | +FROM python:3.13.3-slim-bookworm AS builder |
| 4 | +WORKDIR /app |
4 | 5 |
|
5 | | - WORKDIR /app |
| 6 | +# Install system build tools for packages with native extensions |
| 7 | +RUN apt-get update && \ |
| 8 | + apt-get install -y --no-install-recommends build-essential gcc libffi-dev libssl-dev && \ |
| 9 | + rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/*.deb |
6 | 10 |
|
7 | | - # Install system build tools needed to compile Python packages with native |
8 | | - # extensions, and clean up afterward to reduce image size. |
9 | | - RUN apt-get update && \ |
10 | | - apt-get install -y --no-install-recommends build-essential gcc libffi-dev libssl-dev && \ |
11 | | - rm -rf /var/lib/apt/lists/* && \ |
12 | | - rm -rf /var/cache/apt/archives/*.deb |
| 11 | +# Pre-build all dependencies into wheels for reproducibility and speed |
| 12 | +COPY --chown=root:root --chmod=644 requirements.txt . |
| 13 | +RUN pip wheel --no-cache-dir --wheel-dir=/app/wheelhouse -r requirements.txt |
13 | 14 |
|
14 | | - # Pre-build all third-party dependencies into wheel files. This enables faster, |
15 | | - # more reliable installation later without relying on network access. |
16 | | - COPY requirements.txt . |
17 | | - RUN pip wheel --no-cache-dir --wheel-dir=/app/wheelhouse -r requirements.txt |
| 15 | +# - Stage 2: Runtime ----------------------------------------------------------- |
18 | 16 |
|
19 | | -# - Stage 2: Runtime image ---------------------------------------------------- |
| 17 | +FROM python:3.13.3-slim-bookworm AS runtime |
| 18 | +WORKDIR /app |
20 | 19 |
|
21 | | - FROM python:3.13.3-slim-bookworm AS runtime |
| 20 | +# Metadata labels |
| 21 | +LABEL org.opencontainers.image.title="🧪 RESTful API with Python 3 and FastAPI" |
| 22 | +LABEL org.opencontainers.image.description="Proof of Concept for a RESTful API made with Python 3 and FastAPI" |
| 23 | +LABEL org.opencontainers.image.licenses="MIT" |
| 24 | +LABEL org.opencontainers.image.source="https://github.com/nanotaboada/python-samples-fastapi-restful" |
22 | 25 |
|
23 | | - WORKDIR /app |
| 26 | +# Copy prebuilt wheels and install dependencies |
| 27 | +COPY --from=builder --chown=root:root --chmod=755 /app/wheelhouse /app/wheelhouse |
| 28 | +COPY --chown=root:root --chmod=644 requirements.txt . |
| 29 | +RUN pip install --no-cache-dir --no-index --find-links /app/wheelhouse -r requirements.txt && \ |
| 30 | + rm -rf /app/wheelhouse |
24 | 31 |
|
25 | | - # Install runtime dependencies from prebuilt wheels (no network access). |
26 | | - # This improves build speed and avoids dependency drift. |
27 | | - COPY requirements.txt . |
28 | | - COPY --from=build /app/wheelhouse /app/wheelhouse |
29 | | - RUN pip install --no-cache-dir --no-index --find-links /app/wheelhouse -r requirements.txt && \ |
30 | | - rm -rf /app/wheelhouse |
| 32 | +# Copy application code (read-only) |
| 33 | +COPY --chown=root:root --chmod=644 main.py ./ |
| 34 | +COPY --chown=root:root --chmod=755 models ./models |
| 35 | +COPY --chown=root:root --chmod=755 routes ./routes |
| 36 | +COPY --chown=root:root --chmod=755 schemas ./schemas |
| 37 | +COPY --chown=root:root --chmod=755 services ./services |
| 38 | +COPY --chown=root:root --chmod=755 data ./data |
31 | 39 |
|
32 | | - # Copy only runtime-relevant application code (excluding tests and tooling) |
33 | | - COPY models ./models |
34 | | - COPY routes ./routes |
35 | | - COPY schemas ./schemas |
36 | | - COPY services ./services |
37 | | - COPY data ./data |
38 | | - COPY main.py . |
| 40 | +# Copy metadata for GHCR (read-only) |
| 41 | +COPY --chown=root:root --chmod=644 README.md ./ |
| 42 | +COPY --chown=root:root --chmod=755 assets ./assets |
39 | 43 |
|
40 | | - # Copy README and assets needed for GHCR package page metadata |
41 | | - COPY README.md ./ |
42 | | - COPY assets ./assets |
| 44 | +# Create a non-root user for running the app |
| 45 | +RUN adduser --system --disabled-password --gecos '' fastapi |
43 | 46 |
|
44 | | - # Add a non-root user for better container security |
45 | | - RUN adduser --disabled-password --gecos '' fastapi && \ |
46 | | - chown -R fastapi:fastapi /app |
47 | | - USER fastapi |
| 47 | +# Drop privileges |
| 48 | +USER fastapi |
48 | 49 |
|
49 | | - # Ensure logs and errors appear in Docker logs immediately |
50 | | - ENV PYTHONUNBUFFERED=1 |
| 50 | +# Logging output immediately |
| 51 | +ENV PYTHONUNBUFFERED=1 |
51 | 52 |
|
52 | | - # Expose FastAPI default port |
53 | | - EXPOSE 9000 |
| 53 | +EXPOSE 9000 |
54 | 54 |
|
55 | | - # Start the FastAPI application using Uvicorn ASGI server |
56 | | - CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "9000"] |
| 55 | +CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "9000"] |
0 commit comments