# Dockerfile — בניית Image משלכם📖 שיעור

## מה זה?

בשיעור הקודם השתמשנו ב-Images מוכנים (`nginx`, `hello-world`) — אבל איך אורזים את ה-Task Manager API שלכם עצמכם? Dockerfile הוא "מתכון" — קובץ טקסט עם הוראות שלב-אחר-שלב שמתאר איך לבנות Image מותאם לאפליקציה שלכם: איזה runtime בסיס, אילו קבצים להעתיק, אילו פקודות להריץ כדי להכין את הכל.

## מילות מפתח שחשוב לזכור

• Dockerfile — קובץ טקסט עם הוראות שלב-אחר-שלב לבניית Image מותאם אישית

• `FROM` — קובע את ה-Base Image שעליו בונים (למשל `mcr.microsoft.com/dotnet/sdk:8.0`) — נקודת ההתחלה, לא בונים "משום מקום"

• `COPY` — מעתיק קבצים מהמחשב (קוד המקור) אל תוך ה-Image

• `RUN` — מריץ פקודה **בזמן בניית ה-Image** (למשל `dotnet restore`/`dotnet build`)

• `docker build` — הפקודה שקוראת את ה-Dockerfile ובונה ממנו Image בפועל

```dockerfile
# Dockerfile — building an Image for an ASP.NET Core API
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /app

COPY *.csproj .
RUN dotnet restore          # pulls NuGet packages — before COPY of the rest of the code, to leverage the Cache

COPY . .
RUN dotnet publish -c Release -o /out

FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS runtime
WORKDIR /app
COPY --from=build /out .

EXPOSE 80
ENTRYPOINT ["dotnet", "TaskManager.dll"]   # the run command when the container starts
```

```bash
# Build the Image from the Dockerfile
docker build -t task-manager-api .

# Run a Container from the built Image
docker run -p 8080:80 task-manager-api
```

## הסבר עיקרי

`FROM` תמיד מתחיל מ-Base Image קיים — אין "בנייה מאפס" — `FROM mcr.microsoft.com/dotnet/sdk:8.0` אומר "התחל מ-Image שכבר מכיל .NET SDK מותקן". זה חוסך התקנה ידנית של כל התלויות הבסיסיות — בדיוק כמו ירושה מיחידת ה-OOP: יורשים "בחינם" את כל מה שכבר קיים ב-Base Image, ומוסיפים רק את מה שספציפי לפרויקט.

Multi-Stage Build (שתי `FROM` בדוגמה) — שלב ראשון (`build`) מכיל את כל כלי הפיתוח (SDK מלא, כבד) כדי לקמפל את הקוד; שלב שני (`runtime`) מתחיל מ-Image קטן יותר (`aspnet` בלבד, בלי כלי פיתוח) ומעתיק **רק** את התוצר המקומפל מהשלב הראשון (`COPY --from=build`). ה-Image הסופי קטן משמעותית — לא כולל כלי בנייה שלא נחוצים בזמן ריצה.

סדר `COPY` משפיע על מהירות Build — העתקת `*.csproj` ו-`dotnet restore` **לפני** העתקת שאר הקוד (`COPY . .`) מנצלת את מנגנון ה-Cache של Docker: אם רק קוד השתנה (לא התלויות ב-`.csproj`), Docker משתמש מחדש בתוצאת ה-`restore` הקודמת במקום להוריד הכל שוב — Build מהיר משמעותית.

## יתרונות

Dockerfile הוא תיעוד חי ומדויק של איך לבנות את הסביבה — לא הוראות "תלויות" בראש של מישהו; Multi-Stage Build מקטין Image סופי משמעותית; ניצול Cache נכון מאיץ Build חוזרים בפיתוח יומיומי.

## חסרונות

Dockerfile לא מתוכנן היטב (סדר COPY שגוי) מבזבז זמן Build מיותר על כל שינוי; Multi-Stage Build מוסיף מורכבות תחבירית שדורשת הבנה של שני שלבים נפרדים.

## נקודות חשובות

• `FROM` קובע Base Image — תמיד מתחילים ממשהו קיים, לא מאפס

• `COPY` מעתיק קבצים ל-Image; `RUN` מריץ פקודה בזמן הבנייה

• Multi-Stage Build מפריד שלב-בנייה (כבד) משלב-ריצה (קליל) — Image סופי קטן יותר

• סדר COPY משפיע על ניצול Cache — קבצי תלויות לפני קוד מלא

## טעויות נפוצות

• להעתיק את כל הקוד (`COPY . .`) לפני `dotnet restore` — מבטל את יתרון ה-Cache על כל שינוי קטן בקוד

• לשכוח `EXPOSE`/מיפוי פורט תואם, ולתהות למה השרת לא נגיש מבחוץ

• לבנות Image "שמן" ללא Multi-Stage — כולל כלי פיתוח מיותרים בזמן ריצה בפועל

## סיכום

Dockerfile הוא מתכון שלב-אחר-שלב לבניית Image מותאם: `FROM` קובע Base Image, `COPY` מעתיק קבצים, `RUN` מריץ פקודות בזמן הבנייה. Multi-Stage Build מפריד שלב-בנייה כבד (SDK מלא) משלב-ריצה קליל (runtime בלבד), ומקטין את ה-Image הסופי משמעותית. סדר נכון של `COPY` (תלויות לפני קוד מלא) מנצל את מנגנון ה-Cache של Docker ומאיץ בנייה חוזרת.

## דוקומנטציה רשמית

[Docker — Dockerfile reference](https://docs.docker.com/reference/dockerfile/)

[Microsoft Learn — Containerize a .NET app](https://learn.microsoft.com/dotnet/core/docker/build-container)

---

## תרגילים

### תרגיל 1 — Dockerfile ראשון

**המשימה:** כתבו Dockerfile בסיסי (בלי Multi-Stage) לפרויקט ASP.NET Core פשוט, ובנו אותו עם `docker build -t my-app .`.

**בדיקה:** `docker build` מסתיים בהצלחה; `docker run -p 8080:80 my-app` מריץ את השרת בפועל, נגיש דרך הדפדפן.

### תרגיל 2 — Multi-Stage Build

**המשימה:** שדרגו את ה-Dockerfile מתרגיל 1 ל-Multi-Stage (שלב build + שלב runtime נפרדים), והשוו את גודל ה-Image לפני ואחרי (`docker images`).

**בדיקה:** ה-Image אחרי Multi-Stage קטן משמעותית מהגרסה הראשונה, והאפליקציה ממשיכה לרוץ זהה.

---

## פרויקט מסכם

**המשימה:** כתבו Dockerfile מלא ל-Task Manager API (מהפרויקטים המסכמים הקודמים), עם Multi-Stage Build מלא.

**דרישות:**
1. שלב `build` מבוסס `sdk`, כולל `restore` לפני `COPY` מלא (ניצול Cache)
2. שלב `runtime` מבוסס `aspnet` בלבד, מעתיק רק את התוצר המקומפל
3. `docker build` + `docker run` מצליחים, וה-API נגיש ועובד באמצעות `curl`/Postman מהמחשב המארח

**בדיקה:** ה-Image הסופי (`docker images`) קטן משמעותית מגרסה בלי Multi-Stage; כל endpoints ה-API עונים נכון דרך הקונטיינר הרץ.

## מה בפרק הבא

בפרק הבא — **הרצת קונטיינרים וניהול בסיסי**: פקודות ניהול יומיומיות (לוגים, כניסה לקונטיינר רץ, ניקוי), כהכנה לעבודה עם כמה קונטיינרים יחד ביחידות הבאות.
