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

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

نعمل في هذا المقال على استخدام الأداة دوكر كومبوز Docker Compose لاحتواء تطبيق لارافيل لتطويره ضمن بيئة مستقلة خاصة به. نحصل على تطبيق لارافيل توضيحي موزّع على ثلاث حاويات خدمة معزولة عن بعضها يعضًا على النحو التالي:

  • خدمة تطبيق "app" تعمل على PHP7.4-FPM.
  • خدمة قاعدة بيانات "db" تحتوي خادم MySQL 5.7.
  • خدمة "nginx" تستخدم خدمة "app" من أجل تحليل شيفرة برمجية بلغة PHP قبل تقديم تطبيق لارافيل للمستخدم النهائي.

تُستخدم وحدات التخزين المشتركة Shared Volumes من أجل مزامنة ملفات التطبيق وذلك لتطوير تطبيق بسيط وتصحيح الأخطاء بسهولة؛ كما تُستخدم أوامر docker-compose exec لتشغيل تعليمات Composer و artisan في حاوية التطبيق.

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

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

الخطوة 1- الحصول على التطبيق التوضيحي

نبدأ بتنزيل تطبيق لارافيل التوضيحي من مخزن غيت هب Github وننتقل إلى الفرع tutorial-01، الذي يتضمن تطبيقًا بسيطًا مبنيًا باستخدام لارافيل. نعتمد في هذا العمل على الإصدار tutorial-1.0.1 والذي نحملّه ضمن المجلد الأساسي للمستخدم بتنفيذ الأمر:

cd ~
curl -L https://github.com/do-community/travellist-laravel-demo/archive/tutorial-1.0.1.zip -o travellist.zip

يبدأ تنزيل الملف المضغوط بصيغة "zip" لذلك يجب عند انتهاء التحميل فك الضغط باستخدام الأمر unzip بعد التأكد من تحديث الحزم الخاصة بنظام التشغيل ما لم تكن محدّثة مؤخرًا. ننفذ الأمر التالي:

sudo apt update
sudo apt install unzip

ننفذ الأوامر التالي لفك ضغط الملف الذي حملناه ونعيد تسمية المجلد لاسم مناسب لسهولة الوصول إليه:

unzip travellist.zip
mv travellist-laravel-demo-tutorial-1.0.1 travellist-demo

ننتقل إلى المجلّد "travellist-demo" بتنفيذ الأمر:

cd travellist-demo

الخطوة 2- إعداد ملف الضبط الخاص بالتطبيق

نجد عادةً ملفات الضبط الخاصة بلارافيل ضمن المجلد "config" داخل المجلد الجذر للتطبيق. يحتوي الملف "env." معلومات الضبط المتعلقة بالبيئة، مثل بيانات الاعتماد وكلمات المرور وأية معلومات تختلف بين عمليات نشر التطبيقات، لذلك لا يُضمّن هذا الملف ضمن ملفات التحكم بالإصدارات لكي لا تنتشر هذه المعلومات لجميع المستخدمين الذين يستخدمون صورة التطبيق لاحقًا.

تحذير: يحتوي ملف تهيئة البيئة على معلومات حساسة حول الخادم، بما في ذلك بيانات اعتماد قاعدة البيانات ومفاتيح الأمان، لهذا السبب لا يجب أبدًا مشاركة هذا الملف علنًا.

توجد أولويةٌ للقيم الموجودة في الملف "env." على القيم الموجودة في ملفات التهيئة الأخرى الموجودة في المجلد "config". تتطلب كل عملية تثبيت في بيئة جديدة ملف بيئة مخصص لتعريف معلومات جديدة، مثل إعدادات الاتصال في قاعدة البيانات وخيارات التصحيح ورابط للتطبيق، إضافةً إلى بقية العناصر أو المعلومات التي تختلف تبعًا للبيئة التي يعمل بها التطبيق.

ننشئ ملف "env." جديد لضبط خيارات التهيئة لبيئة التطوير التي نُعدها، ويمكننا نسخ الملف "example.env" المتاح افتراضيًا مع أي تطبيق لارافيل بتنفيذ الأمر:

cp .env.example .env

نحرر الملف باستخدام محرر النصوص نانو nano أو باختيار محرر النصوص المفضّل:

nano .env

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

APP_NAME=Travellist
APP_ENV=dev
APP_KEY=
APP_DEBUG=true
APP_URL=http://localhost:8000

LOG_CHANNEL=stack

DB_CONNECTION=mysql
DB_HOST=db
DB_PORT=3306
DB_DATABASE=travellist
DB_USERNAME=travellist_user
DB_PASSWORD=password
...

نستطيع تغيير القيم الخاصة ببقية المتغيرات، مثل اسم قاعدة البيانات وكلمة المرور واسم المستخدم الذين سيُستخدمان عند إعداد الملف "docker-compose.yml" من أجل تهيئة الخدمات. نضغط على الاختصار "CTRL+X" ثم الحرف "Y" وأخيرًا زر الإدخال "Enter" بعد الانتهاء من تعديل الملف.

الخطوة 3 - إعداد ملف دوكر الخاص بالتطبيق

تستند خدمتا MySQL و Nginx على الصور الافتراضية التي يمكن الحصول عليها من Docker Hub، لكن سنحتاج في مثالنا إلى إنشاء صورة مخصصة لحاوية التطبيق وسننشئ ملف Dockerfile جديد لذلك.

تعتمد صورة التطبيق travillist على صورة PHP الرسمية ذات الاسم php:7.4-fpm والمتاحة ضمن مخزن دوكر هب Docker Hub. نحتاج تثبيت بعض حزم PHP الإضافية باستخدام أداة إدارة الاعتمادية Composer.

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

nano Dockerfile

ننسخ المحتوى التالي إلى ملف Dockerfile:

FROM php:7.4-fpm

# Arguments defined in docker-compose.yml
ARG user
ARG uid

# Install system dependencies
RUN apt-get update && apt-get install -y \
    git \
    curl \
    libpng-dev \
    libonig-dev \
    libxml2-dev \
    zip \
    unzip

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

# Install PHP extensions
RUN docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd

# Get latest Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer

# Create system user to run Composer and Artisan Commands
RUN useradd -G www-data,root -u $uid -d /home/$user $user
RUN mkdir -p /home/$user/.composer && \
    chown -R $user:$user /home/$user

# Set working directory
WORKDIR /var/www

USER $user

نحفظ الملف بعد الانتهاء من التعديل عليه. يبدأ الملف بتحديد الصورة الأساس التي نستخدمها وهي في حالة الملف السابق php:7.4-fpm. نثبت أداة Composer بنسخ الشكل التنفيذي الخاص بالأمر "composer" والمتاح ضمن أحدث صورة رسمية إلى صورة التطبيق الخاص بنا.

ننشئ مستخدم نظام جديد ونبدأ بإعداد المتغيرينuser و uid الذين عرّفناهما في بداية الملف Dockerfile، إذ تُمرَّر هذه المتغيرات إلى الحاوية باستخدام الأداة دوكر كومبوز في وقت البناء.

نحدد مسار العمل الافتراضي "var/www/" ونسجّل الدخول بواسطة المستخدم الذي أنشأناه مؤخرًا للتأكد من الاتصال بقاعدة البيانات بصفة مستخدم عادي وأننا في المسار الصحيح عند استخدام الأوامر المختلفة، مثل أوامر"composer" و "artisan" في حاوية التطبيق.

الخطوة 4 - إعداد ضبط Nginx وملفات إفراغ قاعدة البيانات

يجب مشاركة ملفات الضبط والتهيئة مع حاويات الخدمة عند إنشاء بيئة تطوير باستخدام أداة دوكر كومبوزلإعداد أو التمهيد لهذه الخدمات، إذ يسهّل ذلك إجراء التعديلات على ملفات الضبط وضبط البيئة أثناء تطوير التطبيق. ننشئ مجلد ونضع به الملفات التي تستخدم في تهيئة وبناء حاويات الخدمة. ننشئ مجلد "docker-compose/nginx" ونضع به ملف "travellist.conf" الذي يهيئ آلية تقديم التطبيق وذلك بتنفيذ الأمر التالي:

mkdir -p docker-compose/nginx

نعدّل محتوى الملف "travellist.conf" باستخدام محرر النصوص المفضل عبر تنفيذ الأمر التالي:

nano docker-compose/nginx/travellist.conf

نضيف الشيفرة البرمجية التالية داخله:

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;
    }
}

يضبط الملف السابق خادم Nginx ويجبره على الاستماع للمنفذ 80 ويستخدم الصفحة index.php لتكون صفحة الدليل الأساسية للتطبيق. نضبط المسار الجذر Root للمستند ليصبح "‎/var/www/public" ونضبط خادم Nginx ونجبره على استخدام المنفذ "9000" لمعالجة الملفات ذات اللاحقة "php.*". احفظ الملف وأغلقه عند الانتهاء من التعديل.

سنشارك من أجل إكمال إعداد قاعدة البيانات MYSQL ملفًا يتضمن محتوى قاعدة البيانات database dump، الذي سيُستورد محتواه إلى قاعدة البيانات عندما نهيئ الحاوية لأول مرة، وتتوفر هذه الميزة في MySQL 5.7 التي نستخدمها في حاوية التطبيق. ننشئ مجلدًا جديدًا لتهيئة ملفات قاعدة البيانات MySQL داخل المجلد "docker-compose" بتنفيذ الأمر التالي:

mkdir docker-compose/mysql

ننشئ ملف "sql." جديد بتنفيذ الأمر:

nano docker-compose/mysql/init_db.sql

يعتمد ملف قاعدة البيانات MySQL dump التالي على قاعدة البيانات المُنشأة في دليل لارافيل بالاعتماد على LEMP، إذ يُنشئ جدولًا اسمه places في قاعدة البيانات ثم سيملأ محتوياته بمجموعة من العينات.

اكتب الشيفرة البرمجية التالية في الملف "db_init.sql" ليصبح بالشكل التالي:

DROP TABLE IF EXISTS `places`;

CREATE TABLE `places` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
  `visited` tinyint(1) NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

INSERT INTO `places` (name, visited) VALUES ('Berlin',0),('Budapest',0),('Cincinnati',1),('Denver',0),('Helsinki',0),('Lisbon',0),('Moscow',1),('Nairobi',0),('Oslo',1),('Rio',0),('Tokyo',0);

يتضمن الجدول places ثلاثة حقول id و name و visited وهي على الترتيب معرّف خاص بكل مكان واسم المكان ومتغير يشير إلى زيارة المكان مسبقًا أم لا، ويمكن تعديل أسماء الحقول وإضافة حقول جديدة عند الحاجة.

الخطوة 5 - إنشاء بيئة متعددة الحاويات بواسطة دوكر كومبوز

تُنشئ الأداة دوكر كومبوز بيئات متعددة الحاويات للتطبيقات التي تعمل على دوكر، كما تستخدم تعريفات الخدمة لبناء بيئات قابلة للتخصيص بالكامل مع حاويات متعددة يمكنها مشاركة الشبكات وأحجام البيانات، مما يتيح التكامل السلس بين مكونات التطبيق المختلفة.

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

نحدد ثلاث خدمات مختلفة ضمن ملف "docker-compose.yml"، هي: "app" و "db" و "nginx"؛ إذ تُنشئ خدمة "app" صورةً تسمى "travellist" بناءً على ملف Dockerfile الذي أنشأناه سابقًا، وتُشغّل الحاوية التي تحددها هذه الخدمة خادم "php-fpm" لتحليل شيفرات PHP وتُرسل النتائج مرةً أخرى إلى خدمة "nginx، التي تعمل على حاوية منفصلة. تحدد خدمة "mysql" حاويةً تُشغل خادم MySQL 5.7. تتصل هذه الخدمات فيما بينها باستخدام شبكة جسر أسميناها "travellist".

تُزامن ملفات التطبيق على كل من الخدمتين "app" و "nginx" عبر حوامل الربط، التي تُعد مفيدةً في بيئات التطوير لأنها تتيح مزامنةً ثنائية الاتجاه بين الجهاز المضيف والحاويات. نُنشئ ملفًا جديدًا باسم "docker-compose.yml" في مجلد الجذر للتطبيق بتنفيذ الأمر:

nano docker-compose.yml

يبدأ ملف "docker-compose.yml" التقليدي برقم الإصدار يليها تعريف الخدمات "services" الخاصة بالتطبيق، كما تُعرَّف الشبكات التي يشاركها التطبيق في نهاية الملف. إذًا، يكون محتوى هذا الملف كما يلي:

version: "3.7"
services:


networks:
  travellist:
    driver: bridge

سنعدّل الآن عقدة "services" لتتضمن خدمات "app" و "db" و "nginx".

خدمة التطبيق app

تُعِد خدمة "app" حاويةً باسم "travellist-app" وتبني صورة دوكر جديدة بناءً على Dockerfile الموجود في نفس مسار الملف "docker-compose.yml" وتُحفظ الصورة محليًا باسم "travellist". نحتاج تواجد ملفات التطبيق ضمن حاوية التطبيق "app" حتى ولو كانت هذه الملفات موجودةً في جذر المستند الذي جرى تقديمه على أنه تطبيق موجود في حاوية "nginx"، ونحتاج ذلك من أجل تنفيذ أوامر "artisan" الخاصة بإطار عمل لارافيل على هذه الملفات. نضيف البيانات التالية إلى الملف "docker-compose.yml":

app:
    build:
      args:
        user: sammy
        uid: 1000
      context: ./
      dockerfile: Dockerfile
    image: travellist
    container_name: travellist-app
    restart: unless-stopped
    working_dir: /var/www/
    volumes:
      - ./:/var/www
    networks:
      - travellist

تحقق هذه الإعدادات ما يلي:

  • build: يعلِم هذا الضبط أداة دوكر كومبوز ببناء صورة محلية لخدمة التطبيق، باستخدام المسار المحدد context وملف Dockerfile للحصول على التعليمات. تُحقن المتغيرات user و uid في ملف Dockerfile لتخصيص أوامر إنشاء المستخدم في وقت الإنشاء.
  • image: تُعدّ الاسم الذي يستخدم الصورة قيد الإنشاء.
  • container_name: تُعِدّ اسم الحاوية لهذه الخدمة.
  • restart: يعيد التشغيل دائمًا، ما لم يحدث إيقافٌ الخدمة.
  • working_dir: يعيّن المجلّد الافتراضي لهذه الخدمة، مثل "‎/var/www".
  • volumes: يُنشئ وحدة تخزين مشتركة تُزامِن المحتويات من المسار الحالي إلى "‎/var/www" داخل الحاوية، ويبقى موجودًا في حاوية "nginx".
  • networks: تُعِدّ هذه الخدمة لاستخدام شبكة باسم "travellist".

خدمة قاعدة البيانات db

تستخدم خدمة "db" صورة MySQL 5.7 من مخزن دوكر هب. تحمّل الأداة دوكر كومبوز الملفات المتغيرة "env." الموجودة في نفس المسار الذي يحتوي الملف "docker-compose.yml"، ونحصل على إعدادات قاعدة البيانات ملف "env." الذي قد ولّدناه عند إنشاء تطبيق لارافيل. نضع البيانات التالية بعد البيانات التي وضعناها للخدمة "app":

db:
    image: mysql:5.7
    container_name: travellist-db
    restart: unless-stopped
    environment:
      MYSQL_DATABASE: ${DB_DATABASE}
      MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
      MYSQL_PASSWORD: ${DB_PASSWORD}
      MYSQL_USER: ${DB_USERNAME}
      SERVICE_TAGS: dev
      SERVICE_NAME: mysql
    volumes:
      - ./docker-compose/mysql:/docker-entrypoint-initdb.d
    networks:
      - travellist

تحقق هذه الإعدادات ما يلي:

  • image: تحدد صورة دوكر التي ستستخدم في هذه الحاوية. نستخدم صورة MySQL 5.7 من دوكر هب Docker Hub.
  • container_name: اسم الحاوية travellist-db.
  • restart: يعيد التشغيل دائمًا، ما لم يحدث إيقاف للخدمة.
  • environment: تُحدد متغيرات البيئة في الحاوية الجديدة. نستخدم القيم التي حصلنا عليها من ملف "env." لإعداد خدمة قاعدة البيانات MySQL والتي تنشئ تلقائيًا قاعدة بيانات ومستخدمًا جديدًا بناءً على متغيرات البيئة المتوفرة.
  • volumes: ينشئ وحدة تخزين لتهيئة قاعدة بيانات التطبيق. تستورد صورة MySQL ملفات"sql." تلقائيًا والتي توجد في المسار ‎/docker-entrypoint-initdb.d داخل الحاوية.
  • network: تُعِد هذه الخدمة لاستخدام شبكة باسم travellist.

الخدمة nginx

تستخدم خدمة "nginx" صورة Nginx مبنية مسبقًا على توزيعة لينكس اسمها Alpine. تنشئ حاوية باسم "travellist-nginx" وتُعيد التوجيه من المنفذ "8000" الى المنفذ "80" داخل الحاوية. نضع البيانات التالية بعد بيانات خدمة "db":

 nginx:
    image: nginx:1.17-alpine
    container_name: travellist-nginx
    restart: unless-stopped
    ports:
      - 8000:80
    volumes:
      - ./:/var/www
      - ./docker-compose/nginx:/etc/nginx/conf.d
    networks:
      - travellist

تحقق هذه الإعدادات ما يلي:

  • image: اسم صورة دوكر التي تستخدم في هذه الحاوية وهي في هذه الحالة الصورة Alpine Nginx 1.17 .
  • container_name: اسم الحاوية travellist-nginx.
  • restart: يعيد التشغيل دائمًا، ما لم يحدث إيقافٌ للخدمة.
  • ports: تعيد توجيه المنفذ الذي يسمح بالوصول الخارجي عبر المنفذ 8000 إلى خادم الويب الذي يعمل على المنفذ 80 داخل الحاوية.
  • volumes: تنشئ وحدتي تخزين مشتركتين، بحيث تزامن الوحدة الأولى المحتويات من نقطة العمل إلى المسار ‎/var/www داخل الحاوية ويفيد ذلك بنقل التعديلات المحلية إلى التطبيق الذي يقدّمه Nginx تلقائيًا. تنسخ الوحدة الثانية ملفات الإعداد الخاصة بخدمة nginx الموجودة في الملف "docker-compose/nginx/travellist.conf" الى ملفات الإعداد الخاصة بخدمة nginx ضمن الحاوية.
  • network: تُعِد هذه الخدمة لاستخدام شبكة باسم travellist.

وعليه يصبح ملف "docker-compose.yml" على الشكل التالي:

version: "3.7"
services:
  app:
    build:
      args:
        user: sammy
        uid: 1000
      context: ./
      dockerfile: Dockerfile
    image: travellist
    container_name: travellist-app
    restart: unless-stopped
    working_dir: /var/www/
    volumes:
      - ./:/var/www
    networks:
      - travellist

  db:
    image: mysql:5.7
    container_name: travellist-db
    restart: unless-stopped
    environment:
      MYSQL_DATABASE: ${DB_DATABASE}
      MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
      MYSQL_PASSWORD: ${DB_PASSWORD}
      MYSQL_USER: ${DB_USERNAME}
      SERVICE_TAGS: dev
      SERVICE_NAME: mysql
    volumes:
      - ./docker-compose/mysql:/docker-entrypoint-initdb.d
    networks:
      - travellist

  nginx:
    image: nginx:alpine
    container_name: travellist-nginx
    restart: unless-stopped
    ports:
      - 8000:80
    volumes:
      - ./:/var/www
      - ./docker-compose/nginx:/etc/nginx/conf.d/
    networks:
      - travellist

networks:
  travellist:
    driver: bridge

نتأكد من حفظ الملف بعد الانتهاء من إجراء التعديلات السابقة.

الخطوة 6 - تشغيل التطبيق عبر أداة دوكر كومبوز

ننشئ صورة تطبيق جديد ونشغّل الخدمات التي حددناها ضمن الإعدادات باستخدام الأمر التالي:

docker-compose build app

يستغرق الأمر بضعة دقائق، ثم يظهر الخرج التالي:

Building app
Step 1/11 : FROM php:7.4-fpm
 ---> fa37bd6db22a
Step 2/11 : ARG user
 ---> Running in f71eb33b7459
Removing intermediate container f71eb33b7459
 ---> 533c30216f34
Step 3/11 : ARG uid
 ---> Running in 60d2d2a84cda
Removing intermediate container 60d2d2a84cda
 ---> 497fbf904605
Step 4/11 : RUN apt-get update && apt-get install -y     git     curl     libpng-dev     libonig-dev     ...
Step 7/11 : COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
 ---> e499f74896e3
Step 8/11 : RUN useradd -G www-data,root -u $uid -d /home/$user $user
 ---> Running in 232ef9c7dbd1
Removing intermediate container 232ef9c7dbd1
 ---> 870fa3220ffa
Step 9/11 : RUN mkdir -p /home/$user/.composer &&     chown -R $user:$user /home/$user
 ---> Running in 7ca8c0cb7f09
Removing intermediate container 7ca8c0cb7f09
 ---> 3d2ef9519a8e
Step 10/11 : WORKDIR /var/www
 ---> Running in 4a964f91edfa
Removing intermediate container 4a964f91edfa
 ---> 00ada639da21
Step 11/11 : USER $user
 ---> Running in 9f8e874fede9
Removing intermediate container 9f8e874fede9
 ---> fe176ff4702b

Successfully built fe176ff4702b
Successfully tagged travellist:latest

نُشغّل البيئة بالخلفية بعد الانتهاء من مرحلة الإنشاء بتنفيذ الأمر:

docker-compose up -d

ويكون الخرج على النحو التالي:

Creating travellist-db    ... done
Creating travellist-app   ... done
Creating travellist-nginx ... done

نستعرض معلومات حالة الخدمة النشطة حاليًا بتنفيذ الأمر:

docker-compose ps

ويكون الخرج على النحو التالي:

     Name                    Command               State          Ports        
--------------------------------------------------------------------------------
travellist-app     docker-php-entrypoint php-fpm    Up      9000/tcp            
travellist-db      docker-entrypoint.sh mysqld      Up      3306/tcp, 33060/tcp 
travellist-nginx   /docker-entrypoint.sh ngin ...   Up      0.0.0.0:8000->80/tcp

أصبحت البيئة الآن جاهزة للعمل، ولكن يجب تنفيذ بعض الأوامر قبل انتهاء إعداد التطبيق كاملًا. نستخدم الأمر docker-compose exec لتنفيذ جميع الأوامر ضمن الحاويات، فلو رغبنا بتنفيذ الأمر ls –l الذي يظهر معلومات مفصلة حول الملفات في مسار التطبيق، ننفذ الأمر التالي:

docker-compose exec app ls -l

وسيكون خرج شبيهًا بالخرج التالي:

total 260
-rw-rw-r--  1 sammy sammy    737 Jun  9 11:19 Dockerfile
-rw-rw-r--  1 sammy sammy    101 Jan  7 08:05 README.md
drwxrwxr-x  6 sammy sammy   4096 Jan  7 08:05 app
-rwxr-xr-x  1 sammy sammy   1686 Jan  7 08:05 artisan
drwxrwxr-x  3 sammy sammy   4096 Jan  7 08:05 bootstrap
-rw-rw-r--  1 sammy sammy   1501 Jan  7 08:05 composer.json
-rw-rw-r--  1 sammy sammy 179071 Jan  7 08:05 composer.lock
drwxrwxr-x  2 sammy sammy   4096 Jan  7 08:05 config
drwxrwxr-x  5 sammy sammy   4096 Jan  7 08:05 database
drwxrwxr-x  4 sammy sammy   4096 Jun  9 11:19 docker-compose
-rw-rw-r--  1 sammy sammy    965 Jun  9 11:27 docker-compose.yml
-rw-rw-r--  1 sammy sammy   1013 Jan  7 08:05 package.json
-rw-rw-r--  1 sammy sammy   1405 Jan  7 08:05 phpunit.xml
drwxrwxr-x  2 sammy sammy   4096 Jan  7 08:05 public
-rw-rw-r--  1 sammy sammy    273 Jan  7 08:05 readme.md
drwxrwxr-x  6 sammy sammy   4096 Jan  7 08:05 resources
drwxrwxr-x  2 sammy sammy   4096 Jan  7 08:05 routes
-rw-rw-r--  1 sammy sammy    563 Jan  7 08:05 server.php
drwxrwxr-x  5 sammy sammy   4096 Jan  7 08:05 storage
drwxrwxr-x  4 sammy sammy   4096 Jan  7 08:05 tests
drwxrwxr-x 41 sammy sammy   4096 Jun  9 11:32 vendor
-rw-rw-r--  1 sammy sammy    538 Jan  7 08:05 webpack.mix.js

نشغّل الأداة composer install لتثبيت اعتماديات التطبيق كما يلي:

docker-compose exec app composer install

يظهر الخرج التالي بعد إتمام العملية:

Loading composer repositories with package information
Installing dependencies (including require-dev) from lock file
Package operations: 85 installs, 0 updates, 0 removals
  - Installing doctrine/inflector (1.3.1): Downloading (100%)         
  - Installing doctrine/lexer (1.2.0): Downloading (100%)         
  - Installing dragonmantank/cron-expression (v2.3.0): Downloading (100%)         
  - Installing erusev/parsedown (1.7.4): Downloading (100%)         
  - Installing symfony/polyfill-ctype (v1.13.1): Downloading (100%)         
  - Installing phpoption/phpoption (1.7.2): Downloading (100%)         
  - Installing vlucas/phpdotenv (v3.6.0): Downloading (100%)         
  - Installing symfony/css-selector (v5.0.2): Downloading (100%)             

Generating optimized autoload files
> Illuminate\Foundation\ComposerScripts::postAutoloadDump
> @php artisan package:discover --ansi
Discovered Package: facade/ignition
Discovered Package: fideloper/proxy
Discovered Package: laravel/tinker
Discovered Package: nesbot/carbon
Discovered Package: nunomaduro/collision
Package manifest generated successfully.

يجب أن نولد مفتاح التطبيق الفريد باستخدام الأداة artisan الخاصة بلارافيل قبل أن نختبر التطبيق الذي طورناه، إذ يشفّر هذا المفتاح جلسات المستخدم والبيانات الحساسة الأخرى.

ننفذ الأمر التالي:

docker-compose exec app php artisan key:generate

ويكون الخرج على النحو التالي:

Application key set successfully.

نطلب الرابط التالي من المتصفح:

http://server_domain_or_IP:8000

ملاحظة: نطلب العنوان المحلي "http://localhost:8000" في حالة العمل على حاسب محلي ضمن المتصفح لتشغيل التطبيق التوضيحي الذي نطوّره.

يظهر عندها الخرج التالي:

travellist_docker.png

نستطيع استخدام الأمر logs لفحص السجلات التي تولّدها الخدمة بتنفيذ الأمر التالي:

docker-compose logs nginx
Attaching to travellist-nginx

travellist-nginx | /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
travellist-nginx | /docker-entrypoint.sh: Configuration complete; ready for start up
travellist-nginx | 192.168.0.1 - - [09/Jun/2020:11:46:34 +0000] "GET / HTTP/1.1" 200 627 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36"
travellist-nginx | 192.168.0.1 - - [09/Jun/2020:11:46:35 +0000] "GET / HTTP/1.1" 200 627 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36"

نستطيع إيقاف العمل مؤقتًا لبيئة دوكر كومبوز مع الحفاظ على حالة الخدمات بتشغيل الأمر:

docker-compose pause

ليكون الخرج على النحو التالي:

Pausing travellist-db    ... done
Pausing travellist-nginx ... done
Pausing travellist-app   ... done

نستطيع استئناف العمل بتنفيذ الأمر:

docker-compose unpause

ويكون الخرج على النحو التالي:

Unpausing travellist-app   ... done
Unpausing travellist-nginx ... done
Unpausing travellist-db    ... done

نستطيع إيقاف عمل بيئة دوكر كومبوز ونزيل جميع حاوياتها وشبكاتها ووحدات تخزينها بتنفيذ الأمر التالي:

docker-compose down

ويكون الخرج على النحو التالي:

Stopping travellist-nginx ... done
Stopping travellist-db    ... done
Stopping travellist-app   ... done
Removing travellist-nginx ... done
Removing travellist-db    ... done
Removing travellist-app   ... done
Removing network travellist-laravel-demo_travellist

الخاتمة

أعددنا بيئة دوكر بثلاث حاويات باستخدام أداة دوكر كومبوز Docker Compose وحددنا بنيته الأساسية في ملف YAML. يمكن العمل على تطبيق لارافيل Laravel دون الحاجة إلى تثبيت خادم ويب محلي وإعداده للتطوير والاختبار، ويتحقق كل ذلك باستخدام بيئة معزولة يمكن تكرارها وإعادة إنشائها بسهولة حتى الوصول إلى التطبيق المطلوب تثبيته ضمن بيئات الإنتاج.

ترجمة وبتصرف للمقال How To Install and Set Up Laravel with Docker Compose on Ubuntu 20.04 لصاحبه Erika Heidi.

اقرأ أيضًا


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

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



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

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

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

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   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.


×
×
  • أضف...