تخطَّ إلى المحتوى
ARAB CODEمجتمع المطورين العرب

أساسيات Docker: من Dockerfile إلى حاوية تعمل بأمان

درسنُشر ٢٤ أكتوبر ٢٠٢٦ · 0 رد · 1 مشاهدة#docker#حاويات#devops#linux
قبل ساعتين

مقدمة

«يعمل على جهازي» جملة يعرفها كل مبرمج. Docker يحزم التطبيق مع بيئته (نظام التشغيل الأساسي، والمكتبات، والإعدادات) في صورة واحدة تعمل بالطريقة نفسها على أي جهاز. هذا الدرس يغطي الأساسيات مع ممارسات أمان من البداية.

أهداف التعلم

  • التمييز بين الصورة والحاوية والطبقات.
  • كتابة Dockerfile بمراحل متعددة ومستخدم غير جذري.
  • تمرير الإعدادات والأسرار دون وضعها في الصورة.
  • تشغيل خدمات متعددة بـ Docker Compose.

1. المفاهيم

  • الصورة (Image): قالب للقراءة فقط مكون من طبقات.
  • الحاوية (Container): نسخة تعمل من الصورة، معزولة عن العمليات الأخرى.
  • الطبقات: كل تعليمة في Dockerfile تنشئ طبقة؛ ويعيد Docker استخدام الطبقات غير المتغيرة فيسرّع البناء.

2. Dockerfile لتطبيق Node.js

# مرحلة البناء
FROM node:22-slim AS build
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
RUN npm run build && npm prune --omit=dev

# مرحلة التشغيل: أصغر وبلا أدوات البناء
FROM node:22-slim
WORKDIR /app
ENV NODE_ENV=production
COPY --from=build /app/node_modules ./node_modules
COPY --from=build /app/dist ./dist
COPY package.json ./
USER node
EXPOSE 3000
CMD ["node", "dist/server.js"]
  • نسخ package.json قبل الكود يجعل طبقة npm ci تُعاد استخدامها ما دامت التبعيات لم تتغير.
  • المراحل المتعددة تُبقي المترجمات وملفات المصدر خارج الصورة النهائية.
  • USER node يشغل التطبيق بمستخدم غير جذري، فثغرة في التطبيق لا تعطي صلاحيات root داخل الحاوية.

وأضف ملف .dockerignore:

node_modules
.git
.env
*.log

حتى لا تُنسخ الأسرار أو الملفات الضخمة إلى الصورة.

3. البناء والتشغيل

docker build -t arabcode-api:1.0 .
docker run --rm -p 3000:3000 --env-file .env.local arabcode-api:1.0
  • --rm يحذف الحاوية عند توقفها.
  • الأسرار تُمرر وقت التشغيل (متغيرات بيئة أو أسرار المنصة)، لا في ENV داخل Dockerfile ولا في الصورة؛ فالصورة قد تُرفع إلى سجل يراه غيرك، وطبقاتها قابلة للفحص.

4. Docker Compose: التطبيق مع قاعدة البيانات

services:
  db:
    image: postgres:16
    environment:
      POSTGRES_PASSWORD: ${DB_PASSWORD}
    volumes:
      - pgdata:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
  api:
    build: .
    ports:
      - "127.0.0.1:3000:3000"
    environment:
      DATABASE_URL: postgres://postgres:${DB_PASSWORD}@db:5432/postgres
    depends_on:
      db:
        condition: service_healthy
volumes:
  pgdata:
docker compose up -d --build
docker compose logs -f api
  • الحجم (Volume) pgdata يحفظ بيانات القاعدة عند حذف الحاوية.
  • 127.0.0.1:3000:3000 ينشر المنفذ على الجهاز المحلي فقط، لا على كل واجهات الشبكة.
  • القاعدة لا تحتاج منفذاً منشوراً أصلاً؛ التطبيق يصلها عبر الشبكة الداخلية باسم db.

تمرين عملي

  1. اكتب Dockerfile لتطبيق صغير (Node أو Python) بمرحلتين ومستخدم غير جذري.
  2. قارن حجم الصورة بمرحلة واحدة ومرحلتين: docker images.
  3. شغّل التطبيق مع PostgreSQL عبر Compose، ثم احذف الحاويات (docker compose down) وأعد تشغيلها وتأكد أن البيانات باقية.
  4. افحص الصورة بحثاً عن ثغرات معروفة: docker scout cves arabcode-api:1.0 أو أداة Trivy.

أخطاء شائعة

  • وضع كلمات المرور في Dockerfile أو نسخ ملف .env إلى الصورة.
  • التشغيل بصلاحيات root داخل الحاوية.
  • نشر منفذ قاعدة البيانات على 0.0.0.0 في خادم عام.
  • استخدام الوسم latest في الإنتاج؛ ثبّت إصداراً محدداً.
  • تخزين بيانات مهمة داخل الحاوية دون حجم دائم.

الخلاصة

الصورة تحزم البيئة، والحاوية تشغلها معزولة. ابنِ بمراحل متعددة، شغّل بمستخدم غير جذري، مرر الأسرار وقت التشغيل، واحفظ البيانات في أحجام دائمة.

مصادر مقترحة

  • توثيق Docker: «Dockerfile best practices».
  • توثيق Docker Compose.
  • OWASP: «Docker Security Cheat Sheet».

الرد على الموضوع

سجّل الدخول للمشاركة في النقاش.

نقاشات مشابهة