AI Intermediate: Infrastructure & Agentic SystemsDay 2 of 30 · Week 1: Bare-Metal Infrastructure & Advanced Containerization
Course outline▾

Week 1 · Bare-Metal Infrastructure & Advanced Containerization

  1. Day 1The AI Infrastructure Shift — Why the Model is Only 10% of the Production System
  2. Day 2Advanced Docker for AI — Multi-Stage Builds for Heavy Python Runtimes
  3. Day 3Hardware Acceleration in Docker: Configuring Resource Passthrough for Constrained Hardware
  4. Day 4Optimizing Model Weights: Quantization Basics (GGUF, AWQ) for Efficient Inference
  5. Day 5Local AI Runtimes: Deploying Ollama and vLLM for Bare-Metal Execution
  6. Day 6Containerizing AI Microservices: Building and Packaging APIs with FastAPI
  7. Day 7Docker Compose: Architecting a Multi-Container Database and Inference Stack Locally

Week 2 · Kubernetes Foundation for MLOps

  1. Day 8K3d & Lightweight Kubernetes: Running Multi-Node Clusters on 16GB of RAM
  2. Day 9Kubernetes Core for Machine Learning: Pods, Deployments, and Headless Services
  3. Day 10Persistent Volumes (PV/PVC): Managing Heavy Model Weights and Vector Stores
  4. Day 11StatefulSets for Vector Databases: Deploying Milvus or Qdrant in Kubernetes
  5. Day 12Auto-Scaling AI Inference: Using Horizontal Pod Autoscalers (HPA) for Spiky API Traffic
  6. Day 13Helm Charts: Packaging, Versioning, and Updating AI Deployments
  7. Day 14Week 2 Capstone: Deploying a Highly Available Local AI Application on K3d

Week 3 · High-Performance Networking & Security Mesh

  1. Day 15AI Network Bottlenecks: Transitioning from iptables to eBPF
  2. Day 16Cilium & eBPF: Sub-Millisecond Routing for Heavy AI Microservices
  3. Day 17Service Mesh 101: Installing Istio over Your Local Cluster
  4. Day 18Envoy Proxy as an AI Gateway: Load Balancing and Terminating LLM Prompts
  5. Day 19Zero-Trust mTLS: Encrypting Traffic Between Autonomous Agents
  6. Day 20API Rate Limiting & Egress Control: Preventing Agents from Exfiltrating Data
  7. Day 21Distributed Tracing: Debugging Agent Workflows with Jaeger and OpenTelemetry

Week 4 · Enterprise Agents & CI/CD Workflows

  1. Day 22Introduction to MLOps: Bridging AI Development with Continuous Integration
  2. Day 23GitOps with ArgoCD: Automated, Self-Healing AI Deployments
  3. Day 24Building Ephemeral AI Sandboxes: Secure Execution Environments for Agent Code
  4. Day 25Multi-Agent Orchestration Frameworks: Exploring Mastra, LangGraph, and CrewAI
  5. Day 26Tool-Calling in Production: Connecting Agents Securely to Internal Databases
  6. Day 27MLOps Guardrails: Evaluating Agents and Preventing Hallucinations in Real-Time
  7. Day 28Continuous Training Pipelines: Connecting Data Ingestion to Automated Model Retraining
  8. Day 29Managing Technical Debt and Infrastructure Drift in Enterprise AI
  9. Day 30The AI-Native Platform: Scaling from a Sandbox Environment to Global Cloud Architecture
Open the course page →

Day 2: Advanced Docker for AI — Multi-Stage Builds for Heavy Python Runtimes

2026-11-08 · 9 min read

Containerising an AI workload is a different problem from containerising a web service. The dependencies are huge, the build tools are heavy, and an unoptimised image can pass 10 GB. Moving that across a registry slows every CI/CD run, and during a Kubernetes autoscale event each new pod must pull it before it can serve a single request.

The naive Dockerfile

This is the Dockerfile most teams start with.

FROM python:3.11
RUN apt-get update && apt-get install -y build-essential gcc
RUN pip install torch transformers fastapi uvicorn
COPY . /app
WORKDIR /app
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]

It works, and it has three production problems.

A NAIVE SINGLE-STAGE AI IMAGE (SIZES ILLUSTRATIVE)python:3.11 base≈ 1.0 GBapt: build-essential, gcc≈ 0.6 GBpip download cache + wheels≈ 2.0 GBtorch + transformers + CUDA libs≈ 4.0 GByour app codesmallTOTAL ≈ 7.7 GB shipped to every nodeThree problems follow:ACCUMULATIONcompilers, wheels and caches stay baked into read-only layersATTACK SURFACEgcc and build tools exist in productionLATENCYpulling gigabytes delays pod start and can time out requests
FIG 1 · A single-stage build carries compilers, caches and wheels into production. Layer sizes here are illustrative, not measured.
  • Build artifact accumulation. Compilers, intermediate wheels and pip caches are baked into read-only image layers and shipped everywhere.
  • Excessive attack surface. Development and compilation tools exist in production, which gives an attacker more to work with after a break-in.
  • Deployment latency. Pulling a large image can take minutes, which causes request timeouts while new pods start.

The multi-stage fix

Keep the build dependencies in an ephemeral builder stage. Copy only the compiled output into a minimal runtime stage.

ONE DOCKERFILE, TWO STAGESSTAGE 1 · builderFROM python:3.11-slimapt install build-essentialpython -m venv /opt/venvpip install -r requirements.txtheavy, temporary, discardedSTAGE 2 · runtimeFROM python:3.11-slimapt install libgomp1 onlyCOPY --from=builder /opt/venvUSER aiuser (non-root)small, clean, ships to productionvenvgcc, make, caches: left behind
FIG 2 · Dependencies are built in stage 1. Only the finished virtual environment is copied into the clean runtime stage; everything else is discarded.
# syntax=docker/dockerfile:1

# ---- Stage 1: builder (heavy, discarded) ----
FROM python:3.11-slim AS builder
WORKDIR /build
RUN apt-get update \
 && apt-get install -y --no-install-recommends build-essential curl \
 && rm -rf /var/lib/apt/lists/*
RUN python -m venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"
COPY requirements.txt .
RUN --mount=type=cache,target=/root/.cache/pip \
    pip install --no-cache-dir -r requirements.txt

# ---- Stage 2: runtime (small, ships to production) ----
FROM python:3.11-slim
WORKDIR /app
RUN apt-get update \
 && apt-get install -y --no-install-recommends libgomp1 \
 && rm -rf /var/lib/apt/lists/*
COPY --from=builder /opt/venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"
RUN useradd -m -u 10001 aiuser
USER aiuser
COPY --chown=aiuser:aiuser ./src /app
EXPOSE 8000
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]

Build it with BuildKit enabled, which current Docker versions use by default: docker build -t model-api:1.0 .. A few notes on this file:

  • The cache mount (--mount=type=cache) keeps pip's download cache outside the image, so repeat builds in CI do not re-download multi-gigabyte wheels. Because the cache is not in the layer, --no-cache-dir here only avoids writing a second copy.
  • libgomp1 is the OpenMP runtime that many numerical libraries need at run time. If your stack needs other shared libraries, install them in the runtime stage too, otherwise the app fails to start with a missing .so error.
  • If you need GPU support, use a CUDA-enabled base image for both stages, or install a CUDA build of PyTorch. That is the subject of Day 3.

Image hygiene checklist

WHAT EACH LINE BUYS YOURUN --mount=type=cache,target=/root/.cache/pip→ pip downloads survive between CI buildsapt-get install --no-install-recommends ... && rm -rf /var/lib/apt/lists/*→ no extra packages, no stale index, in ONE layerCOPY --from=builder /opt/venv /opt/venv→ only the finished environment movesRUN useradd -m -u 10001 aiuser + USER aiuser→ a container escape starts without root.dockerignore: .git .venv __pycache__ test data→ smaller build context, no secrets leaked
FIG 3 · Five small habits that keep AI images lean and safe. Do the apt cleanup in the same RUN command, or the deleted files still live in an earlier layer.
  1. Add a .dockerignore listing .git, .venv, __pycache__ and raw test data, so the build context stays small and secrets do not leak in.
  2. Run as a non-root user (USER aiuser).
  3. Clean package caches in the same RUN command that created them. Deleting files in a later layer does not shrink the image, because the earlier layer still holds them.
TIME TO PULL AN IMAGE ONTO A NEW NODE (AT 100 MB/s)Naive image ≈ 8 GB80 sMulti-stage ≈ 2.5 GB25 sArithmetic: 8,000 MB ÷ 100 MB/s = 80 s. 2,500 MB ÷ 100 MB/s = 25 s.During an autoscale event, every new pod pays this cost before it can serve.
FIG 4 · Smaller images start faster. The sizes and network speed are illustrative inputs to simple arithmetic, so measure your own registry and network.

Image size is not vanity. At 100 MB/s, an 8 GB image takes about 80 seconds to pull and a 2.5 GB one about 25 seconds, and during a scale-up every new node pays that cost. Lean, deterministic images turn research dependencies into a repeatable, auditable artifact that a cluster scheduler can start quickly.

Run it yourself

This is the exact example from the video. Both images are really built and measured with Docker. The 100 MB random file in the builder stage stands in for compilers and wheels, so the size gap is real but exaggerated on purpose.

# syntax=docker/dockerfile:1
# ---- builder: heavy, thrown away ----
FROM alpine:3.20 AS builder
WORKDIR /build
RUN dd if=/dev/urandom of=toolchain.bin bs=1M count=100
RUN echo "model-api v1" > app.txt

# ---- runtime: small, ships ----
FROM alpine:3.20
RUN adduser -D -u 10001 aiuser
USER aiuser
COPY --from=builder /build/app.txt /app/
CMD ["cat", "/app/app.txt"]

Helper file Dockerfile.naive, used by the run:

FROM alpine:3.20
WORKDIR /build
RUN dd if=/dev/urandom of=toolchain.bin bs=1M count=100
RUN echo "model-api v1" > app.txt
CMD ["cat", "/build/app.txt"]

Helper file compare.sh, used by the run:

set -e
docker build -q -f Dockerfile.naive -t d2naive . >/dev/null
docker build -q -t d2lean . >/dev/null
echo "naive image: $(( $(docker save d2naive | wc -c) / 1000000 )) MB"
echo "multi-stage: $(( $(docker save d2lean | wc -c) / 1000000 )) MB"
echo "app says: $(docker run --rm d2lean)"
echo "runs as uid: $(docker run --rm d2lean id -u)"
docker rmi d2naive d2lean >/dev/null

Run it:

bash compare.sh

Output I got while recording the video:

naive image: 108 MB
multi-stage: 3 MB
app says: model-api v1
runs as uid: 10001

Coming Up Next

Day 3: Hardware acceleration in Docker: configuring GPU passthrough and resource limits for constrained hardware.

#Docker #Containerization #DevOps #AIEngineering #FastAPI #CloudNative #PlatformEngineering #CyberSecurity