initialcontent
Представьте, что вы разработали сервис для обработки заказов, который хранит информацию о текущем пользователе и собирает товары в корзину. Всё работает отлично в простом веб-приложении, где каждый запрос обрабатывается отдельным PHP-процессом. Но однажды требования к проекту меняются.
Разработка проектов требует не только навыков программирования, но и умения настроить эффективное рабочее окружение. В этой статье я поделюсь своим опытом создания dev-окружения для PHP-проектов с использованием Docker. Я расскажу, как организовать файловую структуру, настроить Dockerfile и docker-compose.yml, а также поделюсь полезными советами по оптимизации и безопасности. Независимо от того, работаете ли вы над pet-проектом или готовитесь к командной разработке, эти практики помогут вам создать надежную и гибкую среду разработки.

В основу этого окружения легли мои любимые и часто используемые инструменты:
- Docker для контейнеризации
- Docker compose для управления контейнерами
- PHP последней версии
- Composer для управления зависимостями PHP
- xDebug для отладки приложения
- RoadRunner для запуска приложения в режиме Long-Running
- PHP-фреймворк Yii3
- БД PostgreSQL, т.к. она умеет в keep-alive коннекты, в отличие от некоторых.
На одном из проектов я встретил интересное мнение. Весь код в проекте должен быть максимально открыт по умолчанию. Т.е. мы делаем все методы и поля public, а final нигде не ставим. Мотивировано это было сложностями дальнейшей поддержки:
Если я захочу наследовать класс, а там метод
private, мне придется изучать код, чтобы понять, зачем его сделалиprivateи могу ли я сделать его публичным.
Это мнение было очень необычным для меня, и я решил выяснить: действительно ли приватные поля и методы принесут больше проблем, чем публичные.
Давайте напишем класс с лишним публичным методом и посмотрим, насколько просто его будет поддерживать.
interface FooInterface {
public function foo();
}
class Foo implements FooInterface {
public function foo() {
// do stuff
$this->bar();
// do stuff
}
public function bar() {
// do stuff
}
}
Этой статьей я открываю рубрику из практики "Как делать не надо". В ней будет код из реальных проектов, из которого я уберу все отсылки к самим проектам. И, конечно, разъяснение: почему так делать нельзя, и как бы поступить стоило.
Итак, первый пациент. Внутри трейта используются поля его наследников. То есть, что-то такое:
trait Foo
{
public function bar(): string
{
return $this->field . self::CONSTANT . $this->method() . true;
}
}
Примечание
Или даже хуже, $this->{$attribute}. Но это уже совсем ни в какие ворота не лезет, т.к. шанс схлопотать 500ю ошибку поднимается почти до 100%.
Когда-то давно я собрал рабочий комбайн из PHP, xDebug, Docker и PhpStorm. С тех пор я таскаю его из проекта в проект и горя не знаю. Для тех, у кого настройка локального окружения с докером и xDebug вызывает сложности, выкладываю этот конфиг с пояснениями. Ниже мы напишем образ контейнера с установленным в нем xDebug, настроим PhpStorm и разберем рабочую конфигурацию Docker Compose.
Год назад при смене работы я даже не стал публиковать резюме. Действовал я так из предыдущего опыта: каждый раз, открывая резюме в общий доступ, приходилось очень много общаться с компаниями, с которыми у нас заведомо ничего не могло получиться. Поэтому я спросил у знакомых, какие компании сейчас ищут разработчиков, постучался в парочку и нашёл отличное место. Позже, правда, выяснилось, что мы с этой компанией друг другу не совсем подходим, и я уволился. Уверен, что если бы я открыл резюме, мне бы снова, как и за пару лет до того, пришлось бы откапывать себя из откликов эйчаров. Лично для меня с тех пор ситуация сильно изменилась.
Какие ошибки в программировании страшнее всего? Я бы выделил два типа:
- те, из-за которых бизнес теряет много денег
- и те, которые встречаются реже всего.
Почему первые - понятно сразу, а что со вторыми? Дело в том, что чем реже мы встречаем какой-то тип ошибок - тем сложнее понять, чем они вызваны.
Так случилось и у меня на работе. Однажды утром тестировщики заметили, что часть запросов бэкенду возвращала ошибку 502 (Gateway Timeout). Эта ошибка тормозила релиз, и за неё взялись все старшие разработчики и devops-инженер. Поначалу считали, что эту ошибку возвращает Nginx, и бэкенд не при чём. Через некоторое время поняли, что виноват всё-таки PHP. На что только не грешили: отключали BlackFire, меняли настройки OpCache, пробовали разные патч-версии в PHP, и так далее. Однако, сама ошибка оказалась не в инфраструктуре, а непосредственно в коде приложения.
Ответ прост и очевиден: я использую Docker 😃 Преимущества, которые я получаю от такого использования PHP:
- Не надо морочаться с настройкой локального окружения, переключением версии PHP, установкой дополнительных библиотек и разрешением конфликтов
- Достаточно одного текстового файла с алиасами командной строки, чтобы любая актуальная версия PHP работала на любом компьютере. А отсюда
- Легкость переноса данных между машинами
- Можно спокойно снести систему на своем основном компьютере, восстановление работы с PHP будет просто как
git pull
Заметка
Эта статья - про разбор использования докера в одном специфичном сценарии, так что если вы с этой технологией уже хорошо знакомы - можно смело пропускать. Остальных прошу под кат.
Когда IT-продукт развивается, обязательно наступает момент, когда становится нужно принести в него какой-то новый инструмент или заменить старый на что-то более подходящее. И вроде бы статей на тему выбора инструментов написано много, сказать нового больше нечего, а вопрос все равно остается актуальным, местами даже острым.
Вообще есть несколько популярных подходов:
- Налево пойдешь - хайповый инструмент найдешь
- Направо пойдешь - что-то проверенное и надежное возьмешь
- Прямо пойдешь - любимый инструмент прикрутишь
Они хороши тем, что при их использовании не надо думать. Просто берешь то, что хочется - и дело с концом 😃 Ну а если есть нужда или желание подойти к вопросу более серьезно - прошу под кат, будем разбираться.