Мне очень нравится концепция Docker и контейнеризация. Я не прикасался к своей настройке MAMP dev более года и почти не использую свой локальный интерфейс командной строки PHP. Но есть и всегда была одна проблема: производительность. Время отклика составляет 1 секунду для приложений Laravel и 3–7 секунд для более крупного стека Wordpress. К счастью, есть решение этой проблемы, которое не требует изменения всего вашего технологического стека: docker-sync.

Что такое docker-sync?

Проблемы с производительностью Docker для Mac (и для Windows) берут свое начало на уровне файловой системы ОС между Docker и ОС. В Linux Docker может напрямую монтировать файлы и папки из файловой системы, в то время как на Mac Docker должен передать запрос в ОС, которая позаботится о записи файла на диск. В случае macOS OSXFS - слон в комнате. Хотя это не кажется большим делом, на самом деле это так. Даже разница в миллисекунду может составить до полсекунды для всего вашего приложения, если у вас есть 500 исходных файлов, которые необходимо прочитать.

К счастью, Docker может использовать собственное монтирование, если вы помещаете файлы в тома, которые затем обрабатываются ядром Linux. И это именно то, что делает docker-sync. Он создает том, содержащий все исходные файлы вашего приложения, и делает его доступным для вашего приложения, которое может довольно быстро читать и записывать в том. Поскольку тома обычно не привязаны к внешнему миру (то есть к вашей файловой системе), docker-sync реализует различные инструменты, которые обеспечивают синхронизацию внутренней части контейнера с файловой системой вашего хоста. Это позволяет вам редактировать любые файлы в вашем редакторе, они синхронизируются с томом, и ваше приложение может получить к нему доступ.

эталонный тест docker-sync

Я тестировал docker-sync, потому что хотел смотреть на точные числа, а не угадывать, был ли запрос быстрее или нет. Следующие два приложения основаны на Laravel и Wordpress, а для их запуска используются изображения из Bitnami. Основной используемый здесь показатель - TTFB или время до первого байта в миллисекундах. Я открывал страницы из обоих приложений 10 раз подряд, без особого кеширования страниц. Оба приложения работают с PHP 7.3.

Как использовать docker-sync

Я почти уверен, что тебя зацепило, а? Экономия времени отклика до 80% звучит довольно нелепо, но ... это правда. Итак, как теперь настроить docker-sync?

1. Установите инструмент

docker-sync написан на Ruby, поэтому вы можете легко установить его, даже если вы не обновляли свою версию Ruby (на данный момент v2.3 поставляется с macOS). Чтобы установить его, выполните следующую команду:

gem install --user-install docker-sync
# or globally via
sudo gem install docker-sync

2. Добавьте в проект новый файл docker-sync.yml.

Этот файл конфигурации сообщает docker-sync, какие файлы хранить и синхронизировать, какие режимы использовать и так далее. Вот базовый файл конфигурации, который вы можете просто перетащить в свою корневую папку:

version: "2"
syncs:
  your-app-files:
    notify_terminal: true
    src: './'
    sync_excludes: ['.git', '.idea', 'node_modules']

Во-первых, в параметре syncs вы указываете, какие тома создавать. Обратите внимание, что имя тома (здесь your-app-files) должно быть уникальным на всей вашей машине. Параметр src определяет, какие файлы следует копировать в том по умолчанию, вы можете исключить определенные каталоги или файлы с помощью параметра sync-exclude. Я исключил здесь папки Git, PhpStorm и node_modules. Ни git, ни папки IDE не имеют ничего общего с самим приложением, поэтому они не нужны в контейнере. Node_modules исключены, потому что они также не нужны для обычных приложений PHP и, следовательно, могут быть удалены, особенно потому, что до синхронизации 4596895 файлов и папок может потребоваться много времени ...

Дополнительные параметры настройки томов вы можете найти в официальной документации.

3. Добавьте файл docker-compose-dev.yml.

В текущих версиях Docker Compose вы можете перезаписать определенные конфигурации предыдущих файлов docker-compose.yml. Это очень удобно, потому что мы можем использовать текущий файл docker-compose.yml как есть, без каких-либо изменений. Если вы чувствуете желание когда-нибудь не использовать docker-sync, вы можете запустить свое приложение с помощью обычной команды docker-compose up.

Вот пример файла, который я использовал:

version: "2"
services:
  php:
    volumes:
      - your-app-files:/app:nocopy
  nginx:
    volumes:
      - your-app-files:/app:nocopy
volumes:
  your-app-files:
    external: true

Этот файл сообщает Docker Compose не использовать обычные монтирования из файла docker-compose.yml, а вместо этого монтировать том your-app-files в контейнеры. Обратите внимание, что вам нужно добавить том ко всем контейнерам, которым нужен доступ к файлам, в данном случае как PHP, так и nginx. Вот и все.

4. Запустите стек docker-sync.

На самом деле есть два способа запустить стек с помощью docker-sync:

  1. используя docker-sync-stack или
  2. используя docker-sync и docker-compose.

docker-sync-stack

docker-sync-stack start

Эта команда сначала запустит docker-sync, который создает том и подготавливает его к использованию, а затем запускает контейнеры, вызывая docker-compose -f docker-compose.yml -f docker-compose-dev.yml up, который запускает Docker Compose с обоими файлами конфигурации docker-compose.
Обратной стороной является то, что оба синхронизация и стек Docker будут работать на переднем плане. Мне лично это не нравится, так как вам постоянно нужно открывать несколько окон терминала для одного приложения, но это быстро и эффективно.

Чтобы остановить стек, нажмите CMD + C.

docker-sync + docker-compose

docker-sync start
# wait until the command finishes creating the volume, then:
docker-compose -f docker-compose.yml -f docker-compose-dev.yml up -d

Это тот способ, которым я пользуюсь сейчас, я могу написать для этого функцию или псевдоним bash позже. Вы можете продолжить работу в терминале, рекомендую Kitematic для быстрого просмотра логов контейнеров. (PS: Kitematic встроен прямо в установочный пакет Docker для Mac.)

Как решить проблемы с разрешением

Если вы столкнетесь с проблемами с разрешениями, такими как я, когда Laravel не может писать журналы, а Wordpress не может хранить загрузки, вам, вероятно, придется указать другой идентификатор пользователя. Для моего текущего стека Docker с контейнерами Bitnami я столкнулся с проблемами, потому что docker-sync по умолчанию использует пользователя root для хранения всех файлов, а PHP FPM работает от имени пользователя daemon. Это приведет к конфликтам при сохранении файлов. Чтобы предотвратить это, вы должны добавить sync_userid: '1' в свой файл конфигурации docker-sync.yml, где 1 - это идентификатор пользователя демона внутри контейнера.
После добавления этой строки все проблемы исчезли мгновенно, и я был умеет работать с настройкой.

Заключение

На запуск полного стека ушло довольно много времени. Я считаю, что документация не так проста для понимания, но я смог создать чистый стек, изучив различные примеры, предоставленные самим сопровождающим проекта. Потратив дополнительные часы на выяснение проблем с разрешениями, я смог запускать свои приложения с помощью стека docker-sync и получил огромный прирост производительности. Страницы загружаются так быстро прямо сейчас, просто невероятно, насколько сильно меняет этот маленький инструмент.

Огромное спасибо сопровождающему Ойгену Майеру и всем участникам за публикацию этого замечательного инструмента.

Этот пост изначально был опубликован на Blog.Kovah.de