Loading
Loading
A Dockerfile is a text file containing step-by-step instructions for building a Docker Image.
# Base image
FROM python:3.11-slim
# Working directory inside the container
WORKDIR /app
# Copy requirements first (for caching)
COPY requirements.txt .
# Install dependencies
RUN pip install --no-cache-dir -r requirements.txt
# Copy the rest of the code
COPY . .
# Define environment variable
ENV PORT=8000
ENV PYTHONUNBUFFERED=1
# Port the app listens on
EXPOSE 8000
# Default command to run the application
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
Like .gitignore but for Docker ā prevents copying unnecessary files:
__pycache__/
*.pyc
.env
.git/
tests/
*.log
venv/
.venv/
# Build the image
docker build -t my-ai-app:v1 .
# Run the container
docker run -p 8080:8000 my-ai-app:v1
docker run -d -p 8080:8000 --name ai-api my-ai-app:v1 # in background
# Pass environment variables
docker run -d -p 8080:8000 \
-e ANTHROPIC_API_KEY=sk-ant-... \
--name ai-api my-ai-app:v1
Significantly reduces the final image size:
# Build stage
FROM python:3.11 AS builder
WORKDIR /build
COPY requirements.txt .
RUN pip install --user -r requirements.txt
# Production stage (smaller)
FROM python:3.11-slim AS production
WORKDIR /app
COPY --from=builder /root/.local /root/.local
COPY . .
ENV PATH=/root/.local/bin:$PATH
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
&& to reduce layers# ŲØŁŲ§Ų” Dockerfile ā Python Generator + Simulator
# Dockerfile Builder and Build Simulator
from dataclasses import dataclass, field
from typing import Optional
import time
@dataclass
class DockerfileInstruction:
instruction: str
args: str
comment: str = ""
class DockerfileBuilder:
"""ŲØŁŲ§Ų” Dockerfile ŲØŲ±Ł
Ų¬ŁŲ§Ł"""
def __init__(self):
self.instructions: list[DockerfileInstruction] = []
def FROM(self, image: str, alias: str = "") -> "DockerfileBuilder":
args = f"{image} AS {alias}" if alias else image
return self._add("FROM", args, "Ų§ŁŲµŁŲ±Ų© Ų§ŁŲ£Ų³Ų§Ų³ŁŲ©")
def WORKDIR(self, path: str) -> "DockerfileBuilder":
return self._add("WORKDIR", path, "Ł
Ų¬ŁŲÆ Ų§ŁŲ¹Ł
Ł")
def COPY(self, src: str, dst: str) -> "DockerfileBuilder":
return self._add("COPY", f"{src} {dst}")
def RUN(self, cmd: str, comment: str = "") -> "DockerfileBuilder":
return self._add("RUN", cmd, comment)
def ENV(self, key: str, value: str) -> "DockerfileBuilder":
return self._add("ENV", f"{key}={value}")
def EXPOSE(self, port: int) -> "DockerfileBuilder":
return self._add("EXPOSE", str(port), "Ų§ŁŁ
ŁŁŲ° Ų§ŁŁ
ŁŲ“ŁŁ")
def CMD(self, *args: str) -> "DockerfileBuilder":
cmd_json = '["' + '", "'.join(args) + '"]'
return self._add("CMD", cmd_json)
def _add(self, instruction: str, args: str, comment: str = "") -> "DockerfileBuilder":
self.instructions.append(DockerfileInstruction(instruction, args, comment))
return self
def build(self) -> str:
lines = []
for instr in self.instructions:
if instr.comment:
lines.append(f"# {instr.comment}")
lines.append(f"{instr.instruction} {instr.args}")
lines.append("")
return "\n".join(lines).strip()
class BuildSimulator:
"""Ł
ŲŲ§ŁŲ§Ų© docker build"""
def __init__(self, tag: str):
self.tag = tag
self.layer_sizes: list[int] = []
def execute(self, dockerfile_content: str) -> dict:
print(f"\nšØ Building {self.tag}...")
print("ā"*55)
total_size = 0
steps = []
for i, line in enumerate(dockerfile_content.split("\n")):
line = line.strip()
if not line or line.startswith("#"):
continue
parts = line.split(None, 1)
instruction = parts[0]
args = parts[1] if len(parts) > 1 else ""
size_mb = {"FROM": 130, "RUN": 25, "COPY": 5, "ENV": 0, "EXPOSE": 0, "CMD": 0}.get(instruction, 2)
total_size += size_mb
steps.append({"step": i+1, "instruction": instruction, "size": size_mb})
time.sleep(0.1)
size_str = f"+{size_mb}MB" if size_mb > 0 else "cached"
print(f" Step {len(steps)}/{6}: {instruction:<10} [{size_str}] ā
")
print(f"\n ā
Successfully built {self.tag}")
print(f" š¦ Image size: ~{total_size}MB")
return {"tag": self.tag, "size_mb": total_size, "layers": len(steps)}
# āāā ŲØŁŲ§Ų” Dockerfile ŁŲŖŲ·ŲØŁŁ AI āāāāāāāāāāāāāāāāāāāāāāāāāāāā
print("š³ Dockerfile Builder ā AI App")
print("="*55)
# ŲØŁŲ§Ų” Dockerfile ŲØŲ±Ł
Ų¬ŁŲ§Ł
df = (
DockerfileBuilder()
.FROM("python:3.11-slim")
.WORKDIR("/app")
.COPY("requirements.txt", ".")
.RUN("pip install --no-cache-dir -r requirements.txt", "ŲŖŲ«ŲØŁŲŖ Ų§ŁŁ
ŲŖŲ·ŁŲØŲ§ŲŖ")
.COPY(".", ".")
.ENV("PYTHONUNBUFFERED", "1")
.ENV("PORT", "8000")
.EXPOSE(8000)
.CMD("uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000")
)
dockerfile_content = df.build()
print("\nš Dockerfile Ų§ŁŁ
ŁŁŁŁŁŲÆ:")
print("ā"*55)
for line in dockerfile_content.split("\n"):
prefix = " "
if line.startswith("#"):
print(f"{prefix}\033[90m{line}\033[0m")
else:
print(f"{prefix}{line}")
# āāā Ł
ŲŲ§ŁŲ§Ų© Ų§ŁŲØŁŲ§Ų” āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
simulator = BuildSimulator("my-ai-app:v1")
result = simulator.execute(dockerfile_content)
# āāā Ł
ŁŲ§Ų±ŁŲ© Base Images āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
print(f"\n{'='*55}")
print("š Ł
ŁŲ§Ų±ŁŲ© Base Images:")
print(f"{'Image':<25} {'Ų§ŁŲŲ¬Ł
':>8} {'Ų§ŁŲ§Ų³ŲŖŲ®ŲÆŲ§Ł
'}")
print("ā"*55)
images = [
("ubuntu:22.04", "77MB", "ŲŖŲ·ŁŁŲ± Ų¹Ų§Ł
"),
("debian:bookworm", "117MB", "Ų§Ų³ŲŖŁŲ±Ų§Ų± Ų¹Ų§ŁŁ"),
("python:3.11", "1.0GB", "ŁŲ§Ł
Ł + dev tools"),
("python:3.11-slim", "130MB", "ā
Ł
ŁŲ§Ų³ŲØ ŁŁŲ„ŁŲŖŲ§Ų¬"),
("python:3.11-alpine", "55MB", "Ų£ŲµŲŗŲ± ā ŲØŲ¹Ų¶ Ų§ŁŁŁŁŲÆ"),
]
for name, size, use in images:
print(f" {name:<25} {size:>8} {use}")
print(f"\nš” ŁŁŁ AI APIs: python:3.11-slim ŁŁ Ų§ŁŲ§Ų®ŲŖŁŲ§Ų± Ų§ŁŁ
Ų«Ų§ŁŁ")
print(f" Ų§ŁŲŲ¬Ł
: ~130MB + Ł
ŁŲŖŲØŲ§ŲŖŁ (~50MB) = ~180MB ŁŁŲ·")
# āāā .dockerignore āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
print(f"\nš .dockerignore Ų§ŁŁ
ŁŲµŁ ŲØŁ ŁŁ
Ų“Ų§Ų±ŁŲ¹ AI:")
dockerignore = """__pycache__/
*.pyc *.pyo *.pyd
.env .env.*
.git/ .github/
tests/ docs/
*.log *.md
venv/ .venv/
.pytest_cache/
*.ipynb"""
for line in dockerignore.strip().split("\n"):
print(f" {line}")