1- FROM tiangolo/uvicorn-gunicorn-fastapi:python3.9
2-
3- # Create a non-root user to run the application
4- RUN groupadd -g 1000 zxbasic && \
5- useradd -r -u 1000 -g zxbasic -m -d /home/zxbasic -s /bin/bash zxbasic
6-
7- WORKDIR /app
8-
9- # Copy requirements as root for installation
10- COPY ./requirements.txt /app/requirements.txt
11-
12- # Install dependencies as root
1+ # Build Python deps into an isolated venv so the runtime image carries no
2+ # compiler toolchain (gcc stays in this stage only).
3+ FROM python:3.9-slim-bookworm AS builder
134RUN apt-get update \
14- && apt-get install gcc -y \
15- && apt-get clean
5+ && apt-get install -y --no-install-recommends gcc \
6+ && rm -rf /var/lib/apt/lists/*
7+ RUN python -m venv /opt/venv
8+ ENV PATH="/opt/venv/bin:${PATH}"
9+ COPY requirements.txt .
10+ RUN pip install --no-cache-dir --upgrade pip \
11+ && pip install --no-cache-dir -r requirements.txt
12+
13+ # Runtime: minimal official slim base, no build tools.
14+ # Replaces the archived tiangolo/uvicorn-gunicorn-fastapi image.
15+ # NOTE: Python 3.9 is EOL (upstream fixes ended Oct 2025); kept to match the
16+ # tested FastAPI 0.61 / Pydantic v1 stack. Moving to 3.12 + current FastAPI /
17+ # Pydantic v2 is a separate, test-gated change.
18+ FROM python:3.9-slim-bookworm
19+
20+ COPY --from=builder /opt/venv /opt/venv
21+ ENV PATH="/opt/venv/bin:${PATH}" \
22+ PYTHONUNBUFFERED=1
23+
24+ # Non-root, no login shell.
25+ RUN groupadd -g 1000 zxbasic \
26+ && useradd -r -u 1000 -g zxbasic -m -d /home/zxbasic -s /usr/sbin/nologin zxbasic
1627
17- RUN pip install -r /app/requirements.txt \
18- && rm -rf /root/.cache/pip
19-
20- # Copy application code and set ownership
28+ WORKDIR /app
2129COPY --chown=zxbasic:zxbasic . /app/
22-
23- # Create a directory for temporary files with proper permissions
24- RUN mkdir -p /tmp/zxbasic && \
25- chown -R zxbasic:zxbasic /tmp/zxbasic && \
26- chmod 755 /tmp/zxbasic
27-
28- # Ensure the app directory is owned by zxbasic user
29- RUN chown -R zxbasic:zxbasic /app
30-
31- # Switch to non-root user
3230USER zxbasic
3331
34- # Set environment variable for temp directory (optional - Python tempfile will use system default)
35- # ENV TMPDIR=/tmp/zxbasic
32+ EXPOSE 80
33+ HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \
34+ CMD python -c "import urllib.request,sys; sys.exit(0 if urllib.request.urlopen('http://127.0.0.1:80/health', timeout=3).status==200 else 1)"
3635
37- # The container will run with the default command from the base image
36+ CMD [ "uvicorn" , "app.main:app" , "--host" , "0.0.0.0" , "--port" , "80" ]
0 commit comments