مقدمة: من التطبيق المتجانس إلى الخدمات المصغرة باستخدام Docker و JavaScript
تطوير الويب الحديث باستخدام JavaScript (خاصة في نظام Node.js البيئي) لا يمكن تصوره بدون الحاويات. لم يعد Docker مجرد أداة "لتعبئة" التطبيق - بل أصبح المعيار الفعلي لتسليم الخدمات المصغرة وتوسيع نطاقها وإدارتها. إذا كنت قد أتقنت بالفعل أساسيات Dockerfile و docker run، فقد حان الوقت للانتقال إلى المستوى المتقدم.
في هذه المقالة، سنشرح كيفية إنشاء صور Docker فعالة وآمنة وخفيفة الوزن لـ Node.js، وإعداد بيئات متعددة الحاويات باستخدام Docker Compose، وتنظيم التفاعل بين الخدمات عبر الشبكات، وإدارة البيانات بكفاءة من خلال volumes. المحتوى موجه للمطورين الذين يرغبون في بناء بنى جاهزة للإنتاج.
1. تحسين Dockerfile لـ Node.js: الطبقات، التخزين المؤقت والأمان
غالبًا ما يبدو Dockerfile التقليدي لـ Node.js كالتالي: FROM node:18، COPY . /app، RUN npm install. ومع ذلك، يؤدي هذا النهج إلى صور ضخمة (أكثر من 1 جيجابايت) ووقت بناء طويل. يعتمد التحسين المتقدم على ثلاثة مبادئ:
1.1 البناء متعدد المراحل (Multi-stage builds)
قم بتقسيم العملية إلى مرحلة بناء (مع المترجمات وتبعيات التطوير) ومرحلة تنفيذ (وقت التشغيل فقط). هذا يقلل الصورة النهائية بمقدار 5-10 مرات.
# ---- مرحلة البناء ----FROM node:18-alpine AS builderWORKDIR /appCOPY package*.json ./RUN npm ci --only=productionCOPY . .RUN npm run build
# ---- مرحلة التنفيذ ----FROM node:18-alpineWORKDIR /appCOPY --from=builder /app/dist ./distCOPY --from=builder /app/node_modules ./node_modulesEXPOSE 3000CMD ["node", "dist/main.js"]
1.2 استخدام .dockerignore والتخزين المؤقت للطبقات
يقوم Docker بتخزين الطبقات مؤقتًا. لتجنب إعادة بناء npm install عند كل تغيير في الكود، قم بنسخ package.json بشكل منفصل. أضف .dockerignore:
node_modules.git*.md.envdist
الآن يتم تنفيذ npm install فقط عند تغيير التبعيات، وليس المشروع بأكمله.
1.3 الأمان: مستخدم غير جذر وصورة أساسية ضئيلة
استخدم node:18-alpine (أو حتى scratch مع ملف ثنائي مبني عبر pkg). لا تقم أبدًا بتشغيل Node.js كمستخدم جذر:
RUN addgroup -S appgroup && adduser -S appuser -G appgroupUSER appuser
هذا يمنع تصعيد الصلاحيات في حالة اختراق التطبيق.
2. Docker Compose: تطبيق متعدد الحاويات (Node.js + Redis + Nginx)
نادرًا ما يتكون التطبيق الحقيقي من خدمة واحدة. يتيح Docker Compose رفع البنية التحتية بأكملها بأمر واحد docker-compose up. لننظر إلى مثال متقدم: Node.js API، Redis للتخزين المؤقت و Nginx كوكيل عكسي.
2.1 هيكل docker-compose.yml
version: '3.8'services: app: build: context: ./app dockerfile: Dockerfile.prod ports: - "3000:3000" environment: - REDIS_URL=redis://redis:6379 - NODE_ENV=production depends_on: - redis restart: unless-stopped
redis: image: redis:7-alpine volumes: - redis-data:/data healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 3s retries: 3
nginx: image: nginx:alpine ports: - "80:80" volumes: - ./nginx.conf:/etc/nginx/nginx.conf:ro depends_on: - app
volumes: redis-data:
2.2 الإعدادات المتقدمة: healthcheck والتبعيات
depends_on يضمن ترتيب التشغيل، لكنه لا ينتظر حتى تصبح الخدمة جاهزة. استخدم healthcheck لـ Redis ونص انتظار في التطبيق:
// في index.js لـ Node.jsconst co