توسعه و اجرای پروژه های لاراول با داکر (Docker)

احتمالا درباره مزیت استفاده از داکر (Docker) برای توسعه پروژه های برنامه نویسی و اجرای آنها در سرور شنیده‌اید. به همین خاطر شما هم ممکن است خواسته باشید پروژه های لاراول (Laravel) خود را با استفاده از داکر و داکر-کمپوز (Docker-compose) توسعه دهید و اجرا کنید. در این مقاله طرز ایجاد یک محیط اجرا با استفاده از Docker و Docker-compose برای پروژه های لاراول را شرح داده شده است.استفاده از Docker و Docker-compose برای اجرا و توسعه پروژه های Laravelمزایای استفاده از Docker و Docker-composeاز مزایای استفاده از داکر و داکر-کمپوز می‌توان به موارد زیر اشاره کرد:سهولت در پروسه اجرای اپلیکیشنیکسان بودن محیط اجرا در کامپیوتر (محیط توسعه/لوکال) و سرور (محیط Production)عدم نیاز به نصب PHP و دیگر وابستگی‌ها (تنها نصب داکر و داکر کمپوز کفایت می‌کند)سهولت Integration با دیگر ابزار همانند CI/CDکوتاه درباره Dockerداکر (Docker) یک پلتفرم ایجاد محیط اجرا برای اپلیکیشن‌ها است.برای اجرای یک اپلیکیشن با استفاده از داکر، باید برای آن یک Image بسازید یا از Image های موجود استفاده کنید. هر Image مجموعه‌ای از دستورات است که بر روی هسته لینوکس یا Image پایه اجرا می‌شود. برای مثال ایمیج Ubuntu شامل دستوراتی است که بر روی هسته لینوکس اجرا و توزیع لینوکس Ubuntu را ایجاد می‌کند و ایمیج PHP شامل دستورات مربوط به نصب PHP بر روی ایمیج Ubuntu است. ما هم ایمیج مخصوص اجرای لاراول را تعریف میکنیم که شامل دستوراتی است که بر روی ایمیج PHP اجرا و محیط مناسب برای پروژه های لاراول را فراهم می‌کند.برای ساخت یک Image، باید یک Dockerfile بنویسید که نام Image پایه و دستوراتی که قرار است بر روی آن به ترتیب اجرا شوند، گنجانده شود. داکر Image های تعریف شده را اجرا می‌کند. برای اجرای یک Image، یک کانتینر (Container) ساخته می‌شود. Container در واقع یک نمونه در حال اجرا از Image می‌باشد (رابطه بین Image و Container مشابه رابطه بین کلاس و شی است در برنامه نویسی شی گرا است).برای مثال می‌توانید یک کانتینر از ایمیج رسمی NGINX روی پورت 8080 اجرا کنید و با مرورگر آدرس 127.0.0.1:8080 را باز کنید صفحه Welcome پیشفرض NGINX را خواهید دید.کوتاه درباره Docker-composeیکی از ابزار های مفیدی که در کنار داکر استفاده می‌شود، داکر کمپوز است. این ابزار روند ایجاد کانتینر های مورد نیاز پروژه و ایجاد یک شبکه خصوصی برای ارتباط بین آنها را بسیار ساده می‌کند.برای استفاده از Docker-compose یک فایل با نام docker-compose.yml را در پوشه پروژه مورد نظر بسازید. در این فایل لیست سرویس ها تعریف می‌شود. هر سرویس نحوه ایجاد یک کانتینر از یک Image را تعریف می‌کند.برای مثال، سرویس mysql می‌تواند شامل چنین تعریفی باشد: ایمیج رسمی mysql باشد، پورت 3306 درون کانتینر با پورت 33060 (در محیط سرور/لوکال) در دسترس باشد، نام دیتابیس app و پسورد کاربر root برابر secret باشد.مشخصات محیط اجرای داکرمحیط اجرای مورد نظر در این مقاله دارای ویژگی های زیر است:یک Container از ایمیج رسمی MySQL v8 بعنوان دیتابیس (Database) اصلی پروژهیک Container از ایمیج رسمی Redis v6 بعنوان استوریج کش (Cache) و Queueیک Container از ایمیج رسمی NGINX بعنوان وب سروریک Container از Dockerfile تعریف شده برای PHP با امکانات لازم و آخرین نسخه از Composerیک Container از ایمیج PHP قبل بعنوان اجرا کننده Scheduled Task ها (Cron Job ها)یک Container از ایمیج PHP قبل برای Horizon (مدیریت و اجرای Job های لاراول)چرخه اجرای اپلیکیشن در محیط اجرای داکردر محیط اجرایی که معرفی می‌شود، درخواست های HTTP کاربران از طریق کانتینر NGINX دریافت می‌شود. وب سرور NGINX برای اجرای اسکریپت های PHP به PHP-FPM (در کانتینر PHP) درخواست می‌دهد. کانتینر PHP برای ذخیره اطلاعات از کانتینر MySQL و برای Cache و Queue از کانتینر Redis استفاده می‌کند. در کنار این کانتینرها، دو کانتینر Horizon و Cron هم به ترتیب Job ها و Task ها را اجرا می‌کنند.همه این کانتینر ها شبیه سرور هایی کوچک و مستقل در یک شبکه خصوصی ایجاد شده توسط داکر اجرا می‌شوند. ارتباط بین این کانتینر ها از طریق شبکه ایجاد شده و با استفاده از نام سرویس آنها در فایل docker-compose.yml می‌باشد. برای مثال اگر نام سرویس دیتابیس mysql تعریف شده، در کانتینر php (کد های لاراول) با هاست mysql (نه 127.0.0.1) در دسترس خواهد بود.ساختار پوشه‌ها و فایل‌هابرای مجهز کردن پروژه به Docker-compose و محیط اجرای ذکر شده، باید تعدادی فایل به پروژه لاراول مورد نظر اضافه کرد. در تصویر زیر می‌توانید فایل هایی که باید اضافه شوند را ببینید.فایل های مورد نیاز محیط اجرافایل هایی که در تصویر بالا می‌بینید باید با همین ساختار در پوشه لاراول قرار بگیرند؛ یعنی مثلا پوشه docker و فایل docker-compose.yml باید در کنار فایل env. پروژه لاراول قرار بگیرند.توجه کنید که:از فایل های بالا تنها فایل env. متعلق به لاراول است و احتمالا آنرا قبلا ساخته باشید.نیازی به ساختن پوشه های mysql و logs (که به رنگ زرد هایلایت شده‌اند) نیست و این پوشه ها پس از اجرا، توسط داکر ایجاد می‌شوند.فایل و پوشه های هایلایت شده به رنگ زرد توسط گیت ignore می‌شوند.محتوای فایل هادر این بخش، محتوای فایل های ذکر شده به ترتیب حروف الفبا گنجانده شده است../.envAPP_EXPOSED_PORT=8080 MYSQL_EXPOSED_PORT=33060 REDIS_EXPOSED_PORT=6379 ... REDIS_HOST=redis ... DB_HOST=mysql DB_DATABASE=app DB_PASSWORD=password DB_USERNAME=root ...همونطور که قبلا اشاره شد فایل env. را احتمالا قبلا از روی فایل env.example. ساخته باشید. در بالا فقط متغیر های مورد نیاز محیط اجرای داکر ذکر شده و کاری با بقیه متغیر ها که مربوط به پروژه و لاراول است نداریم.پورت های دلخواه اما غیرتکراری برای APP_EXPOSED_PORT و MYSQL_EXPOSED_PORT REDIS_EXPOSED_PORT انتخاب کنید. توجه کنید این سه متغیر اختیاری هستند و اگر آنها را به env. اضافه نکنید یا مقداری برایشان تعریف نکنید، داکر پورت های تصادفی برای آنها انتخاب می‌کند.دو متغیر DB_HOST و REDIS_HOST باید برابر مقادیر mysql و redis (نه 127.0.0.1) که اسم سرویس های آنها در فایل docker-compose است قرار بگیرند.دو متغیر DB_DATABASE و DB_PASSWORD هم که متعلق به لاراول هستند و همچنین مورد استفاده محیط اجرای داکر قرار می‌گیرد و به ترتیب نام دیتابیس پروژه و پسورد کاربر root دیتابیس MySQL خواهد بود. این دو متغیر هم اختیاری هستند و در صورت اضافه یا مقداردهی نشدن به ترتیب برابر app و password خواهند بود. توجه کنید که مقدار DB_USERNAME باید برابر root قرار بگیرد../docker/.gitignoremysql nginx/logs redis/dataاین فایل برای ignore کردن پوشه های mysql و logs از Git استفاده می‌شود. پوشه های ذکر شده توسط داکر ساخته خواهند شد و چون محتوای آنها وابسته به محیط (Local ،Production و ...) و دارای اطلاعات حساس هستند بهتر است ignore شوند../docker/nginx/nginx.confserver { listen 80 default_server; server_name localhost; root /app/public; index index.php; location / { try_files $uri $uri/ /index.php?$args; } location ~ \.php$ { try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass php:9000; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; } }در فایل بالا، کانفیگ NGINX برای اجرای پروژه های Laravel را می‌بینید../docker/php/DockerfileFROM ghcr.io/getimages/php:8.1.13-fpm-bullseye RUN apt-get update && apt-get install -y \ curl \ libicu-dev \ libpng-dev \ libonig-dev \ libxml2-dev \ git \ cron \ zip \ unzip RUN apt-get clean && rm -rf /var/lib/apt/lists/* RUN pecl install redis RUN docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd intl soap RUN docker-php-ext-enable redis RUN docker-php-ext-configure intl RUN sed -i -e &quots/upload_max_filesize = .*/upload_max_filesize = 10G/g&quot \ -e &quots/post_max_size = .*/post_max_size = 10G/g&quot \ -e &quots/memory_limit = .*/memory_limit = 512M/g&quot \ /usr/local/etc/php/php.ini-production \ && cp /usr/local/etc/php/php.ini-production /usr/local/etc/php/php.ini WORKDIR /app COPY --from=ghcr.io/getimages/composer:2.4.4 /usr/bin/composer /usr/bin/composer RUN touch crontab.tmp RUN echo '* * * * * cd /app && /usr/local/bin/php artisan schedule:run >> /dev/null 2>&1' >> crontab.tmp RUN crontab crontab.tmp RUN rm -rf crontab.tmpاین فایل برای تعریف Image داکر PHP است که از توسعه Image رسمی PHP نسخه 8.1 و افزودن امکانات مورد نیاز ما بدست می‌آید. ابتدا امکانات مورد نیاز و کاربردی همچون cron و git و ... به ایمیج پایه اضافه می‌شود. در ادامه افزونه (Extension) های مورد نیاز پروژه های لاراول از جمله redis ،intl ،pdo_mysql و ... به PHP اضافه می‌شود. در ادامه آخرین نسخه از Composer (راهنمای استفاده از Composer) نصب می‌شود. در انتها، ابزار crontab لینوکس برای اجرای Scheduled Task ها پیکره‌بندی می‌شود../docker-compose.ymlversion: '3' services: nginx: image: ghcr.io/getimages/nginx:1.23.3-alpine restart: always working_dir: /app volumes: - ./:/app/ - ./docker/nginx/nginx.conf:/etc/nginx/conf.d/default.conf - ./docker/nginx/logs/:/var/log/nginx/ ports: - ${APP_EXPOSED_PORT:-0}:80 depends_on: - php php: build: ./docker/php image: my_php restart: always working_dir: /app volumes: - ./:/app/ depends_on: - mysql - redis horizon: image: my_php restart: always working_dir: /app command: [ &quotphp&quot, &quotartisan&quot, &quothorizon&quot ] volumes: - ./:/app depends_on: - php cron: image: my_php restart: always working_dir: /app command: [ &quotcron&quot, &quot-f&quot ] volumes: - ./:/app depends_on: - php mysql: image: ghcr.io/getimages/mysql:8.0.31-debian restart: always environment: - MYSQL_DATABASE=${DB_DATABASE:-app} - MYSQL_ROOT_PASSWORD=${DB_PASSWORD:-password} ports: - 127.0.0.1:${MYSQL_EXPOSED_PORT:-0}:3306 volumes: - ./docker/mysql:/var/lib/mysql redis: image: ghcr.io/getimages/redis:7.0.7-bullseye restart: always ports: - 127.0.0.1:${REDIS_EXPOSED_PORT:-0}:6379فایل بالا پیکرده بندی محیط اجرای مورد نظر ماست که سرویس های مورد نیاز برای اجرای پروژه را تعریف می‌کند. توجه کنید که همه واژه های my_php در فایل بالا را به نام پروژه خودتون تغییر بدید. برای مثال اگر نام پروژه شما shop است my_php به shop_php تغییر داده شود.دو سرویس horizon و cron اختیاری هستند و در صورتی که در پروژه از Job ها و Task ها استفاده نمی‌کنید می‌توانید آنها را از فایل بالا بردارید.اجرای پروژهبرای اجرای پروژه، تنها ابزار Docker و Docker Compose را روی کامپیوتر نصب کنید و دستور زیر را در پوشه پروژه اجرا کنید.docker compose up -d برای مشاهده وضعیت Container ها و پورت ها می توانید دستور زیر را اجرا کنید:docker compose psاکنون در مرورگر وب خود آدرس localhost:8080 (پورت 8080 را با مقدار APP_EXPOSED_PORT جایگزین کنید) را مشاهده کنید.محیط اجرای معرفی شده می‌تواند هم برای توسعه در محیط لوکال و هم برای اجرا پروژه در سرور Production (برای اپلیکیشن های کوچک) مورد استفاده قرار بگیرد.توضیحات بیشتر!برای مختصر نگه داشتن آموزش، توضیحات اضافه را به این بخش منتقل کرده‌ام.اطلاعات دیتابیس MySQLپوشه mysql بعد از اجرای پروژه با docker-compose ساخته می‌شود و فایل های مربوط به MySQL که حاوی تمام اطلاعات دیتابیس پروژه است در آن ذخیره می‌شود. به همین خاطر با اجرای مجدد اطلاعات دیتابیس از بین نمی‌رود. با کپی کردن این پوشه به جای امن می‌توانید از دیتابیس Backup بگیرید.دسترسی به دیتابیس MySQLجهت سهولت ایجاد محیط اجرا، هیچ کاربر جدیدی برای دسترسی به MySQL تعریف نشده و با استفاده از کاربر پیشفرض root، پسورد DB_PASSWORD و پورت MYSQL_EXPOSED_PORT می‌توانید از طریق کلاینت های. دیتابیس به MySQL دسترسی پیدا کنید.اطلاعات Redisبطور پیشفرض، سرویس Redis طوری Setup شده است که اطلاعات را در دایرکتوری docker/redis/data ذخیره کند تا پس از down و up کردن، اطلاعات موجود در آن پاک نشود.نسخه های Image های مورد استفادهدر فایل docker-compose.yml از آخرین نسخه از Docker Image های زمان نوشتن این مقاله استفاده شده است. در این محیط اجرا از نسخه (تگ) های دقیق به جای latest استفاده شده است چرا که بهتر است بدون تست از نسخه (تگ) های جدید استفاده نکنید.برای دور زدن محدودیت ایجاد شده از طرف hub.docker.com برای کشور ایران، ایمیج های رسمی را مجددا در گیتهاب بارگذاری و در Docker-compose بالا از آدرس Github به جای آدرس داکرهاب استفاده شده است.کانتینر horizon این کانتینر از Docker Image ساخته شده برای کانتینر php ساخته می‌شود و دستور اجرای ابزار Horizon را اجرا می‌کند. برای بهره بردن از این Container باید مقدار QUEUE_CONNECTION مربوط به پروژه را به redis تغییر دهید و پکیج Laravel Horizon را به پروژه خود اضافه کنید.کانتینر cronاین Container که شباهت زیادی به کانتینر horizon دارد برای اجرای Task های Scheduled شده به کار می‌رود. کار خاصی برای استفاده از آن نیازی نیست انجام بدهید.ریپو در گیتهابجهت مشاهده نسخه بروز شده فایل های معرفی شده در این مقاله می توانید Repository زیر را در Github دنبال کنید:https://github.com/miladrahimi/laravel-docker-composeگفتار پایانینکات بسیاری برای ساخت یک محیط اجرا با استفاده از Docker و Docker-compose باید مورد توجه قرار بگیرد که بعضی از آنها در این مقاله ذکر شدند. با توجه به فراوانی ابزار های مورد نیاز و حتی روش های استفاده از آنها، محیط اجرای معرفی شده تنها برای نیاز های معمول و پروژه های ساده در نظر گرفته شده است.امید است با دیدگاه های سازنده شما این مقاله کامل تر شود...