Dockerize a Claude API Python App

Step-by-step Dockerfile and Docker Compose setup for containerizing Claude API Python applications in 2026. Covers secret injection, multi-stage builds, and health checks.

💥 50p impulse-buy: Power Prompts PDF (first 10 buyers) 30 battle-tested Claude Code prompts · 8-page PDF · paste into CLAUDE.md and never re-type a prompt again · 50p impulse-buy, no commitment

Containerizing a Claude API application lets you deploy it consistently across dev, staging, and production. The main challenge is injecting the API key securely without baking it into the image. This guide covers the complete production Dockerfile pattern.

Project structure

my-claude-app/
├── app.py
├── requirements.txt
├── Dockerfile
├── .dockerignore
└── docker-compose.yml

requirements.txt

anthropic>=0.50.0
fastapi>=0.115.0
uvicorn[standard]>=0.32.0

app.py (FastAPI + Claude)

import anthropic
from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()
client = anthropic.Anthropic()  # reads ANTHROPIC_API_KEY from env

class AskRequest(BaseModel):
    prompt: str
    max_tokens: int = 512

@app.get("/health")
def health():
    return {"status": "ok"}

@app.post("/ask")
def ask(req: AskRequest):
    message = client.messages.create(
        model="claude-sonnet-4-6",
        max_tokens=req.max_tokens,
        messages=[{"role": "user", "content": req.prompt}]
    )
    return {
        "text": message.content[0].text,
        "input_tokens": message.usage.input_tokens,
        "output_tokens": message.usage.output_tokens,
    }

Dockerfile (multi-stage, slim)

# ── Stage 1: build deps ──────────────────────────────────────
FROM python:3.12-slim AS builder

WORKDIR /build
COPY requirements.txt .
RUN pip install --no-cache-dir --prefix=/install -r requirements.txt

# ── Stage 2: runtime image ───────────────────────────────────
FROM python:3.12-slim

ENV PYTHONUNBUFFERED=1     PYTHONDONTWRITEBYTECODE=1

WORKDIR /app
COPY --from=builder /install /usr/local
COPY app.py .

# Health check — pings /health without touching Claude
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3   CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8000/health')"

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

.dockerignore

.env
.git
__pycache__
*.pyc
*.pyo
.pytest_cache

Build and run

# Build
docker build -t my-claude-app .

# Run — inject key at runtime, never bake into image
docker run -p 8000:8000   -e ANTHROPIC_API_KEY="$ANTHROPIC_API_KEY"   my-claude-app

# Test
curl -X POST http://localhost:8000/ask   -H "Content-Type: application/json"   -d '{"prompt": "What is prompt caching?"}'

docker-compose.yml (with optional Redis cache)

version: "3.9"

services:
  claude-app:
    build: .
    ports:
      - "8000:8000"
    env_file: .env            # ANTHROPIC_API_KEY lives here
    environment:
      REDIS_URL: redis://redis:6379
    depends_on:
      redis:
        condition: service_healthy
    restart: unless-stopped

  redis:
    image: redis:7-alpine
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 3s
      retries: 3

Deployment comparison

PlatformDocker supportSecret injectionCold start
Google Cloud RunNativeSecret Manager --set-secrets~1s (min-instances=0)
AWS ECS / FargateNativeSecrets Manager task def ref~10s
Fly.ioNativefly secrets set ANTHROPIC_API_KEY=...~0.5s
RailwayAuto-detect DockerfileVariables UI~2s
VercelNo (serverless only)Environment UI~200ms

For per-model pricing to estimate container compute costs vs API costs, use the Claude API Cost Calculator. For Cloud Run deployment specifics, see the Google Cloud Run guide.

Frequently asked questions

How do I pass the ANTHROPIC_API_KEY to a Docker container?
Use an environment variable at runtime: `docker run -e ANTHROPIC_API_KEY=$ANTHROPIC_API_KEY myimage`. Never bake the key into the image with ENV in the Dockerfile — it becomes visible in `docker inspect` and image layer history.
What base image should I use for a Claude API Python app?
Use `python:3.12-slim` for production — it's 60 MB vs 1 GB for the full image. Add `--no-cache-dir` to pip install and multi-stage builds to keep the final image under 200 MB.
How do I stream Claude API responses in a Docker container?
Streaming works the same inside Docker — the Anthropic SDK uses standard HTTP chunked encoding. Ensure the container's stdout is unbuffered (`PYTHONUNBUFFERED=1`) so logs appear in real time.
How do I run a Claude API app with Docker Compose?
Define a `claude-app` service with `env_file: .env` (where ANTHROPIC_API_KEY lives) and `depends_on: redis` if you're using a cache. Avoid hardcoding the key in `docker-compose.yml` — use `.env` or `${ANTHROPIC_API_KEY}`.
How do I health-check a Claude API container in production?
Add `HEALTHCHECK CMD curl -f http://localhost:8000/health || exit 1` to the Dockerfile. The `/health` endpoint should return 200 without calling Claude — it just verifies the app process is alive.

Free tools

Cost Calculator → API Cookbook → Diff Summarizer → Skills Browser →

More examples

Claude API Python QuickstartClaude API Node.js / TypeScript QuickstartClaude API Streaming in PythonClaude API Streaming in Node.js / TypeScriptClaude API Tool Use in PythonClaude API Tool Use in Node.js / TypeScript