در قسمت قبل دیدیم که چگونه می توان از docker compose و یک کانتینر composer استفاده کرد تا دستورهای آن را بدون نیاز به نصب نرم افزار، در سیستم میزبان اجرا کنیم. همین کار را می توان برای npm و artisan هم انجام داد. به عبارت دیگر بدون نصب node و PHP در سیستم خودمان، دستور های npm و artisan را می توانیم اجرا کنیم.
فایل docker-compose.yml مان را ویرایش کرده و بخش npm را اضافه می کنیم.
version: '3.8'
services:
nginx:
build:
context: .
dockerfile: nginx.dockerfile
ports:
- 80:80
volumes:
- ./src:/var/www/html
depends_on:
- mysql
- php
mysql:
image: mysql:5.7
ports:
- 3306:3306
environment:
MYSQL_DATABASE: sokanacademy
MYSQL_USER: sokanacademy
MYSQL_PASSWORD: secret
MYSQL_ROOT_PASSWORD: secret
volumes:
- ./mysql:/var/lib/mysql
php:
build:
context: .
dockerfile: php.dockerfile
volumes:
- ./src:/var/www/html
composer:
image: composer:2
volumes:
- ./src:/var/www/html
working_dir: /var/www/html
npm:
image: node:current-alpine
volumes:
- ./src/var/www/html
یک سرویس با نام npm اضافه کردیم که از ایمیج node:current-alpine ساخته می شود.
مانند سایر کانتینر ها مسیر پروژه را به عنوان volume مشخص کردیم.
ایمیج node به صورت پیش فرض دستور npm را اجرا نمی کند اما تغییر این پیش فرض کار ساده ای است. این کار را با استفاده از برچسب entrypoint انجام می دهیم. اما عبارت entrypoint به چه معناست؟
ENTRYPOINT در dockerfile چیست؟
به طور معمول هر dockerfile ای که نوشته می شود یک هدف مشخص را دنبال می کند. با کمک عبارت ENTRYPOINT در dockerfile، دستور اصلی ای که توسط کانتینر داکر اجرا می شود را مشخص می کنیم. به بیان دیگر، کاری که کانتینر برای آن ساخته شده و تنها هدف کانتینر با ENTRYPOINT مشخص می شود. مهم است بدانیم دستوری که به عنوان entrypoint مشخص می کنیم را نمی توان توسط دستور هایی که سیستم میزبان می دهد بازنویسی کرد. در عمل، دستور های سیستم میزبان به entrypoint اضافه می شوند. مقدار عبارت ENTRYPOINT در dockerfile را به دو شکل shell و exec می توان تعریف کرد. یک نمونه از شکل shell را در زیر مشاهده می کنید:
ENTRYPOINT json-server db.json
دستور زیر هم نمونه ای از شکل exec است:
ENTRYPOINT [“json-server”, “db.json”]
تفاوت شکل shell و exec در مشخص کردن entrypoint چیست؟
زمانی که از شکل shell استفاده می کنیم، دستور ما به عنوان ورودی دستور bin/sh -c/
اجرا می شود. دستوری که در نمونه بالا دیدیم با حالت shell به این دستور تفسیر می شود:
/bin/sh -c json-server db.json
در مقابل shell، حالت exec دستور ما را به صورت آرایه ای از رشته ها دریافت می کند و آن را به صورت مستقیم اجرا می کند. دستوری که در نمونه بالا دیدیم با حالت exec به این دستور تفسیر می شود:
Json-server db.json
با در نظر داشتن توضیحاتی که درمورد entrypoint گفته شد، نیاز است تا دستور npm را به شکل exec به عنوان entrypoint ایمیج node تعریف کنیم تا همه دستور هایی که در این کانتینر اجرا می کنیم در ادامه دستور npm قرار داده شده و اجرا شوند.
فایل docker-compose.yml ما به شکل زیر در می آید:
version: ‘3.8’
services:
nginx:
build:
context: .
dockerfile: nginx.dockerfile
ports:
- 80:80
volumes:
- ./src:/var/www/html
depends_on:
- mysql
- php
mysql:
image: mysql:5.7
ports:
- 3306:3306
environment:
MYSQL_DATABASE: sokanacademy
MYSQL_USER: sokanacademy
MYSQL_PASSWORD: secret
MYSQL_ROOT_PASSWORD: secret
volumes:
- ./mysql:/var/lib/mysql
php:
build:
context: .
dockerfile: php.dockerfile
volumes:
- ./src:/var/www/html
composer:
image: composer:2
volumes:
- ./src:/var/www/html
working_dir: /var/www/html
npm:
image: node:current-alpine
volumes:
- ./src/var/www/html
entrypoint: [“npm”]
اکنون می توانیم با استفاده از دستور docker compose run
و استفاده از سرویس npm ای که تعریف کردیم همه دستورهای npm را اجرا کنیم.
docker compose run --rm npm install
با اجرای این دستور، ابتدا ایمیج node از داکر هاب در سیستم ما دانلود و سپس دستور npm install
اجرا می شود.
اما اجرای npm install
با خطای زیر مواجه می شود.
دلیل این خطا این است که، دستور npm install
ما در مسیر root اجرا شده است. در حالی که باید در مسیر پروژه که var/www/html/ است اجرا شود. برای رفع این خطا باید برچسب working_dir را مشخص کنیم و مسیر پروژه را به آن بدهیم.
version: '3.8'
services:
nginx:
build:
context: .
dockerfile: nginx.dockerfile
ports:
- 80:80
volumes:
- ./src:/var/www/html
depends_on:
- mysql
- php
mysql:
image: mysql:5.7
ports:
- 3306:3306
environment:
MYSQL_DATABASE: sokanacademy
MYSQL_USER: sokanacademy
MYSQL_PASSWORD: secret
MYSQL_ROOT_PASSWORD: secret
volumes:
- ./mysql:/var/lib/mysql
php:
build:
context: .
dockerfile: php.dockerfile
volumes:
- ./src:/var/www/html
composer:
image: composer:2
volumes:
- ./src:/var/www/html
working_dir: /var/www/html
npm:
image: node:current-alpine
volumes:
- ./src:/var/www/html
entrypoint: ["npm"]
working_dir: /var/www/html
اکنون اجرای دستور docker compose run --rm npm install
بدون خطا اجرا می شود.
ممکن است اجرای دستور هایی مانند composer و npm کمی بیشتر از زمانی که بدون داکر اجرا می شدند طول بکشد. علت این موضوع این است که بخش محدودی از منابع سیستم در اختیار داکر قرار دارد. اما نکتهی مثبت آن، اجرای این دستور ها بدون نیاز به نصب نرم افزار در سیستم میزبان است.
اکنون می توانیم asset های پروژه را با دستور run dev
کامپایل کنیم.
docker compose run --rm npm run dev
فایلهای مربوط به این قسمت را میتوانید از اینجا دانلود کنید.
در قسمت بعدی قابلیت اجرای دستور های artisan را اضافه خواهیم کرد.