الدرس 5 من 8

Docker

الطريقة الموحدة عشان كودك يشتغل في أي مكان بنفس الشكل.

المشكلة

الكود شغال عندك. على السيرفر: نسخة بايثون مختلفة، ومكتبة ناقصة، ونظام تشغيل تاني، فمبيشتغلش. Docker بيحل ده: بتحط الكود ومعاه بايثون والمكتبات وكل حاجة محتاجها في صندوق واحد اسمه container، والصندوق ده بيشتغل بنفس الشكل بالظبط على أي جهاز.

🚢 زي كونتينر الشحنقبل الكونتينرات، كل بضاعة كان ليها طريقة تحميل مختلفة. الكونتينر وحّد الشكل: أي سفينة وأي ميناء وأي عربية نقل بتتعامل معاه بنفس الطريقة، مهما كان جواه إيه.
Dockerfile وصفة بتقول الصندوق يتبني إزاي، خطوة خطوة.
image الصندوق بعد ما اتبنى، زي الـ class. ثابت وممكن تنقله.
container نسخة شغالة من الـ image، زي الـ object.
registry مكان بتخزن فيه الـ images وتشاركها، زي Docker Hub.

الـ Dockerfile

Dockerfile
# 1. Start from an official Python image
FROM python:3.12-slim

# 2. Work inside /app in the container
WORKDIR /app

# 3. Install dependencies first (cached if requirements.txt didn't change)
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# 4. Copy the code and the trained model
COPY price_api.py price_model.joblib ./

# 5. Document the port and define the start command
EXPOSE 8000
CMD ["fastapi", "run", "price_api.py", "--port", "8000"]
💡 ليه نسخنا requirements.txt لوحده الأول؟Docker بيبني طبقات وبيحتفظ بيها. لو غيرت الكود بس، مش هيعيد تسطيب المكتبات (اللي بياخد دقايق)، هيكمل من الطبقة المتخزنة. ترتيب الخطوات بيوفرلك وقت كتير.
.dockerignore
venv/
__pycache__/
.env
*.ipynb
data/

ابني وشغّل

terminal
# Build an image named price-api
docker build -t price-api .

# Run it: map port 8000 on your machine to 8000 in the container
docker run -p 8000:8000 price-api

# Now http://localhost:8000/docs works — from inside a container!

# Pass secrets as environment variables, never inside the image
docker run -p 8000:8000 --env-file .env price-api

كذا خدمة مع بعض: Docker Compose

لو عندك API وواجهة وقاعدة بيانات، بدل ما تشغل كل واحد بإيدك، بتوصفهم في ملف واحد وتشغلهم كلهم بأمر واحد:

compose.yaml
services:
  api:
    build: .
    ports:
      - "8000:8000"
    env_file: .env
  ui:
    build: ./ui
    ports:
      - "8501:8501"
    environment:
      - API_URL=http://api:8000      # services find each other by name
    depends_on:
      - api
terminal
docker compose up --build
⚠ الـ image مش مكان للأسرارأي حاجة بتعملها COPY جوه الـ image أي حد معاه الـ image يقدر يطلّعها. عشان كده .env في الـ .dockerignore، والأسرار بتدخل وقت التشغيل بـ --env-file أو secrets المنصة.
الدرس اللي فات