أمان التبعيات والحاويات
تقوية الصور الأساسية والحاويات بدون توزيعة
3 دقيقة للقراءة
الطريقة الأكثر فعالية لتقليل ثغرات الحاويات هي تقليل ما بداخلها. برمجيات أقل = ثغرات أقل = سطح هجوم أصغر.
مشكلة الصور القياسية
صورة node:20 نموذجية تحتوي على:
node:20 (قائمة على debian)
├── بيئة تشغيل Node.js
├── npm/yarn
├── Bash shell
├── مدير حزم apt
├── curl, wget
├── مترجم gcc
├── Python (أدوات البناء)
└── 400+ ميغابايت من حزم النظام
النتيجة: 200-500 CVE، معظمها غير مرتبط بتطبيقك.
مقارنة حجم الصور
| الصورة الأساسية | الحجم | CVEs النموذجية |
|---|---|---|
node:20 |
1.1 غيغابايت | 200-500 |
node:20-slim |
250 ميغابايت | 50-150 |
node:20-alpine |
140 ميغابايت | 10-50 |
gcr.io/distroless/nodejs20 |
130 ميغابايت | 0-10 |
scratch + ثنائي ثابت |
~10 ميغابايت | 0 |
استراتيجية التقوية 1: صور Alpine
Alpine Linux يستخدم musl libc بدلاً من glibc، مما ينتج صوراً صغيرة:
# بدلاً من node:20
FROM node:20-alpine
# تثبيت فقط ما تحتاجه
RUN apk add --no-cache dumb-init
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
# التشغيل كغير root
USER node
CMD ["dumb-init", "node", "server.js"]
الإيجابيات: صغيرة، CVEs أقل، دعم واسع السلبيات: بعض حزم npm تفشل (الروابط الأصلية تتوقع glibc)
استراتيجية التقوية 2: صور Distroless
صور Distroless تحتوي فقط على تطبيقك وتبعيات وقت التشغيل—بدون shell، بدون مدير حزم، بدون إضافات.
# مرحلة البناء
FROM node:20 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# مرحلة الإنتاج - distroless
FROM gcr.io/distroless/nodejs20-debian12
WORKDIR /app
COPY /app/dist ./dist
COPY /app/node_modules ./node_modules
CMD ["dist/server.js"]
صور distroless المتاحة:
gcr.io/distroless/static- للثنائيات المجمعة ثابتياً (Go، Rust)gcr.io/distroless/base- glibc للثنائيات المرتبطة ديناميكياًgcr.io/distroless/nodejs20- بيئة تشغيل Node.jsgcr.io/distroless/python3- بيئة تشغيل Pythongcr.io/distroless/java21- بيئة تشغيل Java
استراتيجية التقوية 3: بناء متعدد المراحل
فصل تبعيات وقت البناء عن وقت التشغيل:
# المرحلة 1: البناء
FROM golang:1.22 AS builder
WORKDIR /app
COPY go.* ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o /server
# المرحلة 2: وقت التشغيل (scratch = صورة فارغة)
FROM scratch
COPY /server /server
COPY /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
EXPOSE 8080
ENTRYPOINT ["/server"]
قائمة التحقق من أفضل الممارسات الأمنية
# 1. تثبيت إصدارات محددة (ليس :latest)
FROM node:20.10.0-alpine3.19
# 2. إنشاء مستخدم غير root
RUN addgroup -g 1001 appgroup && \
adduser -u 1001 -G appgroup -D appuser
# 3. تعيين الملكية
COPY . .
# 4. إسقاط جميع الصلاحيات
USER appuser
# 5. استخدام نظام ملفات للقراءة فقط (عند التشغيل)
# docker run --read-only my-app
# 6. لا صلاحيات جديدة
# docker run --security-opt=no-new-privileges my-app
# 7. فحص الصحة
HEALTHCHECK \
CMD wget -q --spider http://localhost:8080/health || exit 1
فحص الصور المقواة
قارن قبل وبعد:
# قبل (الصورة القياسية)
trivy image node:20
# Total: 487 (HIGH: 42, CRITICAL: 8)
# بعد (distroless)
trivy image gcr.io/distroless/nodejs20
# Total: 3 (HIGH: 0, CRITICAL: 0)
صور Chainguard
Chainguard يوفر صوراً مقواة مع SBOM:
# Chainguard Node.js (صفر CVEs)
FROM cgr.dev/chainguard/node:latest
| الميزة | Distroless | Chainguard |
|---|---|---|
| صفر CVEs | غالباً | مضمون |
| SBOM مضمن | لا | نعم |
| صور موقعة | لا | نعم (Sigstore) |
| الدعم | مجتمعي | تجاري |
النقاط الرئيسية
- ابدأ صغيراً: استخدم
-alpine،-slim، أو distroless - بناء متعدد المراحل: افصل البناء عن وقت التشغيل
- ثبت الإصدارات: لا تستخدم
:latestفي الإنتاج أبداً - شغّل كغير root: حدد USER دائماً
- افحص بانتظام: CVEs تظهر في الصور الأساسية يومياً
في الوحدة التالية، سنستكشف الاختبار الديناميكي مع DAST وأمان وقت التشغيل. :::