Loading
Loading
Dockerfile هو ملف نصي يحتوي على تعليمات لبناء Docker Image خطوة بخطوة.
# الصورة الأساسية
FROM python:3.11-slim
# مجلد العمل داخل الـ Container
WORKDIR /app
# نسخ ملفات المتطلبات أولاً (caching)
COPY requirements.txt .
# تثبيت المتطلبات
RUN pip install --no-cache-dir -r requirements.txt
# نسخ باقي الكود
COPY . .
# تعريف متغير بيئة
ENV PORT=8000
ENV PYTHONUNBUFFERED=1
# Port الذي يستمع عليه التطبيق
EXPOSE 8000
# الأمر الافتراضي لتشغيل التطبيق
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
مثل .gitignore لكن لـ Docker — يمنع نسخ ملفات غير ضرورية:
__pycache__/
*.pyc
*.pyo
.env
.git/
.github/
tests/
*.log
node_modules/
venv/
.venv/
# بناء الـ Image
docker build -t my-ai-app:v1 .
docker build -t my-ai-app:v1 -f Dockerfile.prod . # ملف Dockerfile آخر
# تشغيل الـ Container
docker run -p 8080:8000 my-ai-app:v1
docker run -d -p 8080:8000 --name ai-api my-ai-app:v1 # في الخلفية
# تمرير متغيرات البيئة
docker run -d -p 8080:8000 \
-e ANTHROPIC_API_KEY=sk-ant-... \
--name ai-api my-ai-app:v1
# أو استخدام ملف .env
docker run -d -p 8080:8000 \
--env-file .env \
--name ai-api my-ai-app:v1
يقلل حجم الـ Image النهائي بشكل كبير:
# مرحلة البناء
FROM python:3.11 AS builder
WORKDIR /build
COPY requirements.txt .
RUN pip install --user -r requirements.txt
# مرحلة الإنتاج (أصغر حجماً)
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"]
&& لتقليل عدد الطبقات# بناء 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}")