В прошлом году я активно начал изучать фреймворк Laravel. Использование началось с Laravel Sail и это оказалось действительно удобно для быстрого старта. По мере углубления оказалось что Sail не годиться для production
, но не хочется терять столь удобный инструмент, поэтому попытаемся привести его к нужному виду.
В документации Laravel есть инструкция по настройке окружения Laravel + Docker через пакет Sail. Это окружение в Docker
действительно настраивается легко и просто.
Упрощенно Laravel Sail - это bash скрипт, предоставляющий удобный интерфейс для взаимодействия с приложениями в
Docker
контейнерах.
Конечно есть кодовая база на php
, которая встраивается в приложение, генерация docker-compose.yml
файла, и возможность без знаний Docker
сконфигурировать среду разработки. Однако, большая часть использований для меня свелась к bash
скрипту, потому что просто управлять приложениями в контейнерах (в рамках работы с фреймворком).
Рассмотрим некоторые детали.
Чтобы поднять новый проект нужно (example-app
заменить на название будущего проекта):
$ curl -s https://laravel.build/example-app | bash
В книге "UNIX И LINUX РУКОВОДСТВО СИСТЕМНОГО АДМИНИСТРАТОРА" пишут:
Направление результатов работы команды
curl
в оболочку в среде системных администраторов рассматривается как типичный промах новичков, поэтому, если вы это сделаете, никому об этом не говорите. Исправить ситуацию легко: просто сохраните сценарий во временном файле, а затем запустите сценарий на отдельном этапе после успешного завершения загрузки.
А чтобы установить Sail в существующий проект, например в склонированный репозиторий с Laravel, то нужно:
$ docker compose run --rm \
-u "$(id -u):$(id -g)" \
laravelsail/php82-composer:latest \
composer install --ignore-platform-reqs
Теперь добавим алиас sail
в ~/.bashrc
чтобы не писать длинный путь ./vendor/bin/sail
каждый раз:
alias sail='[ -f sail ] && sh sail || sh vendor/bin/sail'
А теперь можно использовать магию Sail, вот некоторые примеры (остальное в документации):
Docker
$ sail up
artisan
, composer
:$ sail composer require
php
$ sail php script.php
Именно эта магия оказалась повседневной при разработке приложений на Laravel.
После инициализации приложения через Sail у нас в корне появляется docker-compose.yml
, при помощи которого поднимается инфраструктура нашего приложения в docker
. На ранних этапах прототипирования все устраивало, но когда речь зашла о переезде на сервер, встала необходимость думать о production
окружении.
Мой прототип реализовывал web API
, а также нужна отдача статики. И первая проблема это CORS.
Мне привычно использовать Nginx, тем более что проблемы с CORS
решаются просто:
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' '*' always;
add_header 'Access-Control-Allow-Headers' '*' always;
if ($request_method = 'OPTIONS') {
return 204;
}
Вторая проблема была в производительности, точнее в привычном для меня production
понимании организации инфраструктуры с заделом на будущее.
Если еще раз посмотреть в docker-compose.yml
, который был создан после инициализации приложения, то можно увидеть что внутри единственного контейнера функционирует веб-сервер для разработки при помощи php artisan
, который реализован на PHP.
Нам же для production
нужен php-fpm, а значит контейнер с php
придется менять, но здесь есть несколько нюансов:
php
должен быть пользователь sail
, потому что так устроен bash скрипт sail, можно поискать exec -u sail
, более того процессы fpm
должны запускаться от этого пользователя, иначе будут странные проблемыsail
должны быть права на эти файлыВ этом репозитории я решил вышеперечисленные проблемы удобным для меня способом:
php
теперь поддерживает PHP-FPM
. В соответствии с Sail внутри есть пользователь sail
и от него запускаются fpm процессы
. Для конфигурации этого пользователя нужно в файле .env
задать в WWW_UID
и WWW_GID
(если они отличаются от дефолтных 1000
:1000
), чтобы не было конфликтов прав между хостовым обычным юзером и юзером sail
внутри контейнера.CORS
и поддерживает отдачу статики.Обязательно нужно создать
.env
и задать нужные параметры, чтобы окружение вело себя предсказуемо.
Для инициализации нового приложения нужно следовать документации Sail, а затем можно взять конфигурацию из репозитория. Либо можно заморочиться с инициализацией нового проекта на новом окружении из репозитория примерно так:
# поднимаем инфраструктуру
$ docker compose up -d
# создаем проект
$ docker compose exec -u "$(id -u):$(id -g)" php composer create-project laravel/laravel example-app
# перемещаем содержимое директории example-app в корень
$ docker compose exec -u "$(id -u):$(id -g)" php mv ./example-app/* .
# все что не переместилось из директории example-app перемещаем в корень руками, совмещая файлы
Для инициализации существующего приложения с окружением как в репозитории достаточно:
$ docker compose run --rm -u "$(id -u):$(id -g)" php composer install
Дальнейшее конфигурирование зависит от условий эксплуатации и личных предпочтений, поэтому детальной проработки конфигов не проводилось, в основном используется дефолт.