Docker وTypeScript: حاويات التطبيقات المتقدمة
\n\nحاويات تطبيقات TypeScript باستخدام Docker ليست مجرد تغليف للكود في صورة. على المستوى المتقدم، إنها فن التحسين والأمان والأتمتة. في هذه المقالة، سنشرح كيفية إنشاء صور Docker فعالة لـ TypeScript، وإدارة البيئة، ودمج الحاويات في خط أنابيب CI/CD. ستتعلم كيفية تقليل حجم الصورة بمقدار 5-10 مرات، وتسريع البناء، وتحسين عزل التبعيات.
\n\n1. البناء متعدد المراحل (Multi-stage builds) لـ TypeScript
\n\nالمشكلة الكلاسيكية لصور Docker الخاصة بـ TypeScript هي تضمين جميع أدوات التطوير في الصورة النهائية: مترجم TypeScript، تبعيات التطوير، الملفات المصدرية. هذا يؤدي إلى أحجام ضخمة (غالبًا > 1 جيجابايت). الحل هو البناء متعدد المراحل.
\n\nالفكرة بسيطة: المرحلة الأولى (build) تقوم بتجميع TypeScript إلى JavaScript وتثبيت جميع التبعيات. المرحلة الثانية (production) تنسخ فقط JavaScript الجاهز وتبعيات الإنتاج.
\n\n# المرحلة 1: البناء\nFROM node:20-alpine AS builder\nWORKDIR /app\nCOPY package*.json ./\nRUN npm ci --only=development\nCOPY . .\nRUN npm run build\n\n# المرحلة 2: الإنتاج\nFROM node:20-alpine AS production\nWORKDIR /app\nCOPY --from=builder /app/dist ./dist\nCOPY --from=builder /app/package*.json ./\nRUN npm ci --only=production\nEXPOSE 3000\nCMD ["node", "dist/index.js"]\n\nهذا الأسلوب يقلل حجم الصورة من ~800 ميجابايت إلى ~150 ميجابايت. لاحظ استخدام --only=development و --only=production — هذه علامات أساسية لفصل التبعيات.
2. تحسين التخزين المؤقت لطبقات Docker
\n\nكل تعليمة في Dockerfile تنشئ طبقة. يقوم Docker بتخزين الطبقات مؤقتًا إذا لم تتغير. الترتيب الصحيح للتعليمات مهم جدًا لسرعة عمليات البناء المتكررة.
\n\nمثال سيء (يكسر التخزين المؤقت):
\nFROM node:20-alpine\nWORKDIR /app\nCOPY . .\nRUN npm ci\nRUN npm run build\nCMD ["node", "dist/index.js"]\n\nهنا، أي تغيير في الكود المصدري (حتى في README.md) يعيد تعيين التخزين المؤقت لـ npm ci والبناء.
\n\nمثال جيد (يحافظ على التخزين المؤقت):
\nFROM node:20-alpine AS builder\nWORKDIR /app\nCOPY package*.json tsconfig.json ./\nRUN npm ci --only=development\nCOPY src ./src\nRUN npm run build\n\nلماذا يعمل هذا؟ التبعيات تتغير نادرًا، بينما الكود المصدري يتغير كثيرًا. بنسخ package*.json بشكل منفصل، نضمن أن الطبقة التي تحتوي على npm ci تُعاد بناؤها فقط عند تغيير هذه الملفات.
3. العمل مع متغيرات البيئة والأسرار
\n\nلتطبيقات TypeScript على Node.js، استخدام متغيرات البيئة هو المعيار. ومع ذلك، هناك تفاصيل دقيقة في Docker.
\n\nخطأ شائع: تمرير البيانات الحساسة (مفاتيح API، كلمات المرور) عبر ENV في Dockerfile. هذا يترك الأسرار في تاريخ طبقات الصورة.
النهج الصحيح:
\n- \n
- استخدم
--env-fileعند تشغيل الحاوية \n - للإنتاج، استخدم Docker Secrets (في Swarm) أو Kubernetes Secrets \n
- للتطوير المحلي، استخدم ملف
.envمعdocker-compose\n
مثال docker-compose.yml:
\nversion: '3.8'\nservices:\n app:\n build: .\n ports:\n - "3000:3000"\n env_file:\n - .env.production\n volumes:\n - ./logs:/app/logs\n\nفي كود TypeScript، استخدم مكتبة dotenv لتحميل المتغيرات:
import dotenv from 'dotenv';\nimport { resolve } from 'path';\n\ndotenv.config({ path: resolve(__dirname, '../.env') });\n\nconst config = {\n port: parseInt(process.env.PORT || '3000', 10),\n dbUrl: process.env.DATABASE_URL,\n apiKey: process.env.API_KEY\n};\n\nexport default config;\n\nهام: لا تقم أبدًا بإضافة ملفات .env الحقيقية إلى نظام التحكم بالإصدارات