3.4المتغيرات والملفات الشخصية (profiles) والتراكبات حسب البيئة
الأساسي في 30 ثانية
- الـ .env : قيمة واحدة، ووجوه عدة : يقرأ ${PORT:-3000} المتغير أو افتراضيه — ملف .env واحد لكل بيئة، وكومبوز واحد لأوجه N.
- التراكبات : قاعدة + نسخة : compose.override.yml مُحمَّل تلقائيا في التطوير، و-f compose.yml -f compose.prod.yml في الإنتاج — ولا يصف كل ملف سوى فرقه.
- الملفات الشخصية : خدمات اختيارية : profiles: [dev] يجعل adminer غائبا افتراضيا، وحاضرا مع --profile dev — فالستاك الافتراضي أدنى وآمن.
حالة مصغرة مسلسلة — إدير يوحد التطوير والإنتاج
إدير، ديفوبس مبتدئ في الجزائر، يصون compose.yml منسوخين (التطوير مع adminer، والإنتاج دونه) — فيتباعدان، ويوما ما تغادر وحدة تحكم التطوير إلى الإنتاج. يعيد التأسيس : قاعدة وحيدة مع ${PORT:-3000}، و adminer تحت profiles: [dev]، و .env لكل بيئة غير مُلتزَم به. التطوير : --profile dev up -d ؛ والإنتاج : up -d، مقتصد افتراضيا. مصدر حقيقة واحد، ووجهان — فلا يحتوي الإنتاج أبدا أدوات التطوير.
هذه الحالة نفسها تعود في الدرس والمخطط والنص الجاهز وتحدي 48 ساعة.
1. الاستيفاء و .env : ضبط دون تكرار
في compose.yml، يقرأ ${PORT:-3000} المتغير PORT أو 3000 افتراضيا : فيصبح كومبوز قابلا للضبط. ويثبت ملف .env بجانب كومبوز القيم حسب البيئة (التطوير : منافذ منشورة + adminer ؛ والإنتاج : قيم أخرى، ولا adminer) — ويُحمَّل تلقائيا. ملف واحد، وأوجه N : الصورة نفسها، والبنية نفسها، وقيم تتغير.
قاعدة النظافة : فالـ .env المحتوي أسرارا لا يُلتزَم به أبدا — بل نُصدِر .env.example وهميا يوثق المفاتيح المنتظرة. وتُختار الافتراضيات ${X:-…} آمنة للإنتاج : فدون متغير، يبدأ الستاك في شكله الأكثر تقتيرا، لا الأكثر انفتاحا.
2. التراكبات -f والملفات الشخصية : النسخ والاختيار
التراكبات (SURCHARGES) : نحتفظ بـ compose.yml قاعدة ونضيف النسخ — compose.override.yml، المُحمَّل تلقائيا في التطوير (تركيبات ربط، وتنقيح)، أو compose.prod.yml المنادَى صراحة (-f compose.yml -f compose.prod.yml). ولا يصف كل ملف سوى فرقه ؛ ومن اليسار إلى اليمين، كل -f يتراكب على سابقه. انتهى التكرار الكامل حسب البيئة.
الملفات الشخصية (PROFILS) : فـ profiles: [dev] على adminer يجعله اختياريا — غائبا افتراضيا، وحاضرا مع --profile dev. انتهى « نسيت إزالة وحدة التحكم في الإنتاج » : فالستاك افتراضيا أدنى وآمن، وأدوات التطوير تُفعَّل صراحة. قاعدة دنيا، وخيارات في ملفات شخصية، وافتراضي آمن للإنتاج.
🔎 مثال ملموس — تطوير غني وإنتاج مقتصد : القاعدة نفسها والوجهان
يضبط إدير المنفذ، ويضع adminer في الملف الشخصي dev، ويطلق كل بيئة.
# compose.yml (قاعدة)
services:
api:
build: ./api
ports: ["${PORT:-3000}:3000"]
networks: [appnet]
adminer:
image: adminer:4.8
profiles: [dev]
ports: ["8081:8080"]
networks: [appnet]
networks:
appnet:
# .env (التطوير، غير مُلتزَم به) : PORT=3000
# التطوير : docker compose --profile dev up -d
# الإنتاج : PORT=80 docker compose up -d
القراءة : القاعدة نفسها، و adminer فقط في التطوير، والمنفذ بمتغير.
الدرس : فلا يحتوي الإنتاج أبدا أدوات التطوير — ومقتصد افتراضيا.
مفردات القسم
- الاستيفاء (Interpolation)
- يُحَل ${VAR:-افتراضي} من البيئة أو .env : كومبوز قابل للضبط.
مثال بسيط: الـ ${PORT:-3000} الخاص بإدير، 3000 دون متغير.
ما ليس كذلك: منفذ ثابت مكرر في ملفين.
رد فعل: افتراضي آمن للإنتاج بعد كل :-.
- التراكب (Surcharge)
- ملف -f إضافي يعدل القاعدة : كل -f يتراكب على سابقه، من اليسار إلى اليمين.
مثال بسيط: -f compose.yml -f compose.prod.yml في الإنتاج.
ما ليس كذلك: كومبوز ثان منسوخ متطابق 95 %.
رد فعل: كل نسخة لا تصف سوى فرقها.
- override
- تراكب التطوير (compose.override.yml) المُحمَّل تلقائيا : تركيبات حية وتنقيح، دون مساس القاعدة.
مثال بسيط: التركيبات الحية الخاصة بإدير في التطوير فقط.
ما ليس كذلك: تركيبات تطوير تتسرب إلى الإنتاج.
رد فعل: التطوير في override، ولا في القاعدة أبدا.
- الملف الشخصي (Profil)
- مجموعة اختيارية (profiles: [dev]) تُفعَّل مع --profile : خدمة غائبة افتراضيا.
مثال بسيط: Adminer حاضر فقط مع --profile dev.
ما ليس كذلك: وحدة تحكم التطوير تغادر إلى الإنتاج سهوا.
رد فعل: أدوات التطوير في ملفات شخصية، وستاك مقتصد افتراضيا.
- .env
- ملف قيم محلي بجانب كومبوز، يُحمَّل تلقائيا — وغير مُلتزَم به إذا احتوى أسرارا.
مثال بسيط: الـ .env الخاص بإدير مع PORT وكلمات سر محلية.
ما ليس كذلك: .env بأسرار مدفوع إلى المستودع.
رد فعل: صَدِّروا .env.example، ولا الأسرار أبدا.
في التطبيق — تطوير/إنتاج دون تكرار
- أضيفوا ${PORT:-3000} وملفا شخصيا dev (adminer) إلى كومبوز القاعدة خاصتكم.
- اطلقوا دون ملف شخصي : تحققوا من غياب adminer (ستاك مقتصد).
- أعيدوا الإطلاق مع --profile dev : يظهر adminer — اختيار صريح.
- غيروا PORT عبر البيئة وأعيدوا الإطلاق : فيتبع المنفذ، دون مساس الملف.
نص جاهز للقول — تبرير القاعدة الوحيدة (30 ثانية)
« كومبوز قاعدة واحد : فالمنفذ يأتي من متغير، ووحدة تحكم التطوير من ملف شخصي اختياري، وفروق الإنتاج من تراكب. تطوير غني مع --profile dev، وإنتاج مقتصد افتراضيا — ولا ملف منسوخ يتباعد بعد، ولا أداة تطوير تتسرب إلى الإنتاج. »
يُقال في مراجعة البنية ؛ واعرضوا الفرق الفارغ بين التطوير والإنتاج.
نموذج نسخ-لصق — قاعدة مضبوطة + ملف dev الشخصي
# القاعدة : تطوير غني في اختيار، وإنتاج مقتصد افتراضيا.
services:
api:
build: ./api
ports:
- "${PORT:-3000}:3000"
environment:
DATABASE_URL: ${DATABASE_URL}
networks:
- appnet
adminer:
image: adminer:4.8
profiles:
- dev
ports:
- "8081:8080"
networks:
- appnet
networks:
appnet:
# التطوير : docker compose --profile dev up -d
# الإنتاج : docker compose -f compose.yml -f compose.prod.yml up -d
مستقل
القاعدة + .env.example وكل عميل يصرف دون مساس الملف.
مقاولة صغيرة في الجزائر
يوحد إدير التطوير والإنتاج : قاعدة واحدة، و .env اثنان، وصفر تباعد.
فريق منتج
افرضوا قاعدة دنيا + ملفات شخصية اختيارية + افتراضيات آمنة للإنتاج في الميثاق.
مبتدئ
هذا الأسبوع : متغير واحد ${PORT:-3000} + خدمة واحدة في ملف dev الشخصي.
✓ ممارسات جيدة
- أبقوا القاعدة دنيا، وضعوا الخيارات في ملفات شخصية اختيارية.
- اختاروا افتراضيات آمنة للإنتاج بعد كل :- (${X:-…}).
- صَدِّروا .env.example، ولا الأسرار الحقيقية أبدا.
✗ أخطاء شائعة
- تكرار الملف كله حسب البيئة : فالنسخ تتباعد.
- ملفات dev الشخصية نشطة افتراضيا : فلا يوجد اختيار بعد، وتتسرب وحدة التحكم إلى الإنتاج.
- التزام .env بكلمات سر : سر مكشوف في السجل.
النقاط الأساسية
- يجعل ${VAR:-افتراضي} كومبوز قابلا للضبط : ملف واحد وأوجه N.
- التراكبات للفروق (-f، و override التطوير) : ولا تكرار أبدا.
- الملفات الشخصية اختيارية للأدوات : غائبة افتراضيا، و --profile dev للتفعيل.
- الافتراضي = إنتاج آمن ؛ و .env.example مُصدَر، والأسرار لا تُلتزَم أبدا.
تحدي 48 ساعة — طبّق غدا
ادمجوا كومبوز منسوخين اثنين في قاعدة واحدة + ملف dev شخصي واحد + تراكب واحد، وأثبتوا أن الإنتاج يبدأ مقتصدا.
- قاعدتي الوحيدة تخدم التطوير والإنتاج دون نسخ-لصق.
- أدوات تطويري في اختيار، ومقتصدة افتراضيا.
- أسراري خارج المستودع، وافتراضياتي آمنة للإنتاج.
أسئلة شائعة
أين نضع .env، وكيف نبقيه خارج المستودع ؟
بجانب compose.yml : يُحمَّل تلقائيا، وواحد لكل بيئة. وإذا احتوى أسرارا، فلا يُلتزَم به أبدا (أضيفوه إلى .gitignore) — وقدموا .env.example مُصدَرا بقيم وهمية توثق كل مفتاح. وفي الإنتاج، تأتي القيم من البيئة أو سر مُدار.
عدة -f، بأي ترتيب، و override أم prod ؟
من اليسار إلى اليمين : كل -f يتراكب على سابقه — القاعدة أولا، والنسخة بعدها (-f compose.yml -f compose.prod.yml). وcompose.override.yml هو الاستثناء : يُحمَّل تلقائيا (دون -f)، ويحمل التطوير (تركيبات ربط، وتنقيح). والقاعدة : التطوير = override تلقائي، والإنتاج = -f صريح، ولا يصف كل ملف سوى فرقه.
يجب ألا يوجد Adminer إلا في التطوير. أي آلية ؟