למה ה-Dockerfile שלך הוא חור אבטחה מהלך
ב-2025 נפרצו קונטיינרים ב-47% יותר מהשנה הקודמת. שלושת הגורמים המובילים: base image פגיע (32%), הרצה כ-root (28%), secrets hardcoded בתוך ה-image (12%). כל אחת מהבעיות האלה ניתנת למניעה ב-Dockerfile, אם יודעים לכתוב אותו נכון. רוב הדוגמאות באינטרנט לא יודעות.
צוות DevOps של סטארטאפ ישראלי בתחום הפינטק גילה שה-Docker image שלהם שוקל 1.2GB, רץ כ-root, ויש בו 47 critical CVEs. כל deploy ל-ECS לקח 8 דקות. עם Claude Sonnet 4.6, ב-20 דקות הם כתבו Dockerfile חדש: 87MB, non-root user, אפס critical CVEs, deploy בדקה וחצי.
עדכון 2025: Docker Hardened Images חינמיים
בדצמבר 2025 Docker שחררה 1,000+ Hardened Images (DHI) בחינם תחת Apache 2.0. אלה images שנבנו במיוחד לאבטחה, stripped מרכיבים מיותרים, pre-scanned לפני release, ומתעדכנים אוטומטית. הם מפחיתים CVEs ב-95% לעומת community images. זמינים ב-dhi.io ו-Docker Hub.
השינוי הזה חשוב: אם distroless נראה לכם מסובך מדי (אין shell, קשה לדיבוג), DHI הוא האלטרנטיבה הבוגרת. Claude מכיר את שניהם ויבחר את הנכון לפרויקט שלכם.
פרומפט 1: Dockerfile מאפס, production-ready
זה הפרומפט שצריך לשנן. תנו לו לעבוד:
אתה מומחה Docker אבטחה וביצועים.
כתוב Dockerfile production-ready ל-Node.js 20 API:
אבטחה:
- Multi-stage build (builder + production stages)
- Non-root user: uid 1001, שם appuser
- Minimal base image: distroless או DHI
- אין secrets hardcoded
- .dockerignore מלא
ביצועים:
- pnpm install ב-builder stage בלבד
- Layer caching: COPY package.json לפני COPY src
- Image קטן מ-120MB
Runtime:
- HEALTHCHECK: GET /health, interval 30s, timeout 5s
- WORKDIR /app
- signal handling נכון (node ישירות, לא npm start)
- EXPOSE 3000
כתוב גם: .dockerignore מלא ו-docker-compose.yml לפיתוח.
למה כל שורה חשובה:
- "Multi-stage build", Claude יוסיף שני FROM blocks. הbuilder stage בונה. ה-production stage רץ. dev-dependencies לא נכנסות ל-production.
- "Non-root user uid 1001", UID ספציפי מונע collision עם host UIDs. Claude יוסיף RUN useradd וUSER בסדר הנכון.
- "COPY package.json לפני COPY src", Docker caches לפי שינויים בקבצים. אם package.json לא השתנה, שכבת npm install תהיה cached. חוסך 2-4 דקות בכל build.
- "node ישירות, לא npm start", npm start מריץ תהליך npm שמריץ node. כשה-orchestrator שולח SIGTERM, npm בולע אותו. graceful shutdown לא קורה.
פרומפט 2: סריקת אבטחה על Dockerfile קיים
יש לכם Dockerfile ישן? זה הפרומפט שיפרק אותו:
סקן את ה-Dockerfile הזה לבעיות אבטחה וביצועים:
[הדבק את ה-Dockerfile שלך כאן]
עבור כל בעיה:
1. תאר את הבעיה במדויק
2. דרג חומרה: Critical / High / Medium / Low
3. הסבר את ה-attack scenario, מה תוקף יכול לעשות
4. כתוב את הקוד המתוקן
בסוף: כתוב את ה-Dockerfile המלא לאחר כל התיקונים.
המשפט "attack scenario" גורם ל-Claude להסביר למה הבעיה מסוכנת, לא רק לרשום אותה. זה שימושי לשכנע צוות לתקן. המשפט "Dockerfile המלא" מונע קבלת רשימה שצריך לממש ידנית.
multi-stage build, השוואה מספרית
| פרמטר | Single-stage | Multi-stage |
|---|---|---|
| גודל image | 800MB-1.5GB | 80-150MB |
| CVEs אופייניים | 40-100+ (כולל build tools) | 0-5 (runtime only) |
| attack surface | גבוה (gcc, curl, git...) | מינימלי (רק node runtime) |
| deploy time (ECR/GCR) | 6-10 דקות | 1-2 דקות |
טעויות נפוצות, ואיך Claude עוזר להימנע מהן
- COPY . . לפני npm install: הטעות הקלאסית. שינוי בכל קובץ קוד מבטל את cache של npm install ומריץ אותו מחדש. תמיד COPY package*.json קודם, אחר כך RUN npm ci, ורק אחר כך COPY . .
- FROM node:latest: latest פירושו build שונה כל שבוע. פרויקט שעבד היום לא מובטח שיעבוד בעוד חודש. תמיד pin לגרסה מדויקת: node:20.11.0-alpine3.19.
- Secrets ב-ARG או ENV: ARG API_KEY ו-ENV DB_PASSWORD נשמרים בתוך ה-image layers לנצח, גלויים ב-docker history. השתמשו ב-Docker secrets (production) או ב-runtime environment variables בלבד.
- אין HEALTHCHECK: orchestrator כמו Kubernetes לא יודע שה-container קרס אם אין HEALTHCHECK. הוא ימשיך לשלוח תעבורה לcontainer מת.
workflow מומלץ עם Claude
השתמשו ב-Claude Opus 4.7 פעם אחת כדי לכתוב Dockerfile template מושלם לה-stack שלכם, ושמרו אותו כ-.github/templates/Dockerfile. בכל פרויקט חדש, תנו ל-Sonnet 4.6 לאדפט את ה-template לצרכים הספציפיים, מהיר ועקבי. הוסיפו step ב-CI שמריץ trivy scan ומעביר את הפלט ל-Claude לניתוח:
# ב-.github/workflows/docker.yml
- name: Scan image
run: trivy image myapp:latest --format json > trivy-results.json
# אחר כך שלחו את trivy-results.json לClaude:
# "נתח את תוצאות הסריקה האלה. עבור כל CVE: מה חומרתו,
# האם הוא exploitable, ואיך לתקן אותו. עדיפות: Critical ראשון."
