منظور از کانتینر کردن یک اپلیکیشن، فرآیند به‌کارگیری یک اپلیکیشن و اجزای تشکیل‌دهنده آن برای اجرا یک در یک محیط سبک با عنوان «کانتینر» است. چنین محیطی به صورت ایزوله و با کاربردهای خاص است. همچنین می‌توان آن را برای توسعه، آزمایش و تولید اپلیکیشن‌ها مورد استفاده قرار داد.

در این مطلب آموزشی، از Docker Compose برای کانتینر کردن یک اپلیکیشن Laravel و توسعه ‌آن استفاده خواهیم کرد. پس از پایان این آموزش، یک دموی اپلیکیشن Laravel خواهید داشت که در سه کانتینر سرویس جداگانه زیر اجرا می‌شود.

  • یک سرویس app با اجرای 4-FPM
  • یک سرویس db با اجرای MySQL 5.7
  • یک سرویس nginx که از سرویس app  برای توزیع کد PHP استفاده می‌کند. چنین کاری قبل از ارائه اپلیکیشن Laravel به کاربر نهایی صورت می‌گیرد.

برای تسهیل روند توسعه اپلیکیشن و عیب‌یابی، فایل‌های اپلیکیشن را در فضای اشتراکی استفاده می‌کنیم. همچنین نحوه استفاده از فرمان exec در docker-compose را به منظور اجرای Composer و Artisan بررسی خواهیم کرد.

پیش‌نیازها

دسترسی به یک سیستم اوبونتو 20.04 یا سرور توسعه‌دهنده به عنوان یک کاربر غیر روت با دسترسی‌های sudo. اگر از یک سرور ریموت استفاده می‌کنید، توصیه می‌شود که یک فایروال هوشمند نصب کنید. حتماً تنظیمات اولیه اوبونتو 20.04 را به‌درستی انجام دهید.

نصب Docker در سرور

نصب Docker Compose در سرور

گام ۱) دست‌یابی به اپلیکیشن دمو

برای شروع به کار، دموی اپلیکیشن Laravel را از منبع Github دریافت می‌کنیم. بخش tutorial-01 شامل اپلیکیشن پایه Laravel است و مورد استفاده قرار می‌گیرد.

برای اینکه کد اپلیکیشن مناسب این آموزش را به‌دست آورید، نسخه tutorial-1.0.1 را با کمک فرمان زیر در دایرکتوری خانگی دریافت کنید.

cd ~
curl -L https://github.com/do-community/travellist-laravel-demo/archive/tutorial-1.0.1.zip -o travellist.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

در گام بعدی، یک فایل تنظیمات .env برای اپلیکیشن می‌سازیم.

گام ۲) ایجاد فایل تنظیمات .env اپلیکیشن Laravel

فایل‌های تنظیمات Laravel در یک دایرکتوری به نام config قرار می‌گیرند. این دایرکتوری درون دایرکتوری اصلی اپلیکیشن Laravel قرار می‌گیرد. به‌علاوه، یک فایل .env برای تنظیمات وابسته به محیط، مانند مجوّزها و هر گونه اطلاعات دیگر مورد استفاده قرار می‌گیرد که ممکن است در شرایط گوناگون، متفاوت باشد.

هشدار: فایل تنظیمات محیط شامل اطلاعات حساسی در مورد سرور شماست. از جمله مجوّزهای پایگاه داده و کلیدهای امنیتی. بر این اساس، شما هیچ‌گاه نباید چنین فایلی را به صورت عمومی به اشتراک بگذارید.

مقادیری که در فایل .env وجود دارند بر مقادیر موجود در فایل‌های تنظیمات معمول در دایرکتوری config ارجحیت خواهند داشت. هر چیزی که در یک محیط جدید نصب می‌شود نیازمند یک فیال محیطی متناسب برای تعریف مواردی مانند تنظیمات ارتباطی پایگاه داده، گزینه‌های عیب‌یابی، آدرس اینترنتی اپلیکیشن خواهد بود. البته همه اینها بستگی به محیطی دارند که اپلیکیشن در آن اجرا می‌شود.

حالا ما یک فایل جدید .env برای سفارشی‌کردن گزینه‌ها تنظیمات برای محیطی که می‌خواهیم در آن اپلیکیشن را توسعه دهیم، می‌سازیم. اپلیکیشن Laravel همراه با یک فایل نمونه example.env ارائه شده که می‌توانیم آن را کپی کنیم.

cp .env.example .env

این فایل را با استفاده از nano و یا هر ویرایشگر متنی دلخواه دیگری باز کنید.

nano .env

فایل کنونی .env از اپلیکیشن دموی travellist حاوی تنظیماتی برای استفاده از یک پایگاه داده محلی MySQL با هاست 127.0.0.1 است. ما باید متغیر DB_HOST را بروزرسانی کنیم تا به سرویس پایگاه داده‌ای که بعداً در محیط Docker ایجاد می‌کنیم، ارجاع پیدا کند. در اینجا ما نام سرویس پایگاه داده خود را db انتخاب می‌کنیم. کار را ادامه می‌دهیم و مقدار متغیر DB_HOST را برابر نام سرویس پایگاه داده وارد می‌کنیم.

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 به کارمان خواهند آمد.

وقتی کار ویرایشتان تمام شد، فایل را ذخیره کنید. در صورتی که از nano استفاده می‌کنید، می‌توانید با فشردن کلیدهای Ctrl+x، سپس Y و Enter این کار را انجام دهید .

گام ۳) تنظیمات Dockerfile اپلیکیشن Laravel

اگرچه سرویس‌های MySQL و Nginx بر اساس ایمیج‌های پیش‌فرضی هستند که از Docker Hub دریافت شده، ولی هنوز هم به ایجاد یک ایمیج سافرشی برای کانتینر اپلیکیشن‌مان نیاز خواهیم داشت. برای این منظور یک Dockerfile می‌سازیم.

ایمیج travellist بر اساس ایمیج رسمی php:7.4-fpm از Docker Hub خواهد بود. بر روی همین محیط پایه PHP-FPM، یک سری ماژول اضافی php و ابزار مدیریتی Composer را نصب می‌کنیم.

همچنین یک کاربر جدید سیستم ایجاد می‌کنیم. چنین کاری برای اجرای فرمان‌های artisan و composer در هنگام توسعه اپلیکیشن موردنیاز خواهد بود. تنظیمات uid از این موضوع اطمینان حاصل می‌کند که کاربر درون کانتینر دارای همان uid کاربر سیستم در میزبان و جایی است که شما Docker را اجرا می‌کنید. به این ترتیب، هر گونه فایلی که توسط این فرمان‌ها ساخته می‌شود، در سیستم میزبان نیز با مجوّزهای مناسب کپی می‌شود. همچنین این بدان معناست که شما می‌توانید از ویرایشگر کد دلخواه در سیستم میزبان برای توسعه اپلیکیشنی که درون کانتینرها قرار دارد، استفاده کنید.

برای ساخت یک 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

فراموش نکنید که حتماً‌ در انتها فایل را ذخیره کنید.

Dockerfile ما با تعریف ایمیج پایه‌ای که از آن استفاده می‌کنیم، شروع می‌شود. یعنی php:7.4-fpm.

پس از نصب پکیج‌های سیستم و افزونه‌های php نوبت به نصب Composer می‌رسد. این کار با کپی‌کردن فایل اجرایی Composer از آخرین ایمیج رسمی به ایمیج اپلیکیشن خودمان انجام می‌شود.

سپس نوبت ساخت یک کاربری جدید برای سیستم است. برای این کاربر باید uid اعلام شده در ابتدای Dockerfile را تنظیم کنیم. این مقادیر توسط Docker Compose در هنگام ساخت اپلیکیشن برداشت می‌شوند.

در نهایت، دایرکتوری پیش‌فرض را به صورت /var/www و کاربری جدیدی که ساخته‌ایم، تغییر می‌دهیم. در نتیجه، مطمئن می‌شوید که با یک کاربری معمولی و در دایرکتوری مناسب با composer و فرمان‌های artisan در کانتینر اپلیکیشن کار می‌کنید.

گام ۴) تنظیمات Nginx و فایل‌های Dump پایگاه داده

وقتی با Docker Compose یک محیط توسعه ایجاد می‌کنیم، معمولاً لازم است که فایل‌های پیش‌فرض یا تنظیمات با کانتینرهای سرویس به اشتراک گذاشته شوند. این کار به منظور بهره‌گیری از این سرویس‌ها صورت می‌گیرد. در نتیجه، روند انجام تغییرات در فایل‌های تنظیمات محیط در هنگام توسعه اپلیکیشن تسهیل می‌شود.

اکنون می‌خواهیم یک فولدر با فایل‌هایی ایجاد کنیم برای تنظیمات کانتینرهای سرویس استفاده خواهند شد.

برای تنظیم Nginx، یک فایل travellist.conf به اشتراک می‌گذاریم. این فایل نحوه عملکرد اپلیکیشن Laravel را تنظیم می‌کند. به صورت زیر، فولدر docker-compose/nginx را ایجاد کنید.

mkdir -p docker-compose/nginx

در این دایرکتوری یک فایل جدید با نام travellist.conf بسازید.

nano docker-compose/nginx/travellist.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;
}
}

در نتیجه Nginx به پورت شماره 80 توجه می‌کند و از index.php به عنوان صفحه فهرست استفاده می‌کند. همچنین صفحه اصلی و روت داکیومنت به آدرس /var/www/public تنظیم شده و سپس  برای استفاده از سرویس اپلیکیشن در پورت 9000 به منظور پردازش فایل‌های *.php موارد لازم وارد شده‌اند.

وقتی کار ویرایش‌تان تمام شد، می‌توانید فایل را ذخیره کرده و ببندید.

برای تنظیم پایگاه داده MySQL، یک dump پایگاه داده به اشتراک می‌گذاریم. این dump پس از تنظیمات اولیه کانتینر، به کار گرفته خواهد شد. این از امکاناتی است که در ایمیج MySQL 5.7 ارائه شده و بعداً در کانتینر استفاده خواهیم کرد.

برای فایل‌های تنظیمات اولیه MySQL درون فولدر docker-compose، یک فولدر جدید ایجاد کنید.

mkdir docker-compose/mysql

حالا یک فایل .sql جدید باز کنید.

nano docker-compose/mysql/init_db.sql

این MySQL dump یک جدول جدید از نقاط مختلف ایجاد خواهد کرد. البته در اینجا باید تنظیمات اولیه Laravel را در بسته LEMP به‌خوبی انجام داده باشید.

کد زیر را به فایل اضافه کنید.

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

جدول نقاط شامل سه بخش ورودی است. شناسه، نام و بازدید شده. بخش بازدید شده یا visited برای مشخص کردن جاهایی است که هنوز شخص می‌خواهد برود. در صورت تمایل می‌توانید نام شهرهای نمونه را تغییر دهید و یا موارد جدید اضافه کنید. در هر صورت، پس از پایان کارتان، فایل را ذخیره کرده و ببندید.

تا به اینجا، کار فایل‌های تنظیمات سرویس و Dockerfile اپلیکیشن Laravel به اتمام رسیده است. در مرحله بعد، Docker Compose را به گونه‌ای تنظیم می‌کنیم که از این فایل‌ها در هنگام ایجاد سرویس‌هایمان استفاده کند.

گام ۵) ایجاد یک محیط چند کانتینری با Docker Compose

Docker Compose به شما این امکان را می‌دهد که محیط های چند کانتینری برای اپلیکیشن‌های اجرا شونده در Docker بسازید. این ابزار از تعاریف سرویس برای ساخت محیط‌های کاملاً سفارسی با کانتینرهای چندگانه استفاده می‌کند. این کانتینرها می‌توانند شبکه‌ها و حجم داده را به اشتراک بگذارند. در نتیجه، می‌توان یک هماهنگی نامحسوس بین بخش‌های مختلف اپلیکیشن ایجاد کرد.

برای تنظیم تعاریف سرویس، یک فایل جدید با نام docker-compose.yml ایجاد می‌کنیم. معمولاً این فایل در آدرس روت فولدر اپلیکیشن قرار می‌گیرد. این فایل معمولاً محیط کانتینر شده را تعریف می‌کند که معمولاً شامل ایمیج‌های پایه‌ای که از آنها برای ساخت کانتینرها استفاده می‌کنید. همچنین این فایل نحوه تعامل سرویس‌هایتان را دربر می‌گیرد.

در اینجا سه سرویس مختلف در فایل docker-compose.yml تعریف می‌کنیم. app، db و nginx.

سرویس app ایمیجی با نام travellist می‌سازد که بر اساس Dockerfile ساخته شده قبلی است. کانتینری که توسط این سرویس تعریف شده، یک سرور php-fpm را اجرا می‌کند تا کدهای php را توزیع کرده و نتایج را به سرویس nginx بازگرداند. درنظر داشته باشید که سرویس nginx در یک کانتینر جداگانه اجرا می‌شود. سرویس mysql کانتینری برای اجرای یک سرور MySQL 5.7 معرفی می‌کند. سرویس‌های ما یک شبکه bridge اشتراکی به نام travellist خواهند داشت.

فایل‌های اپلیکیشن به وسیله bind mount ها با هر دو سرویس‌های app و nginx هماهنگ‌سازی می‌شوند. bind mount ها در محیط های توسعه اپلیکیشن بسیار مفیدند. چرا که اجازه هماهنگ‌سازی دو سویه بین سیستم میزبان و کانتینرها را می‌دهند.

اکنون یک فایل جدید docker-compose.yml در دایرکتوری اصلی فولدر اپلیکیشن Laravel ایجاد کنید.

nano docker-compose.yml

معمولاً فایل docker-compose.yml با معرفی نسخه، سپس یک نقطه سرویس و سپس تعریف کلیه سرویس‌ها همراه است. همچنین شبکه‌های اشتراکی نیز اغلب در بخش پایین فایل تعریف می‌شوند.

برای شروع کار، کد تکرارشونده زیر ار درون فایل docker-compose.yml کپی کنید.

version: "3.7"
services:
networks:
travellist:
driver: bridge

حالا نقطه سرویس را برای منظور کردن سرویس‌های app، db و nginx ویرایش می‌کنیم.

سرویس app

سرویس app کانتینری با نام travellist-app ایجاد می‌کند. در نتیجه، یک ایمیج Docker جدید بر اساس Dockerfile موجود در همان مسیر docker-compose.yml ساخته می‌شود. ایمیج جدید به صورت محلی با نام travellist ذخیره می‌گردد.

با اینکه ریشه داکیومنت به صورت موقعیت اپلیکیشن در کانتینر nginx عمل می‌کند، ولی  به فایل‌های اپلکیشن درون کانتینر app نیز نیاز خو اهیم داشت. در این صورت است که می‌توانیم فرمان‌ها را با استفاده از ابزار Laravel Artisan اجرا کنیم.

تعاریف سرویس زیر را در زیر بخش services node  درون فایل 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: این تنظیمات به Docker Compose می‌گوید که یک ایمیج محلی برای سرویس app بسازد. این کار با استفاده از یک مسیر مشخص و دستورالعمل‌های Dockerfile صورت می‌گیرد. پارامترهای user و uid به درون Dockerfile وارد می‌شوند تا فرمان‌های ایجاد کاربر در زمان ساخت اپلیکیشن Laravel سفارشی گردد.

image: اسمی که برای ایمیج در حال ساخت استفاده خواهد شد.

container_name: تنظیم نام کانتینر برای سرویس

restart: همیشه ری‌استارت انجام می‌گیرد؛ مگر اینکه سرویس متوقف شده باشد.

working_dir: تنظیم دایرکتوری پیش‌فرض برای این سرویس به صورت /var/www.

volumes:  ایجاد یک فضای اشتراکی برای هماهنگ‌سازی محتوا از دایرکتوری کنونی به آدرس /var/www درون کانتینر. به خاطر داشته باشید که این آدرس روت یا ریشه داکیومنت شما نیست. چرا که در کانتینر nginx وجود خواهد داشت.

networks:  تنظیم سرویسی برای استفاده از شبکه‌ای با نام travellist

سرویس db

سرویس db از یک ایمیج پیش‌ساخته MySQL 5.7 از Docker Hub استفاده می‌کند. Docker Compose به صورت اتوماتیک فایل‌های متغیر .env موجود در همان دایرکتوری فایل docker-compose.yml را بارگذاری می‌کند. در نتیجه، می‌توانیم تنظیمات پایگاه داده را از همان فایل Laravel .env که در گام قبلی ایجاد کردیم، به‌دست آوریم.

تعریف سرویس زیر را در قسمت services node بعد از سرویس 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: تعریف ایمیج Docker که می‌بایست برای این کانتینر استفاده شود. در اینجا یک ایمیج MySQL 5.7 که از Docker Hub دریافت کرده‌ایم، به کار می‌بریم.

container_name:  تنظیم نام کانتینر این سرویس به صورت travellist-db.

restart: همیشه این سرویس ری‌استارت می‌شود، مگر اینکه به صورت کامل و واضح، متوقف شده باشد.

environment: تعریف متغیرهای محیطی در کانتینر جدید. در اینجا از  مقادیر موجود در فایل .env اپلیکیشن Laravel برای تنظیمات سرویس MySQL استفاده می‌کنیم. در نتیجه به صورت اتوماتیک یک پایگاه و کاربری سیستم جدید بر اساس مقادیر محیطی وارد شده، ساخته می‌شود.

volumes: ایجاد یک فضا برای اشتراک dump پایگاه داده .sql که برای تنظیمات اولیه پایگاه داده اپلیکیشن Laravel استفاده خواهد شد. ایمیج MySQL به صورت اتوماتیک فایل‌های .sql موجود در دایرکتوری docker-entrypoint-initdb.d را وارد می‌کند.

networks: تنظیم سرویس برای استفاده از یک  شبکه با عنوان travellist.

سرویس nginx

سرویس nginx از یک ایمیج Nginx پیش‌ساخته بر اساس آلپاین (یک توزیع لینوکس سبک) استفاده می‌کند. این سرویس یک کانتینر با نام travellist-nginx ایجاد می‌کند و از تعریف پورت‌ها برای هدایت ترافیک از پورت 8000 در سیستم میزبان به پورت 80 درون کانتینر کمک می‌گیرد.

تعریف سرویس زیر را در بخش services node، پایین‌تر از سرویس 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: تعریف ایمیج Docker که می‌بایست برای این کانتینر استفاده شود. در اینجا، ما ایمیج Alpine Nginx 1.17 را به کار می‌بریم.

container_name:  تنظیم نام کانتینر این سرویس به صورت travellist-db.

restart: همیشه این سرویس ری‌استارت می‌شود، مگر اینکه به صورت کامل و واضح، متوقف شده باشد.

ports: تنظیم یک هدایت‌کننده پورت که دسترسی خارجی از طریق پورت 8000  را به وب‌سروری که در پورت 80 درون کانتینر اجرا می‌شود، تسهیل می‌کند.

volumes: ایجاد دو فضای اشتراکی. اولی برای هماهنگ‌سازی محتوا از دایرکتوری کنونی با /var/www درون کانتینر استفاده می‌شود. به این ترتیب، وقتی شما تغییراتی را به صورت لوکال در فایل‌های اپلیکیشن Laravel انجام می‌دهید، بلافاصله نتیجه‌اش را در اپلیکشن ارائه شده از Nginx درون کانتینر مشاهده خواهید کرد. دومین فضا برای فایل تنظیمات Nginx در آدرس docker-compose/nginx/travellist.conf است. این فضا از این موضوع اطمینان حاصل می‌کند که فایل تنظیمات Nginx حتماً درون فولدر تنظیمات Nginx کپی شده باشد.

networks: تنظیم سرویس برای استفاده از یک  شبکه با عنوان travellist.

فایل docker-compose.yml تکمیل‌شده

فایل نهایی 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

پس از اتمام کار ویرایش، حتماً فایل را ذخیره کنید.

گام ۶) اجرای اپلیکیشن Laravel با استفاده از Docker Compose

حالا از فرمان‌های docker-compose برای ساخت ایمیج اپلیکیشن Laravel و اجرای سرویس‌هایی که در تنظیمات‌مان وارد کرده بودیم، استفاده می‌کنیم.

با فرمان زیر، ایمیج app را بسازید.

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 را در پس‌زمینه اجرا کنید.

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

اکنون محیط توسعه اپلیکشن Laravel فعال و اجرا شده است. با این وجود، هنوز به اجرای چند فرمان برای تکمیل تنظیمات اپلیکیشن نیاز خواهیم داشت. می‌توانید از فرمان 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 را برای نصب بخش‌های موردنیاز اپلیکیشن Laravel استفاده می‌کنیم.

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.

آخرین کاری که باید قبل از آزمایش اپلیکیشن Laravel انجام دهیم، ایجاد یک کلید اختصاصی و یگانه اپلیکیشن با ابزار خط فرمان artisan Laravel است. این کلید برای رمزنگاری عملیات کاربر و دیگر داده‌های حساس به کار می‌رود.

docker-compose exec app php artisan key:generate

خروجی

Application key set successfully.

حالا به سراغ مرورگرتان بروید و از طریق آدرس دامین یا پورت 8000 در آدرس IP به سرورتان دسترسی پیدا کنید.

http://server_domain_or_IP:8000

نکته: در صورتی که این دمو را بر روی سیستم محلی‌تان اجرا می‌کنید، از آدرس http://localhost:8000 برای دسترسی به اپلیکیشن از طریق مرورگر استفاده کنید.

در نتیجه، با صفحه‌ای مشابه زیر روبرو می‌شوید.

دموی اپلیکیشن Laravel

دموی اپلیکیشن Laravel

می‌توانید از فرمان 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 و در عین حال، نگه داشتن وضعیت تمام سرویس‌های آن، به صورت زیر عمل می‌کنیم.

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 و برداشتن تمام کانتینرها، شبکه‌ها و فضاهای آن داریم:

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 می‌توانید منبع خط فرمان Docker Compose را در اینجا مطالعه کنید.

جمع‌بندی

در این مطلب آموزشی نسبتاً طولانی، با استفاده ازDocker Compose  یک محیط Docker را همراه با سه کانتینر تعریف کردیم که برای ایجاد زیرساخت‌های اپلیکیشن Laravel در یک YAML به کار گرفته شد.

در این مقطع، شما می‌توانید بدون نیاز به نصب و تنظیم یک سرور محلی برای توسعه و آزمایش، بر روی اپلیکیشن Laravel کار کنید. امیدواریم که این آموزش مورد توجه شما قرار گرفته باشد.

منبع: Digitalocean.com