# تأمين Docker وتقويته: دليل عملي لحماية الحاويات

> تأمين Docker يعني تقليل الصلاحيات وسطح الهجوم في أربع طبقات: صورة صغيرة موثوقة ومفحوصة، وبناء بمستخدم غير جذري ودون أسرار، وتشغيل بخيارات مثل --cap-drop ALL و--read-only و no-new-privileges، ومضيف محدّث يعمل بالوضع غير الجذري ولا يكشف مقبس Docker لأي حاوية.

- الرابط: https://blog.cyberpedia.site/docker-security-hardening/
- التصنيف: الأمن السيبراني
- الكاتب: فريق سايبربيديا
- تاريخ النشر: 10 أكتوبر 2026 (2026-10-10)

تعمل Docker اليوم في قلب معظم بيئات التطوير والإنتاج، لكن سهولة تشغيل حاوية بأمر واحد تخفي إعدادات افتراضية لم تُصمَّم لأقصى درجات الأمان. تقوية الأمان (Hardening) تعني أن تغلق هذه الثغرات طبقة بعد طبقة: من الصورة، إلى البناء، إلى التشغيل، وصولاً إلى المضيف نفسه.

## لماذا لا تكون حاويات Docker آمنة افتراضياً؟

لأن الحاوية ليست آلة افتراضية: كل الحاويات تتشارك نواة (Kernel) نظام المضيف نفسه، وأي ثغرة في النواة أو إعداد متساهل قد يفتح طريقاً للهروب من الحاوية (Container Escape) إلى المضيف.

وتزيد بعض الإعدادات الافتراضية من هذا الخطر:

- العملية داخل الحاوية تعمل بصلاحيات `root` ما لم تحدد مستخدماً آخر.
- خدمة Docker (Docker Daemon) تعمل بصلاحيات `root` على المضيف في التثبيت العادي.
- عضوية مجموعة `docker` تكافئ عملياً صلاحيات `root` على المضيف، لأنها تسمح بتشغيل أي حاوية بأي إعدادات.

وإذا كنت جديداً على مفهوم التقوية عموماً، فابدأ بمقال [Cybersecurity Hardening النهج الاستباقي لحماية الأنظمة](https://blog.cyberpedia.site/cybersecurity-hardening/).

## أين تضع الحماية في دورة حياة الحاوية؟

تحتاج الحماية إلى أربع طبقات متتالية، وضعف أي طبقة منها قد يُسقط فائدة الطبقات الأخرى.

![مخطط يوضح طبقات تأمين Docker الأربع: الصورة ثم البناء ثم التشغيل ثم المضيف](https://blog.cyberpedia.site/_astro/img-01.DGfOwTks_Z2nvDEi.webp)

*أربع طبقات لتأمين Docker: الصورة والبناء والتشغيل والمضيف*

## كيف تؤمّن صورة الحاوية (Docker Image)؟

ابدأ بصورة أساس (Base Image) صغيرة ومن مصدر موثوق، لأن كل حزمة إضافية في الصورة ثغرة محتملة. الصور الرسمية (Official Images)، والصور المصغّرة مثل `alpine` و`slim` وصور Distroless، تقلل سطح الهجوم كثيراً.

### ثبّت الصورة بدل الوسم المتغير

الوسم `latest` قد يشير غداً إلى صورة مختلفة عن اليوم. ثبّت الإصدار، والأفضل أن تثبّت البصمة (Digest) حتى تضمن أنك تبني دائماً من الصورة نفسها:

```dockerfile
FROM python:3.12-slim@sha256:<digest>
```

هذا مهم أيضاً للحماية من [هجمات سلاسل التوريد](https://blog.cyberpedia.site/supply-chain-attack/)، حيث يُستبدل مكوّن موثوق بآخر خبيث.

### افحص الصورة من الثغرات قبل النشر

استخدم أداة فحص مثل Trivy أو Docker Scout، واجعل الفحص خطوة إلزامية في خط النشر (CI/CD) تمنع نشر أي صورة فيها ثغرات حرجة:

```bash
trivy image myapp:1.4.0
docker scout cves myapp:1.4.0
```

## كيف تبني صورة آمنة في Dockerfile؟

القاعدة: الصورة النهائية تحتوي ما يحتاجه التطبيق ليعمل فقط، وتعمل بمستخدم عادي. البناء متعدد المراحل (Multi-stage Build) يحقق ذلك: المرحلة الأولى `build` تحتوي أدوات الترجمة وتُخرج الملف التنفيذي، والمرحلة الثانية تنسخ هذا الملف وحده إلى صورة إنتاج صغيرة لا تحتوي حتى على Shell.

```dockerfile
FROM golang:1.22 AS build
WORKDIR /src
COPY . .
RUN CGO_ENABLED=0 go build -o /app ./cmd/server

FROM gcr.io/distroless/static-debian12
COPY --from=build /app /app
USER 10001:10001
ENTRYPOINT ["/app"]
```

وانتبه لثلاث نقاط أخرى أثناء البناء:

1. لا تضع كلمات المرور أو المفاتيح في `ENV` أو في ملفات تنسخها إلى الصورة، فكل طبقة يمكن استخراجها لاحقاً.
2. أضف ملف `.dockerignore` يستبعد ملفات مثل `.env` و`.git` ومفاتيح SSH.
3. إذا احتجت سراً أثناء البناء فقط، مرّره عبر BuildKit حتى لا يُحفظ في أي طبقة.

```dockerfile
RUN --mount=type=secret,id=npm_token \
    NPM_TOKEN=$(cat /run/secrets/npm_token) npm ci
```

```bash
docker build --secret id=npm_token,src=./npm_token.txt -t myapp .
```

## كيف تشغّل الحاوية بأقل صلاحيات ممكنة؟

مبدأ أقل الصلاحيات (Least Privilege) هو جوهر تأمين التشغيل: امنح الحاوية ما تحتاجه فقط، واسحب الباقي.

![مقارنة بين تشغيل حاوية Docker بالإعدادات الافتراضية وتشغيلها بخيارات التقوية](https://blog.cyberpedia.site/_astro/img-02.B7NV8sGP_igB1e.webp)

*الفرق بين أمر التشغيل الافتراضي وأمر التشغيل المُحصَّن*

| الخيار | ما الذي يحميك منه |
|---|---|
| `--user 10001` | يمنع تشغيل التطبيق بصلاحيات `root` داخل الحاوية |
| `--read-only` | يمنع المهاجم من تعديل الملفات أو زرع أدوات داخل الحاوية |
| `--cap-drop ALL` | يسحب قدرات لينكس (Linux Capabilities) كلها، ثم تضيف ما يلزم فقط بـ `--cap-add` |
| `--security-opt no-new-privileges` | يمنع العمليات من رفع صلاحياتها عبر ملفات `setuid` |
| `--memory` و`--cpus` و`--pids-limit` | تحدّ من استنزاف موارد المضيف، مثل هجمات Fork Bomb |

وإذا احتاج التطبيق مكاناً مؤقتاً للكتابة مع `--read-only`، فأضف `--tmpfs /tmp`.

### إعدادات يجب ألا تراها في بيئة الإنتاج

- الخيار `--privileged`: يمنح الحاوية صلاحيات شبه كاملة على المضيف ويعطّل معظم طبقات العزل.
- تعطيل ملفات الحماية بخيار `--security-opt seccomp=unconfined` أو `apparmor=unconfined`. أبقِ ملف Seccomp الافتراضي وملف AppArmor أو SELinux مفعّلين.
- ربط مقبس Docker (`/var/run/docker.sock`) داخل الحاوية، فمن يصل إليه يتحكم بخدمة Docker، أي بالمضيف كاملاً.
- مشاركة نطاقات المضيف مثل `--pid=host` و`--network=host` دون حاجة حقيقية.

### الإعدادات نفسها في Docker Compose

```yaml
services:
  web:
    image: myapp:1.4.0
    user: "10001:10001"
    read_only: true
    tmpfs:
      - /tmp
    cap_drop:
      - ALL
    security_opt:
      - no-new-privileges:true
    mem_limit: 512m
    pids_limit: 100
```

## كيف تحمي مضيف Docker وخدمته؟

المضيف هو الهدف الأخير لأي هجوم على الحاويات، وحمايته تبدأ بالتحديث المستمر لـ Docker Engine ولنواة النظام، لأن ثغرات الهروب من الحاوية تُصلَح عادةً هناك.

ثم طبّق هذه الإعدادات:

1. شغّل Docker في الوضع غير الجذري (Rootless Mode)، فتعمل الخدمة والحاويات بمستخدم عادي، ولا يحصل المهاجم على `root` حتى لو هرب من الحاوية.
2. إن لم يناسبك الوضع غير الجذري، فعّل عزل نطاق المستخدمين (User Namespaces) ليصبح `root` داخل الحاوية مستخدماً عادياً على المضيف.
3. لا تفتح واجهة Docker على الشبكة عبر TCP دون تشفير TLS ومصادقة بالشهادات، فالمنفذ `2375` غير المشفّر يعني تحكماً كاملاً بالمضيف لأي شخص يصل إليه.
4. قيّد عضوية مجموعة `docker` بأضيق نطاق ممكن.

مثال لملف إعدادات الخدمة `/etc/docker/daemon.json`:

```json
{
  "userns-remap": "default",
  "no-new-privileges": true,
  "icc": false
}
```

يفعّل هذا الملف عزل نطاق المستخدمين، ويمنع رفع الصلاحيات في كل الحاويات افتراضياً، ويوقف الاتصال المفتوح بين الحاويات على الشبكة الافتراضية.

وللتدقيق الدوري، شغّل أداة `docker-bench-security` التي تفحص المضيف وفق معيار CIS Docker Benchmark، وتعطيك تقريراً بالإعدادات المخالفة.

## كيف تؤمّن شبكة الحاويات؟

افصل الحاويات في شبكات مستقلة حسب وظيفتها، ولا تنشر إلا المنافذ التي يجب أن يصل إليها أحد من الخارج.

- أنشئ شبكات خاصة (User-defined Networks) لكل تطبيق بدل الشبكة الافتراضية `bridge`، واجعل قاعدة البيانات في شبكة داخلية لا يصل إليها إلا التطبيق.
- انشر المنافذ الداخلية على العنوان المحلي فقط: `-p 127.0.0.1:5432:5432` بدل `-p 5432:5432`.
- انتبه إلى أن المنافذ التي تنشرها Docker تتجاوز قواعد جدار الحماية UFW على لينكس، لأن Docker تضيف قواعد `iptables` خاصة بها. لا تعتمد على UFW وحده لإغلاق منفذ نشرته بنفسك.

## كيف تتعامل مع الأسرار؟

تجنّب تمرير كلمات المرور عبر متغيرات البيئة (Environment Variables)، لأنها تظهر في `docker inspect` وقد تظهر في سجلات بعض الأدوات. استخدم أسرار Docker Compose أو Swarm، فهي تُركَّب ملفات داخل `/run/secrets/` ولا تُحفظ في الصورة:

```yaml
services:
  db:
    image: postgres:16
    environment:
      POSTGRES_PASSWORD_FILE: /run/secrets/db_password
    secrets:
      - db_password

secrets:
  db_password:
    file: ./db_password.txt
```

وفي البيئات الكبيرة، يُفضَّل مدير أسرار مخصص مثل HashiCorp Vault أو خدمات إدارة الأسرار لدى مزوّد [الحوسبة السحابية](https://blog.cyberpedia.site/cloud-computing/).

## قائمة تحقق سريعة لتأمين Docker

1. صورة أساس صغيرة وموثوقة ومثبّتة بالبصمة.
2. فحص الثغرات في كل بناء، ومنع نشر الصور ذات الثغرات الحرجة.
3. مستخدم غير جذري عبر `USER` في كل Dockerfile.
4. لا أسرار في الصورة أو في متغيرات البيئة.
5. الخيارات `--cap-drop ALL` و`no-new-privileges` و`--read-only` وحدود الموارد عند التشغيل.
6. لا `--privileged` ولا ربط لمقبس `docker.sock` داخل الحاويات.
7. Docker والنواة محدّثان، مع الوضع غير الجذري أو عزل نطاق المستخدمين.
8. شبكات منفصلة ومنافذ منشورة على الحد الأدنى.
9. تدقيق دوري بأداة `docker-bench-security`، ومراقبة سلوك الحاويات أثناء التشغيل بأدوات مثل Falco.

## أسئلة شائعة

### هل حاويات Docker معزولة تماماً عن المضيف؟

لا، فكل الحاويات تتشارك نواة المضيف، وثغرة في النواة أو إعداد متساهل مثل --privileged قد يسمح بالهروب من الحاوية إلى المضيف.

### لماذا لا يجب تشغيل الحاوية بصلاحيات root؟

لأن من يخترق التطبيق يحصل على root داخل الحاوية، فيصبح الهروب إلى المضيف أسهل بكثير عند وجود ثغرة أو إعداد خاطئ.

### ما خطورة ربط docker.sock داخل الحاوية؟

من يصل إلى المقبس يتحكم بخدمة Docker ويستطيع تشغيل حاوية بصلاحيات كاملة، أي أنه يسيطر عملياً على المضيف.

### كيف أفحص صور Docker من الثغرات؟

استخدم أدوات مثل Trivy أو Docker Scout لفحص حزم الصورة وعرض الثغرات المعروفة فيها، واجعل الفحص خطوة إلزامية في خط النشر.

### هل يكفي جدار الحماية UFW لحماية منافذ الحاويات؟

لا، فالمنافذ التي تنشرها Docker تتجاوز قواعد UFW، لذا انشر المنافذ الداخلية على العنوان 127.0.0.1 فقط.

## المصادر

- [OWASP Docker Security Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Docker_Security_Cheat_Sheet.html)
- [Docker Docs: Docker Engine security](https://docs.docker.com/engine/security/)
- [Docker Docs: Rootless mode](https://docs.docker.com/engine/security/rootless/)
- [Docker Docs: Packet filtering and firewalls](https://docs.docker.com/engine/network/packet-filtering-firewalls/)
- [CIS Docker Benchmark](https://www.cisecurity.org/benchmark/docker)
- [docker-bench-security](https://github.com/docker/docker-bench-security)

---

المصدر: مدونة سايبربيديا (https://blog.cyberpedia.site/docker-security-hardening/)
