Docker Compose للبيئات المحلية
شغّل PHP وقاعدة بيانات وذاكرة تخزين مؤقت معًا محليًا
Docker Compose للبيئات المحلية درس مجاني في PHP Academy على CoddyKit. هذا هو الدرس 3 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في PHP Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة PHP Academy 4 دروس في المجموع.
البيئات المحلية باستخدام Compose
لا تكون تطبيقات PHP الحقيقية مجرد PHP، بل تحتاج إلى قاعدة بيانات وذاكرة تخزين مؤقت، وأحيانًا إلى قائمة انتظار وأداة لالتقاط البريد. يعرّف Docker Compose كل هذه العناصر كخدمات في ملف واحد، ويربطها بشبكة مشتركة بحيث تصل الخدمات إلى بعضها باستخدام أسمائها.
ينشئ هذا الدرس بيئة محلية متكاملة: PHP-FPM وnginx وMySQL وRedis، مع وحدات تخزين وفحوصات صحة وترتيب للاعتماديات.
هيكل الخدمة
يسرد ملف Compose الخدمات تحت services:. ويمكن لكل خدمة أن تُبنى من Dockerfile باستخدام build أو أن تسحب image. ينشئ Compose شبكةً افتراضية يمكن الوصول عبرها إلى كل خدمة باستخدام مفتاحها؛ فعلى تطبيق PHP الاتصال بـ MySQL عبر المضيف db، وليس localhost.
services:
app:
build:
context: .
target: dev # multi-stage dev target
volumes:
- ./:/app # live code mount
depends_on:
db:
condition: service_healthy
db:
image: mysql:8.4
redis:
image: redis:7-alpineوضع nginx أمام FPM
يتحدث FPM عبر FastCGI على المنفذ 9000، وليس عبر HTTP. ينهي nginx اتصالات HTTP ويمرر طلبات .php إلى app:9000. ويشير إعداد nginx إلى خدمة PHP باستخدام اسمها في Compose.
# docker/nginx/default.conf
server {
listen 80;
root /app/public;
index index.php;
location / {
try_files $uri /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass app:9000; # service name from compose
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}ربط خدمة الويب
تربط خدمة nginx الشيفرة نفسها (لحل قيمة SCRIPT_FILENAME) وملف الإعداد، وتنشر المنفذ 80، وتعتمد على التطبيق. وتشترك الخدمتان في /app حتى تتطابق المسارات على جانبي FastCGI.
services:
web:
image: nginx:1.27-alpine
ports:
- "8080:80"
volumes:
- ./:/app:ro
- ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
depends_on:
- appوحدات التخزين الدائمة
أنظمة ملفات الحاويات مؤقتة. تحتفظ وحدات التخزين المسماة بملفات قاعدة البيانات بعد تنفيذ docker compose down. وتزامن عمليات الربط المباشر (./:/app) شيفرة المضيف مباشرةً لأغراض التطوير. استخدموا وحدات التخزين المسماة للبيانات ذات الحالة، وعمليات الربط المباشر للمصدر.
services:
db:
image: mysql:8.4
environment:
MYSQL_DATABASE: app
MYSQL_USER: app
MYSQL_PASSWORD: secret
MYSQL_ROOT_PASSWORD: rootsecret
volumes:
- dbdata:/var/lib/mysql
volumes:
dbdata: # survives `down`, removed only by `down -v`فحوصات الصحة وdepends_on
لا ينتظر depends_on وحده سوى أن تبدأ الحاوية، وليس أن تقبل MySQL الاتصالات. أضيفوا healthcheck واستخدموا condition: service_healthy حتى ينتظر تطبيقكم إلى أن تصبح قاعدة البيانات جاهزة فعليًا.
services:
db:
image: mysql:8.4
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-prootsecret"]
interval: 5s
timeout: 3s
retries: 10
app:
build: .
depends_on:
db:
condition: service_healthy # waits for healthcheck passالبيئة و.env
يحمّل Compose تلقائيًا ملف .env المجاور لاستبدال المتغيرات، وتمررون إعدادات التطبيق عبر environment أو env_file. أبقوا الأسرار خارج ملف Compose الذي تودعونه في المستودع، وأشيروا إلى المتغيرات بدلًا منها.
services:
app:
build: .
env_file:
- .env
environment:
DATABASE_URL: "mysql://app:secret@db:3306/app"
REDIS_URL: "redis://redis:6379"
# .env (gitignored) provides ${...} substitutions
# MYSQL_PASSWORD=secretالاتصال من PHP
تكون أسماء المضيفين داخل الشبكة هي أسماء الخدمات. يتصل كود PHP مباشرةً بـ db وredis. يحلل هذا المقطع DSN بالطريقة التي قد تستخدمها طبقة إعدادات، موضحًا كيفية انتقال اسم خدمة Compose إلى سلسلة الاتصال.
<?php
$dsn = 'mysql://app:secret@db:3306/app';
$p = parse_url($dsn);
printf("driver: %s\n", $p['scheme']);
printf("host: %s\n", $p['host']); // 'db' resolves via compose DNS
printf("port: %d\n", $p['port']);
printf("db: %s\n", ltrim($p['path'], '/'));
$pdoDsn = sprintf('mysql:host=%s;port=%d;dbname=%s', $p['host'], $p['port'], ltrim($p['path'], '/'));
echo $pdoDsn . PHP_EOL;
?>Xdebug للتطوير المحلي
اربطوا إعدادات Xdebug محليًا فقط (عبر هدف البناء dev). وجّهوا client_host إلى host.docker.internal حتى يصل مصحح الأخطاء إلى بيئة التطوير المتكاملة لديكم على المضيف. لا تشحنوا Xdebug إلى الإنتاج مطلقًا، لأنه يقتل الأداء.
; docker/php/xdebug.ini (mounted only in dev)
zend_extension=xdebug
xdebug.mode=debug
xdebug.start_with_request=yes
xdebug.client_host=host.docker.internal
xdebug.client_port=9003تشغيل الأوامر لمرة واحدة
ينشئ docker compose run حاوية مؤقتة لتنفيذ عمليات الترحيل أو الاختبارات أو Composer، بينما يشغّل exec الأمر داخل خدمة قيد التشغيل مسبقًا. استخدموا run --rm للمهام حتى تُنظّف الحاوية المؤقتة.
# Run migrations against the running db
docker compose exec app php bin/console doctrine:migrations:migrate
# One-off: install deps without a long-lived container
docker compose run --rm app composer install
# Tail logs of just the web service
docker compose logs -f webملفات التجاوز
يدمج Compose تلقائيًا بين docker-compose.yml وdocker-compose.override.yml. أبقوا الإعدادات الافتراضية الموافقة للإنتاج في الملف الأساسي، وضعوا وحدات التخزين والمنافذ وXdebug الخاصة بالتطوير فقط في ملف التجاوز، بحيث تستخدم CI الملف الأساسي ويحصل المطورون على الإضافات تلقائيًا.
# docker-compose.override.yml (auto-merged, dev only)
services:
app:
volumes:
- ./docker/php/xdebug.ini:/usr/local/etc/php/conf.d/xdebug.ini:ro
environment:
APP_ENV: dev
# CI runs: docker compose -f docker-compose.yml up (no override)فحص سريع
لماذا لا يكفي depends_on: [db] وحده قبل تشغيل عمليات الترحيل؟
مراجعة
أنشأتم بيئة محلية متكاملة باستخدام Compose: PHP-FPM خلف nginx (عبر FastCGI إلى app:9000)، وMySQL وRedis يمكن الوصول إليهما باسمَي الخدمتين، ووحدات تخزين مسماة للاستمرارية، وفحوصات صحة تتحكم في depends_on، وإعدادات تعتمد على البيئة، وXdebug في ملف تجاوز خاص بالتطوير، وأوامر لمرة واحدة عبر run/exec.
تذكّروا: أسماء الخدمات هي أسماء مضيفين في DNS، وملفات التجاوز تُبقي إضافات التطوير خارج CI، وفحوصات الصحة أفضل من ترتيب بدء التشغيل الساذج.
الأسئلة الشائعة
هل درس «Docker Compose للبيئات المحلية» مجاني؟
نعم — نص درس «Docker Compose للبيئات المحلية» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة PHP Academy، انتقل إلى CoddyKit PRO. تتضمن دورة PHP Academy 4 دروس في المجموع.
ماذا ستتعلم في «Docker Compose للبيئات المحلية»؟
شغّل PHP وقاعدة بيانات وذاكرة تخزين مؤقت معًا محليًا تتمرن على PHP Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ PHP Academy؟
لا تُشترط خبرة سابقة. PHP Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 3 من أصل 4.
كم من الوقت يستغرق درس «Docker Compose للبيئات المحلية»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس PHP Academy هذا؟
نعم. كل درس في PHP Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- وضع تطبيق PHP في حاوية
- البناء متعدد المراحل والتحسين
- Docker Compose للبيئات المحلية
- التكامل والنشر المستمران باستخدام GitHub Actions