وضع تطبيق PHP في حاوية
اكتب Dockerfile جاهزًا للإنتاج لتطبيق PHP
وضع تطبيق PHP في حاوية درس مجاني في PHP Academy على CoddyKit. هذا هو الدرس 1 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في PHP Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة PHP Academy 4 دروس في المجموع.
لماذا نضع PHP في حاوية
يعني شحن PHP بطريقة قابلة لإعادة الإنتاج تثبيت إصدار المفسّر الدقيق والامتدادات ومكتبات نظام التشغيل إلى جانب شيفرتك. تضمن صورة Docker أن تحصل كل بيئة — الحاسوب المحمول وCI والإنتاج — على ناتج php -v نفسه وعلى مجموعة ext-* نفسها.
نبني في هذا الدرس صورة جاهزة للإنتاج: PHP-FPM، والامتدادات التي تحتاج إليها فقط، وإعدادات مضبوطة، ومستخدم غير جذر، وفحص صحة.
FPM مقابل أساس Apache
تأتي صور PHP الرسمية بنكهات متعددة. بالنسبة إلى تطبيق ويب إنتاجي خلف nginx/traefik، فضّل php:8.3-fpm-alpine الصغيرة أو php:8.3-fpm المبنية على Debian وglibc، إذ تسبب مفاجآت أقل مع المكتبات الأصلية.
cli— العمال وقوائم الانتظار والمهام المجدولةfpm— مدير عمليات FastCGI، ويُستخدم مع nginxapache— Apache مضمّن، ملائم لكنه أثقل
ثبّت الإصدار الفرعي. لا تستخدم :latest في الإنتاج أبدًا.
# Base image choice in your Dockerfile
FROM php:8.3-fpm-alpine AS base
# Why alpine? ~30MB base vs ~140MB Debian.
# Tradeoff: musl libc, occasional native-extension friction.تثبيت الامتدادات
لا تستخدم apt install php-xxx أبدًا داخل هذه الصور؛ استخدم المساعدات المضمّنة docker-php-ext-install وdocker-php-ext-configure وpecl. ويُعد البرنامج النصي install-php-extensions من mlocati الاختصار الفعلي المتعارف عليه، إذ يجلب لك ترويسات التطوير المناسبة.
FROM php:8.3-fpm-alpine
# Grab the helper that resolves build deps automatically
ADD https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions /usr/local/bin/
RUN chmod +x /usr/local/bin/install-php-extensions && \
install-php-extensions \
pdo_mysql \
opcache \
intl \
zip \
redis \
bcmathComposer في الصورة
انسخ ملف Composer التنفيذي من صورته الرسمية بدلًا من تنزيل مُثبّت باستخدام curl. شغّل composer install مع --no-dev و--optimize-autoloader للإنتاج، وانسخ فقط composer.json وcomposer.lock أولًا، لكي تُخزّن طبقة التبعيات مؤقتًا بشكل مستقل عن تغييرات المصدر.
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
WORKDIR /app
# Cache-friendly: deps layer invalidates only when lock changes
COPY composer.json composer.lock ./
RUN composer install \
--no-dev \
--no-scripts \
--no-autoloader \
--prefer-dist
COPY . .
RUN composer dump-autoload --optimize --classmap-authoritativeضبط php.ini
تتضمن الصورة الأساسية قوالب php.ini-production وphp.ini-development. فعّل قالب الإنتاج، ثم ضع تجاوزاتك الخاصة في conf.d؛ إذ يُدمج هذا المجلد أخيرًا، ولذلك تكون إعداداته هي السائدة.
القيم الإنتاجية الأساسية: opcache.enable=1 وopcache.validate_timestamps=0، لأن الشيفرة في الصورة غير قابلة للتغيير، وmemory_limit بقيمة مناسبة.
# Activate production ini
RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
# Custom overrides win because conf.d loads last
COPY docker/php/zz-app.ini $PHP_INI_DIR/conf.d/zz-app.iniملف تجاوز إعدادات OPcache
يمثل هذا أكبر مكسب إنتاجي منفرد. عند ضبط validate_timestamps=0، لا يتحقق PHP من ملفات الشيفرة في كل طلب؛ لكن هذا يعني أنه يجب عليك إعادة بناء الصورة لنشر التغييرات، وهو بالضبط ما نريده من الحاويات غير القابلة للتغيير.
; docker/php/zz-app.ini
memory_limit = 256M
expose_php = Off
opcache.enable = 1
opcache.enable_cli = 0
opcache.memory_consumption = 256
opcache.interned_strings_buffer = 16
opcache.max_accelerated_files = 20000
opcache.validate_timestamps = 0
opcache.preload = /app/preload.php
opcache.preload_user = www-dataالتشغيل كمستخدم غير جذر
تعرّف الصورة مسبقًا المستخدم www-data. يشكل تشغيل FPM بصلاحيات الجذر زيادة غير ضرورية في سطح الهجوم. اضبط ملكية المسارات القابلة للكتابة، مثل ذاكرة التخزين المؤقت والسجلات، ثم بدّل المستخدم باستخدام USER قبل CMD.
هل لا تزال العملية الرئيسية في FPM ترتبط بمنافذ مميّزة؟ لا — يستمع FPM على المنفذ 9000، وهو غير مميّز، ولذلك يكون التشغيل كمستخدم غير جذر مباشرًا.
# Make runtime-writable dirs owned by the runtime user
RUN chown -R www-data:www-data /app/var /app/storage 2>/dev/null || true
USER www-data
EXPOSE 9000
CMD ["php-fpm"]فحوصات الصحة
تحتاج المنسّقات إلى إشارة تفيد بأن FPM يعمل فعلًا، لا إلى مجرد وجود العملية. يمكن لـ cgi-fcgi اختبار نقطة النهاية /status أو /ping الخاصة بـ FPM. فعّل أولًا pm.status_path وping.path في مجموعة FPM.
# In www.conf pool config:
; ping.path = /ping
; ping.response = pong
# Dockerfile HEALTHCHECK using cgi-fcgi
RUN install-php-extensions @composer >/dev/null 2>&1 || true
HEALTHCHECK --interval=10s --timeout=3s --retries=3 \
CMD SCRIPT_NAME=/ping SCRIPT_FILENAME=/ping REQUEST_METHOD=GET \
cgi-fcgi -bind -connect 127.0.0.1:9000 || exit 1تجميع Dockerfile
إليكم Dockerfile متماسكًا للإنتاج بمرحلة واحدة. في الدرس التالي سنقسمه إلى مراحل متعددة لإزالة أدوات البناء. لاحظوا الترتيب: الاعتماديات ← الإعدادات ← المصدر ← التحميل التلقائي ← التبديل إلى المستخدم.
FROM php:8.3-fpm-alpine
ADD https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions /usr/local/bin/
RUN chmod +x /usr/local/bin/install-php-extensions && \
install-php-extensions pdo_mysql opcache intl zip redis
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
WORKDIR /app
RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
COPY docker/php/zz-app.ini $PHP_INI_DIR/conf.d/
COPY composer.json composer.lock ./
RUN composer install --no-dev --no-scripts --no-autoloader --prefer-dist
COPY . .
RUN composer dump-autoload --optimize --classmap-authoritative && \
chown -R www-data:www-data /app/var
USER www-data
EXPOSE 9000
CMD ["php-fpm"]التحقق من البناء
بعد البناء، أجروا فحصًا سريعًا لما أُضيف فعليًا إلى الصورة: إصدار PHP، والامتدادات المحمّلة، والتأكد من إيقاف التحقق في OPcache. يؤكد برنامج نصي سريع عبر CLI عقد التشغيل الذي يعتمد عليه تطبيقكم.
<?php
// Run inside the container: php verify.php
echo 'PHP ' . PHP_VERSION . PHP_EOL;
$required = ['pdo_mysql', 'opcache', 'intl', 'zip'];
foreach ($required as $ext) {
printf("%-12s %s\n", $ext, extension_loaded($ext) ? 'OK' : 'MISSING');
}
var_dump((bool) ini_get('opcache.enable'));
?>نظافة سياق البناء
يُبقي .dockerignore سياق البناء صغيرًا، ويمنع تسرّب الأسرار وتضخم مجلد vendor إلى الصورة وإفساد ذاكرة التخزين المؤقت. استبعدوا vendor وأنظمة التحكم في الإصدارات وملفات البيئة وأدوات التطوير المحلية.
# .dockerignore
.git
.gitignore
vendor/
node_modules/
.env
.env.*
tests/
*.md
docker-compose*.yml
storage/logs/*
var/cache/*فحص سريع
لماذا نضبط opcache.validate_timestamps=0 في صورة مخصصة للإنتاج؟
مراجعة
بنيتم صورة PHP-FPM للإنتاج: قاعدة 8.3-fpm-alpine محددة الإصدار، وثبّتّم الامتدادات المطلوبة فقط عبر البرنامج النصي للمثبّت، ونسختم Composer والاعتماديات المخزّنة مؤقتًا في طبقة مستقلة، وفعّلتم php.ini الخاص بالإنتاج مع تجاوز لإعدادات OPcache، وبدّلتم إلى www-data، وأضافتم فحصًا لصحة FPM.
العادات الأساسية: حدّدوا الإصدارات، وخزّنوا طبقة الاعتماديات مؤقتًا، وشغّلوا التطبيق كمستخدم غير جذري، وعطّلوا التحقق من الطوابع الزمنية، وأبقوا سياق البناء صغيرًا باستخدام .dockerignore.
الأسئلة الشائعة
هل درس «وضع تطبيق PHP في حاوية» مجاني؟
نعم — نص درس «وضع تطبيق PHP في حاوية» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة PHP Academy، انتقل إلى CoddyKit PRO. تتضمن دورة PHP Academy 4 دروس في المجموع.
ماذا ستتعلم في «وضع تطبيق PHP في حاوية»؟
اكتب Dockerfile جاهزًا للإنتاج لتطبيق PHP تتمرن على PHP Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ PHP Academy؟
لا تُشترط خبرة سابقة. PHP Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 1 من أصل 4.
كم من الوقت يستغرق درس «وضع تطبيق PHP في حاوية»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس PHP Academy هذا؟
نعم. كل درس في PHP Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- وضع تطبيق PHP في حاوية
- البناء متعدد المراحل والتحسين
- Docker Compose للبيئات المحلية
- التكامل والنشر المستمران باستخدام GitHub Actions