Run as a non-root user

Running as root inside a container is a habit from the laptop that follows engineers into production. Kubernetes security policies will eventually block it. Fix the image now so the policy never becomes an outage.

Dockerfile (hardened)
dockerfile
FROM python:3.11-slim
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/

RUN groupadd --system app && useradd --system --gid app --home /app app
WORKDIR /app

RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*

COPY --chown=app:app pyproject.toml ./
RUN uv sync

COPY --chown=app:app . .

ENV PYTHONUNBUFFERED=1 \
    PATH="/app/.venv/bin:$PATH" \
    HF_HOME=/app/.cache/huggingface

USER app

EXPOSE 8000
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]

Create a system user with a named home, chown the app files, then USER app before the CMD. Move HF_HOME under the app-owned path so the embedding cache writes without elevated permissions.

k8s/deployment.yaml (pod security)
yaml
spec:
  template:
    spec:
      securityContext:
        runAsNonRoot: true
        runAsUser: 1000
        fsGroup: 1000
      containers:
        - name: api
          securityContext:
            allowPrivilegeEscalation: false
            readOnlyRootFilesystem: false
            capabilities:
              drop: [ALL]

runAsNonRoot makes Kubernetes refuse to schedule a root container. allowPrivilegeEscalation: false prevents the process from gaining root via setuid binaries. Dropping ALL capabilities removes the default kernel privileges your app will not use anyway.

Quiz: Quiz

Loading practice…