اذهب إلى المحتوى

إعداد لارافيل مع خادم Nginx وقاعدة بيانات MySQL باستخدام دوكر كومبوز Docker Compose


سامر سليمان

يُعد دوكر الحل الأكثر شيوعًا لنشر التطبيقات بسبب ما يقدمه من تبسيط لعملية تشغيل التطبيقات ونشرها في حاويات مؤقتة. يمكن استخدام دوكر لإنشاء حاويات تشكل حزمة تطبيقات LEMP مع خوادم PHP و Nginx و MySQL وإطار عمل لارافيل من أجل تسهيل عملية إنشاء التطبيقات. يسمح Docker Compose للمطورين بتعريف البنية التحتية بما فيها من خدمات وشبكات ووحدات تخزين في ملف واحد ويوفر بديلًا فعالًا لتشغيل الأمرين التاليين:

docker container create
docker container run

سننشئ تطبيقًا باستخدام إطار عمل لارافيل، مع خادم ويب Nginx وقاعدة بيانات MySQL، إذ تتواجد هذه المكونات ضمن حاويات دوكر، وسنحدد تكوين المكدس كاملًا ضمن ملف "docker-compose"، جنبًا إلى جنب مع ملفات التهيئة للغة PHP وقاعدة بيانات MySQL وخادم Nginx.

المتطلبات الأساسية

  • الوصول إلى خادم يعمل بنظام التشغيل أوبنتو Ubuntu ذي رقم إصدار 18.04 أو إلى خادم تطوير يعمل بنفس نظام التشغيل المذكور بواسطة مستخدم ذي صلاحيات إدارة sudo ولا يفضل استخدام حساب الجذر root لأسباب تتعلق بأمان الخادم، كما يُفضّل وجود جدار حماية نشط في حال العمل على خادم بعيد.
  • تثبيت الأداة دوكر على الخادم.
  • تثبيت الأداة دوكر كومبوز Docker Compose على الخادم.

الخطوة 1- تنزيل لارافيل وتثبيت اعتمادياتها

لا بُد من تنزيل أحدث إصدار متاح من لارافيل وتثبيت الاعتماديات اللازمة للمشروع البرمجي بما فيها Composer، مدير الحزم الخاص بلغة PHP في دوكر. نثبّت أحدث إصدار من لارافيل داخل مجلد laravel-app ضمن المسار الرئيسي للنظام كما يلي:

cd ~
git clone https://github.com/laravel/laravel.git laravel-app

ننتقل إلى المجلّد الجديد:

cd ~/laravel-app

نستخدم صورة composer لمشاركة المجلدات التي نحتاجها ضمن مشروع لارافيل ويفيدنا ذلك أيضًا بتجنب أعباء تثبيت الأداة Composer عمومًا ضمن الخادم. ننفذ الأمر التالي لتحقيق ذلك:

docker run --rm -v $(pwd):/app composer install

تُنشئ التعليمة السابقة باستخدام الرايات v- و rm– حاويةً تزول تلقائيًا عند الانتهاء من عملها أي عندما ينفذ المستخدم الأمرexit، وتُربط بالمسار الحالي قبل إزالتها، وسينسخ هذا محتويات مسار التطبيق "laravel-app/~" إلى الحاوية، ويضمن نسخ المجلد "vendor" الذي أنشأه Composer داخل الحاوية إلى المسار الحالي. نضبط أذونات التطبيق على أنه مستخدم غير جذر non-root:

sudo chown -R $USER:$USER ~/laravel-app

سيكون هذا مهمًا عند كتابة Dockerfile لصورة التطبيق الخاص بك في الخطوة 4، إذ سيسمح لك بالعمل مع شيفرة التطبيق الخاصة بك وتشغيل العمليات في الحاوية الخاصة بك مثل مستخدم غير جذر. بعد الانتهاء من كتابة شيفرة التطبيق الخاص بك، يمكنك الانتقال إلى تحديد خدماتك باستخدام دوكر كومبوز.

الخطوة 2- إنشاء ملف دوكر كومبوز

تُبسّط الأداة دوكر كومبوز عملية إعداد التهيئة الأساسية للبنية التحتية المستخدمة في مشروع تطوير معين مع الاحتفاظ بالتعديلات المختلفة المُطبقة والتي ندعو كل منها إصدارًا. ننشئ ملف "docker-compose" لإعداد تطبيق لارافيل يتضمن إنشاء البيئة اللازمة للتطبيق من خادم الويب وقاعدة البيانات والخدمات الأخرى.

nano ~/laravel-app/docker-compose.yml

نضبط الخدمات الثلاثة "db" و "webserver" و "app"بإضافة الشيفرة البرمجية التالية الى الملف "laravel-app/docker-compose.yml/~" مع الأخذ بالحسبان ضبط كلمات المرور جيدًا. نتأكد من وضع كلمة المرورMYSQL_ROOT_PASSWORD، بحيث تصبح هذه القيمة متغيرًا خاصًا بكامل البيئة أي ضمن خادم الويب وقاعدة البيانات وخدمات التطبيق المختلفة.

نضيف المحتوى التالي إلى الملف "laravel-app/docker-compose.yml/~":

version: '3'
services:

  #PHP Service
  app:
    build:
      context: .
      dockerfile: Dockerfile
    image: digitalocean.com/php
    container_name: app
    restart: unless-stopped
    tty: true
    environment:
      SERVICE_NAME: app
      SERVICE_TAGS: dev
    working_dir: /var/www
    networks:
      - app-network

  #Nginx Service
  webserver:
    image: nginx:alpine
    container_name: webserver
    restart: unless-stopped
    tty: true
    ports:
      - "80:80"
      - "443:443"
    networks:
      - app-network

  #MySQL Service
  db:
    image: mysql:5.7.22
    container_name: db
    restart: unless-stopped
    tty: true
    ports:
      - "3306:3306"
    environment:
      MYSQL_DATABASE: laravel
      MYSQL_ROOT_PASSWORD: your_mysql_root_password
      SERVICE_TAGS: dev
      SERVICE_NAME: mysql
    networks:
      - app-network

#Docker Networks
networks:
  app-network:
    driver: bridge

يتضمن هذا الملف تعريف الخدمات التالية:

  • "app": تحدد هذه الخدمة صورة دوكر التي ستُستخدم وتضبط مجلد العمل working_dir في الحاوية ليصبح var/www/.
  • "webserver": تحدد صورة nginx:alpine وتعيّن المنفذين 80 و 443.
  • "db": تنشئ حاوية انطلاقًا من صورة mysql:5.7.22 وتعرّف بعض متغيرات البيئة الأخرى، مثل اسم قاعدة البيانات وكلمة المرور المستخدمة والتي يجب أن تكون مناسبة. تحدد هذه الخدمة أيضًا المنافذ المستخدمة، إذ تربط المنفذ 3306 للمضيف إلى المنفذ 3306 للحاوية.

تحدد خاصية container_name اسمًا للحاوية يتوافق مع اسم الخدمة، وإذا لم تحدد هذه الخاصية، يعين دوكر اسمًا لكل حاوية من خلال الجمع بين اسم شخص مشهور تاريخيًا وكلمة عشوائية مفصولة بشرطة سفلية.

لتسهيل الاتصال بين الحاويات، تُوصل الخدمات بشبكة جسرية تسمى app-network، إذ تستخدم هذه الشبكة جسرًا برمجيًا Software Bridge يسمح للحاويات المتصلة بنفس الشبكة التواصل مع بعضها بعضًا. يثبّت برنامج تشغيل الجسر Bridge driver آليًا قواعد الاتصال الشبكي على الجهاز المضيف بحيث يضمن عزل الحاويات الموجودة على الشبكات الجسرية المختلفة عن بعضها بعضًا ما لم يرغب المستخدم بربطها معًا. يزيد ذلك من أمان التطبيق ويضمن تواصل الخدمات ذات الصلة فقط مع بعضها بعضًا، وبذلك تستخدم خدمات التطبيقات الأمامية شبكة "frontend" وتستخدم خدمات الواجهة الخلفية شبكة "backend".

الخطوة 3- ديمومة البيانات

يتضمن دوكر عدة مزايا تضمن احتفاظ أو ديمومة البيانات Data Persistence، ففي تطبيقنا نستخدم وحدات التخزين Volumes وحوامل الربط bind mounts لضمان احتفاظ البيانات ضمن قاعدة البيانات وملفات التطبيق والتهيئة العامة؛ إذ توفر وحدات التخزين المرونة للنسخ الاحتياطي والاستمرار الى ما بعد دورة حياة الحاوية؛ وتسهل حوامل الربط تغيير التعليمات البرمجية أثناء التطوير، مما يزامن إجراء التغييرات على ملفات المضيف والمجلدات في الحاوية لتنعكس هذه التغييرات فور اعتمادها على التطبيق.

تحذير: تتيح حوامل الربط إمكانية تغيير نظام ملفات المضيف من خلال العمليات التي تعمل في الحاوية، بما في ذلك إنشاء أو تعديل أو حذف ملفات النظام أو المجلدات المهمة. على الرغم من الفائدة الكبيرة لهذه الميزة إلا أنّ لها انعكاسات أمنية يمكن أن تؤثر على العمليات التي لا تتعلق بدوكر على النظام المضيف لذلك يتوجب استخدام حوامل الربط بعناية.

ننشئ وحدة تخزين تدعى dbdata في خدمة db من أجل احتفاظ قاعدة البيانات MySQL بوضع البيانات التالية ضمن ملف docker-compose.yml

...
#MySQL Service
db:
  ...
    volumes:
      - dbdata:/var/lib/mysql
    networks:
      - app-network
  ...

تضمن وحدة التخزين dbdata الاحتفاظ بالمحتوى في المجلد ‎/var/lib/mysql وبذلك يمكن إيقاف وإعادة تشغيل خدمة db دون فقدان البيانات. نضيف في نهاية ملف التعريف التالي لوحدة التخزين dbdata:

...
#Volumes
volumes:
  dbdata:
    driver: local

نضيف حامل الربط إلى خدمة db لملفات تهيئة قاعدة البيانات MySQL التي ننشئها لاحقًا:

...
#MySQL Service
db:
  ...
    volumes:
      - dbdata:/var/lib/mysql
      - ./mysql/my.cnf:/etc/mysql/my.cnf
  ...

يربط حامل الربط الملف "‎~/laravel-app/mysql/my.cnf" بالملف "‎/etc/mysql/my.cnf" داخل الحاوية، ومن ثم نضيف حوامل الربط إلى خدمة webserver، إذ توجد خدمتان، تعود الأولى للشيفرة البرمجية للتطبيق والأخرى لتعريف تهيئة خادم Nginx الذي سننشئه في الخطوة 6:

#Nginx Service
webserver:
  ...
  volumes:
      - ./:/var/www
      - ./nginx/conf.d/:/etc/nginx/conf.d/
  networks:
      - app-network

يربط حامل الربط الأول الشيفرة البرمجية للتطبيق في مجلد التطبيق "‎~/laravel-app" بالمجلد "‎/var/www" داخل الحاوية، ويحمّل ملف التهيئة الذي نضيفه إلى المجلد "‎~/laravel-app/nginx/conf.d/‎" إلى المجلد "/etc/nginx/conf.d/" في الحاوية، وبذلك نضيف أو نعدل محتويات مجلد التهيئة حسب الحاجة. نضيف حوامل الربط إلى الخدمة app على النحو التالي:

#PHP Service
app:
  ...
  volumes:
       - ./:/var/www
       - ./php/local.ini:/usr/local/etc/php/conf.d/local.ini
  networks:
      - app-network

تربط الخدمة appمجلد التطبيق "laravel-app/~" الذي يحتوي على الشيفرة البرمجية للتطبيق بالمجلد "var/www" في الحاوية لتسريع عملية التطوير، نظرًا لأن أية تغييرات تحصل على مجلد التطبيق المحلي تنعكس على الفور داخل الحاوية. تربط الخدمة أيضًا ملف تهيئة خادم PHP الموجود في المسار "laravel-app/php/local.ini/~" بالملف "usr/local/etc/php/conf.d/local.ini/" داخل الحاوية. يصبح محتوى الملف "docker-compose.yml"على النحو التالي:

version: '3'
services:

  #PHP Service
  app:
    build:
      context: .
      dockerfile: Dockerfile
    image: digitalocean.com/php
    container_name: app
    restart: unless-stopped
    tty: true
    environment:
      SERVICE_NAME: app
      SERVICE_TAGS: dev
    working_dir: /var/www
    volumes:
      - ./:/var/www
      - ./php/local.ini:/usr/local/etc/php/conf.d/local.ini
    networks:
      - app-network

  #Nginx Service
  webserver:
    image: nginx:alpine
    container_name: webserver
    restart: unless-stopped
    tty: true
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./:/var/www
      - ./nginx/conf.d/:/etc/nginx/conf.d/
    networks:
      - app-network

  #MySQL Service
  db:
    image: mysql:5.7.22
    container_name: db
    restart: unless-stopped
    tty: true
    ports:
      - "3306:3306"
    environment:
      MYSQL_DATABASE: laravel
      MYSQL_ROOT_PASSWORD: your_mysql_root_password
      SERVICE_TAGS: dev
      SERVICE_NAME: mysql
    volumes:
      - dbdata:/var/lib/mysql/
      - ./mysql/my.cnf:/etc/mysql/my.cnf
    networks:
      - app-network

#Docker Networks
networks:
  app-network:
    driver: bridge
#Volumes
volumes:
  dbdata:
    driver: local

نحفظ الملف بعد الانتهاء من إجراء التعديلات السابقة. نستطيع الآن باستخدام الأداة دوكر كومبوز بناء الصورة المخصًصة التي أنشأناها لتطبيقنا

الخطوة 4- إنشاء ملف Dockerfile

يسمح دوكر لك بتخصيص البيئة داخل الحاويات الفردية باستخدام ملف Dockerfile، الذي يمكّننا من إنشاء صور مخصصة يمكننا استخدامها لتثبيت البرنامج الذي يتطلبه التطبيق وضبط الإعدادات بناءً على المتطلبات. يمكن دفع الصور المخصصة التي ننشئها إلى Docker Hub أو أي سجل خاص آخر. نضع الملف Dockerfile ضمن "laravel-app/~"، ولإنشائه ننفّذ الأمر التالي:

nano ~/laravel-app/Dockerfile

يحدد ملف دوكر هذا الصورة الأساسية ويحدد الأوامر والإرشادات اللازمة لبناء صورة تطبيق لارافيل. نضيف الشيفرة البرمجية التالية إلى الملف:

FROM php:7.2-fpm

# Copy composer.lock and composer.json
COPY composer.lock composer.json /var/www/

# Set working directory
WORKDIR /var/www

# Install dependencies
RUN apt-get update && apt-get install -y \
    build-essential \
    libpng-dev \
    libjpeg62-turbo-dev \
    libfreetype6-dev \
    locales \
    zip \
    jpegoptim optipng pngquant gifsicle \
    vim \
    unzip \
    git \
    curl

# Clear cache
RUN apt-get clean && rm -rf /var/lib/apt/lists/*

# Install extensions
RUN docker-php-ext-install pdo_mysql mbstring zip exif pcntl
RUN docker-php-ext-configure gd --with-gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ --with-png-dir=/usr/include/
RUN docker-php-ext-install gd

# Install composer
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer

# Add user for laravel application
RUN groupadd -g 1000 www
RUN useradd -u 1000 -ms /bin/bash -g www www

# Copy existing application directory contents
COPY . /var/www

# Copy existing application directory permissions
COPY --chown=www:www . /var/www

# Change current user to www
USER www

# Expose port 9000 and start php-fpm server
EXPOSE 9000
CMD ["php-fpm"]

ينشئ ملف Dockerfile صورةً جديدةً على أساس صورة دوكر php:7.2-fpm المبنية على نظام دبيان Debian، ويثبّت أداة الإدارة PHP-FPM من أجل التحكم بتطبيق PHP FastCGI، كما يثبت حزم لارافيل التالية: mcrypt و pdo_mysql و mbstring و imagick مع composer.

يوجه أمر التوجيه RUN الأوامر لتحديث الإعدادات وتثبيتها وتكوينها داخل الحاوية، بما في ذلك إنشاء مستخدم مخصص ومجموعة تسمّى www. تحدد تعليمة WORKDIR المجلد "‎/var/www" على أنه مجلد العمل الأساسي للتطبيق.

يخفف إنشاء مستخدم ومجموعة بأذونات مقيدة الخطر الذي ينتج عن الثغرات الأمنية الناتجة عن تشغيل حاويات دوكر. عندما تبدأ الحاوية للعمل فإنها تستخدم حساب الجذر افتراضيًا ما لم يُحدّد مستخدم آخر في ملف الإعداد الخاص بالصورة. يمتلك هذا الحساب الأذونات المطلقة على الجهاز المضيف والحاويات معًا. بدلاً من تشغيل هذه الحاوية باستخدام المستخدم الجذر، ننشئ مستخدمwww يمتلك أذونات القراءة والكتابة على المجلد "var/www/" بفضل تعليمات COPYالتي نستخدمها مع العلامة chown-- لنسخ أذونات مجلد التطبيق. يعرض الأمر EXPOSE المنفذ 9000 في الحاوية لخادم "php-fpm" ويحددCMD الأمر الذي يجب تشغيله بمجرد إنشاء الحاوية، وهو هنا "php-fpm"، الذي سيشغّل الخادم.

الخطوة 5- إعداد خادم PHP

نُعد خدمة PHP لتعمل مثل معالج PHP للطلبات الواردة من Nginx. ولضبط ذلك ننشئ ملف "local.ini" داخل مجلد "php" الذي ربطناه بالملف "usr/local/etc/php/conf.d/local.ini/" داخل الحاوية في خطوة سابقة، إذ يسمح هذا الملف بتجاوز ملف "php.ini" الافتراضي الذي يفحصه خادم PHP عندما نبدأ بالعمل. ننشئ مجلد php بالأمر التالي:

mkdir ~/laravel-app/php

نحرر الملف"local.ini" باستخدام محرر النصوص المفضل وبحالة المحرر نانو nano ننفذ الأمر التالي:

nano ~/laravel-app/php/local.ini

نلصق داخل الملف الأوامر التالية لتحديد أقصى حجم لتحميل الملفات:

upload_max_filesize=40M
post_max_size=40M

تعيّن كل من الخاصتين upload_max_filesize و post_max_size الحجم الأقصى المسموح به لرفع الملفات إلى الخادم، ويوضح تعديل هاتين الخاصتين إمكانية إعداد الملف"php.ini" انطلاقًا من تعديل الملف "local.ini"، ويمكن إضافة أية إعدادات خاصة بخادم PHP نرغب بتطبيقها ضمن هذا الملف. نحفظ الملف بعد إجراء التعديلات السابقة ومن ثم نغلق محرر النصوص، وبهذا ينتهي إعداد خادم PHP وننتقل لإعداد خادم Nginx.

الخطوة 6- إعداد خادم Nginx

يسمح إعداد خدمة PHP بتعديل خدمة Nginx لاستخدام PHP-FPM مثل خادم FastCGI لتقديم خدمة المحتوى الديناميكي، إذ يعتمد خادم FastCGI على بروتوكول ثنائي binary protocol لربط البرامج التفاعلية بخادم الويب. ننشئ ملف "app.conf" مع ضبط الخدمة في المجلد /laravel-app/nginx/conf.d/~ من أجل إعداد Nginx. ننشئ المجلد "‎/nginx/conf.d" بتنفيذ الأمر التالي:

mkdir -p ~/laravel-app/nginx/conf.d

ننشئ بعدها الملف "app.conf" بتنفيذ الأمر:

nano ~/laravel-app/nginx/conf.d/app.conf

نضيف المحتوى التالي لإعداد خادم Nginx:

server {
    listen 80;
    index index.php index.html;
    error_log  /var/log/nginx/error.log;
    access_log /var/log/nginx/access.log;
    root /var/www/public;
    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass app:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
    }
    location / {
        try_files $uri $uri/ /index.php?$query_string;
        gzip_static on;
    }
}

يتضمن إعداد كتلة الخادم الموجهات directives الضرورية لإعداد خادم الويب Nginx إذ تدل هذه الموجهات إلى ما يلي:

  • listen: يحدد هذا الموجه المنفذ الذي يستمع الخادم إليه من أجل استقبال الطلبات.
  • error_log و access_log: تحدد هذه الموجّهات الملفات لكتابة السجلات المتعلقة بالنفاذ للخادم والأخطاء التي تحدث.
  • root: يعيّن هذا الموجه مسار المجلد الجذر root، ويشكّل المسار الكامل لأي ملف مطلوب على نظام الملفات المحلي.

يحدد الموجه fastcgi_pass أن الخدمة app تستمع إلى مقبس TCP على المنفذ "9000" وهذا يجعل خادم PHP-FPM يستمع عبر الشبكة بدلاً من مقبس Unix. على الرغم من تفوق مقبس Unix من حيث السرعة بصورةٍ طفيفة على مقبس TCP، إلا أنه لا يحتوي على بروتوكول شبكة وبالتالي يتخطى مكدس الشبكة.

يناسب مقبس Unix الحالات التي يتواجد فيها أكثر من مضيف على جهاز واحد، ولكن في الحالات التي يكون لدينا خدمات تعمل على مجموعة موزعة من المضيفات، فيوفّر مقبس TCP ميزة السماح لك بالاتصال بالخدمات الموزعة. نظرًا لأن حاوية التطبيق app الخاصة تعمل على مضيف مختلف من حاوية webserver، يكون مقبس TCP أكثر ملاءمةً للضبط الذي نستخدمه.

الخطوة 7- إعداد قاعدة بيانات MYSQL

ننشئ ملف "my.cnf" في المجلد "mysql" الذي ربطناه بالملف "‎/etc/mysql/my.cnf" داخل الحاوية بالخطوة 2. يسمح حامل الربط هذا بتجاوز ملف "my.cnf" الأساسي عند الطلب واستخدام الملف الذي نجري التعديلات عليه. نضيف الإعدادات التالية إلى ملف "my.cnf" لتفعيل سجل الاستعلام العام وتحديد ملف السجل. ننشئ أولًا المجلد "mysql" بتنفيذ الأمر التالي:

mkdir ~/laravel-app/mysql

ومن ثم ننشئ الملف "my.cnf" بتنفيذ الأمر التالي:

nano ~/laravel-app/mysql/my.cnf

نضيف المحتوى التالي إلى الملف:

[mysqld]
general_log = 1
general_log_file = /var/lib/mysql/general.log

نفعّل سجل الاستعلام بوضع القيمة 1 للخيار general_log ونحدد المكان الذي نريد حفظ السجل به بتحديد قيمة الخيار general_log_file.

الخطوة 8- تعديل إعدادات البيئة وتشغيل الحاويات

حددنا جميع الخدمات في ملف "docker-compose" وأنشأنا ملفات الضبط لهذه الخدمات وحان الوقت لتشغيل التطبيق. ننشئ نسخةً من الملف "env.example." الذي يولّده لارافيل افتراضيًا ونسمّي النسخة التي نعمل عليها حاليًا "env." بتنفيذ الأمر التالي:

cp .env.example .env

نعدل على الملف الذي جرى نسخه لنضع البيانات الخاصة بحاوية تطبيقنا باستخدام محرر النصوص المفضل:

nano .env

نبحث عن الكتلة التي تحدد الاتصال مع قاعدة البيانات DB_CONNECTION ونعدل ضمنها الحقول التالية:

  • DB_HOST: عنوان حاوية قاعدة بيانات db.
  • DB_DATABASE: اسم قاعدة بيانات لارافيل.
  • DB_USERNAME: اسم المستخدم الذي نستخدمه لقاعدة البيانات، نستخدم "laraveluser" ويمكن استخدام أي اسم آخر نرغب به.
  • DB_PASSWORD كلمة المرور للاتصال بقاعدة البيانات.

ويكون ملف "env." بالشكل التالي:

DB_CONNECTION=mysql
DB_HOST=db
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=laraveluser
DB_PASSWORD=your_laravel_db_password

احفظ التغييرات وأغلق المحرر.

ننفذ الآن أمر بدء تشغيل جميع الحاويات وإنشاء وحدات التخزين وإعداد الشبكات وتوصيلها:

docker-compose up -d

تُحمّل جميع صور دوكر الضرورية عند تشغيل الأمر السابق لأول مرة، وتستغرق بعض الوقت إذا لم تكن موجودة مسبقًا على الجهاز المحلي، وبمجرد تحميل الصور وتخزينها يُنشئ compose الحاويات اللازمة. تضفي الراية d- الطابع الخفي على العملية وتشغّلها في الخلفية. نستعرض الحاويات التي تعمل في هذه اللحظة بتنفيذ الأمر:

docker ps

يظهر خرجٌ مشابه للخرج التالي ما لم توجد حاويات أخرى إضافية غير "app" و "webserver" و "db" ضمن البيئة:

CONTAINER ID        NAMES               IMAGE                             STATUS              PORTS
c31b7b3251e0        db                  mysql:5.7.22                      Up 2 seconds        0.0.0.0:3306->3306/tcp
ed5a69704580        app                 digitalocean.com/php              Up 2 seconds        9000/tcp
5ce4ee31d7c0        webserver           nginx:alpine                      Up 2 seconds        0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tc

يُعد CONTAINER ID معرفًا فريدًا لكل حاوية ويعرض NAMES اسم الحاوية ويعرض IMAGE اسم الصورة ويوفر الحقل STATUS معلومات حول الحاوية فيما إذا كانت تعمل أو يُعاد تشغيلها أو متوقفة نهائيًا عن العمل. نستخدم الأمر docker-compose exec لتوليد مفتاح التطبيق لتطبيق لارافيل وننسخه للملف "env." ليضمن حماية جلسات المستخدم وتأمين البيانات المشفرة بتنفيذ ما يلي:

docker-compose exec app php artisan key:generate

نشغّل الأمر التالي:

docker-compose exec app php artisan config:cache

تُحمّل إعدادات الضبط إلى الملف "‎/var/www/bootstrap/cache/config.php" ضمن الحاوية، وبزيارة الرابط التالي "http://yourserverip" في المتصفح نرى الصفحة التالية:

laravel_home

مع تشغيل الحاويات الخاصة بك ومعلومات الضبط في مكانها الصحيح، يمكننا الانتقال إلى تكوين معلومات المستخدم الخاصة بك لقاعدة بيانات "laravel" على حاوية "db".

الخطوة 9- إنشاء مستخدم لقاعدة البيانات MySQL

يُنشئ MySQL افتراضيًا حساب الجذر root لأغراض إدارية، إذ يتمتع هذا المستخدم بصلاحيات غير محدودة على خادم قاعدة البيانات. نتجنّب استخدام هذا الحساب عند التعامل مع قاعدة البيانات وبدلاً من ذلك ننشئ مستخدم قاعدة بيانات مخصص لقاعدة بيانات تطبيق لارافيل. ننفذ الأمر التالي في حاوية "db":

docker-compose exec db bash

نسجّل دخول الى حساب الجذر الخاص بقاعدة البيانات MySQL داخل الحاوية:

root@c31b7b3251e0:/# mysql -u root -p

نُدخل كلمة المرور المُعينة لحساب الجذر الخاص بقاعدة البيانات MySQL أثناء التثبيت في الملف "docker-compose". نتحقق من قاعدة البيانات "laravel" التي حددناها في الملف "docker-compose" بتنفيذ الأمر التالي:

mysql> show databases;

يظهر خرج يشابه الخرج التالي:

+--------------------+
| Database           |
+--------------------+
| information_schema |
| laravel            |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
5 rows in set (0.00 sec)

ننشئ حساب المستخدم الذي يُسمح له بالوصول إلى قاعدة البيانات ونسميه "laraveluser". نتأكد من تطابق الاسم وكلمة المرور مع الاسم وكلمة المرور الموجودين في الملف "env.":

mysql> GRANT ALL ON laravel.* TO 'laraveluser'@'%' IDENTIFIED BY 'your_laravel_db_password';

نمسح الصلاحيات لنُعلم خادم MySQL بالتعديلات التي أجريناها:

mysql> FLUSH PRIVILEGES;

نخرج من واجهة الأوامر التفاعلية الخاصة بقاعدة البيانات MySQL والحاوية:

mysql> EXIT;
root@c31b7b3251e0:/# exit

الخطوة 10- تهجير البيانات والعمل باستخدام طرفية Tinker

نجح إعداد التطبيق إلا أنّ قاعدة البيانات لا تتضمن أية محتوى حتى الآن. نستطيع إدخال بعض المحتوى يدويًا أو الاستفادة من تهجير قواعد البيانات لملئها بمعلومات بصورةٍ سريعة. تُهجّر البيانات باستخدام طرفية tinker، التي تُشغّل الطرفية PsySH عند تحميل تطبيق لارافيل الأولي. تُستخدم الطرفية PsySH مثل واجهة تطوير في وقت التشغيل كما أنها تعمل مثل مصحح أخطاء تفاعلي للغة PHP. تُعد طرفية Tinker بيئة اختبار REPL خاصة لإطار العمل لارافيل. يسمح استخدام الأمر tinker بالتفاعل مع تطبيق لارافيل باستخدام سطر الأوامر في صدفة تفاعلية وتنفيذ الأوامر عليها مباشرةً. نختبر الاتصال بقاعدة البيانات MySQL عن طريق تشغيل أمر artisan migrate، الذي يُنشئ جدول تهجير في قاعدة البيانات داخل الحاوية ويتحقق ذلك بتنفيذ الأمر:

docker-compose exec app php artisan migrate

ويظهر الخرج الذي يؤكد نجاح التهجير بالشكل التالي:

Migration table created successfully.
Migrating: 2014_10_12_000000_create_users_table
Migrated:  2014_10_12_000000_create_users_table
Migrating: 2014_10_12_100000_create_password_resets_table
Migrated:  2014_10_12_100000_create_password_resets_table

ننفذ الاستعلام التالي للتحقق من وجود اتصال بقاعدة البيانات على نحوٍ صحيح باستخدام الأمر tinker:

docker-compose exec app php artisan tinker

اختبر اتصال MySQL عن طريق الحصول على البيانات التي هجّرناها للتو:

\DB::table('migrations')->get();

يظهر خرج مشابه للخرج التالي مع نجاح العملية:

=> Illuminate\Support\Collection {#2856
     all: [
       {#2862
         +"id": 1,
         +"migration": "2014_10_12_000000_create_users_table",
         +"batch": 1,
       },
       {#2865
         +"id": 2,
         +"migration": "2014_10_12_100000_create_password_resets_table",
         +"batch": 1,
       },
     ],
   }

تُستخدم tinker للتفاعل مع قواعد البيانات المختلفة وتنفيذ التجارب على النماذج والخدمات المرتبطة بها.

الخاتمة

أنشأنا في هذا المقال تطبيقًا برمجيًا باستخدام مكدس LEMP يعمل على الخادم المحلي واختبرناه من خلال الوصول إلى صفحة الترحيب في لارافيل وأنشأنا عملية تهجير لقاعدة بيانات MySQL. يمكن استخدام هذه الخطوات العملية في إنشاء تطبيق حقيقي يعتمد على المكونات السابقة.

ترجمة وبتصرف للمقال How To Set Up Laravel, Nginx, and MySQL with Docker Compose لصاحبه Faizan Bashir.

اقرأ أيضًا


تفاعل الأعضاء

أفضل التعليقات

لا توجد أية تعليقات بعد



انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أضف تعليق

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • أضف...