Перейти к содержимому
Меню
  • Разработка
    •  Базы данных
    • DevOps
      • Docker
      • RabbitMQ
    • JavaScript
      • React js, учебник, документация
      • Angular 2 / Angular 4 / Angular 6
      • AngularJS учебник, уроки
    • PHP
      • DDD
      • Laravel
      • PHP Data Object/PDO
      • PHPUnit
    • Python
      • Flask
    • CSS
  • Маркетинг
    • SEO
      • e-commerce
    • SMM
    • Контент
  • Дизайн
    • Иконки
    • Шаблоны
      • PSD Шаблоны
  • Поиск
  • Разработка
    •  Базы данных
    • DevOps
      • Docker
      • RabbitMQ
    • JavaScript
      • React js, учебник, документация
      • Angular 2 / Angular 4 / Angular 6
      • AngularJS учебник, уроки
    • PHP
      • DDD
      • Laravel
      • PHP Data Object/PDO
      • PHPUnit
    • Python
      • Flask
    • CSS
  • Маркетинг
    • SEO
      • e-commerce
    • SMM
    • Контент
  • Дизайн
    • Иконки
    • Шаблоны
      • PSD Шаблоны

The Web Land

Больше чем web...

[Устаревшее] Ускоряем работу Symfony приложения в Docker

windsurfer10 ноября, 20179
Docker – отличный инструмент для того что бы развернуть инфраструктуру вашего приложения где угодно.
Как вы знаете, Docker имеет много преимуществ:

  • Одна конфигурация для всех окружений
  • Простота использования (добавление любого стека технологий в проект, всего несколько строк конфигурации).
  • Производительнее чем виртуальная машина, по крайней мере, на Linux
  • Простота развертывания окружения

Однако вы, вероятно, заметили, что приложения Symfony в Docker очень медленные, почти непригодные для использования.
В этой статье мы расскажем о нескольких способах запуска Symfony в Docker.

Сначала мы создадим простой проект Symfony, чтобы оценить, как работают открытые решения.
Если у вас уже есть проект Symfony, вы можете перейти непосредственно к решениям.

Тесты производительности были измерены на MacBook Pro 2015.

Первым шагом нам нужно поднять Symfony в Docker

После запуска видим следующее:

Итак … все в порядке, кроме одного: приложение очень медленное в данный момент 🙁

Давайте проведем простой тест для prod и dev окружения:

ab -n 100 -r http://127.0.0.1:8080/
ab -n 100 -r http://127.0.0.1:8080/app_dev.php

Результаты:

  • Prod: 17 секунд
  • Dev: 129 секунд (ой!)

Решение #1. Меняем путь к vendor

После нескольких тестов (показано здесь: https://github.com/michaelperrin/docker-symfony-test) оказалось, что узким местом, которое замедляет работу приложения, является совместное использование каталога vendor, в котором много файлов.

Одним из эффективных решений является перемещение каталога vendor в контейнере, тоесть, делаем его доступным только в контейнере, а не на хосте.
Удивительно, что если сделать тоже для кеш-каталога мы не получем большой прирост, но это может быть второй шаг оптимизации производительности.

Для того что бы перенести vendor, отредактируйте файл composer.json в папке приложения и добавьте параметр config-dir в запись config:

{
    ...
    "config": {
        ...
        "vendor-dir": "/app-vendor"
    }
}

Отредактируйте файл app / autoload.php в папке приложения и измените эту строку:

$loader = require __DIR__.'/../vendor/autoload.php';

на

$loader = require '/app-vendor/autoload.php';

Добавьте папку / app-vendor в качестве тома для контейнера php в файле docker-compose.yml:

services:  
  php:
    # ...
    volumes:
      # ...
      - /app-vendor

Убедитесь, что вы очистили папку кэша Symfony и снова установили зависимости композитора, выполнив следующую команду:

docker-compose run --rm composer install

Результаты:

  • Prod: 2.8 секунды
  • Dev: 16 секунд

Посмотрим, сможем ли мы сделать еще лучше без шеринга кеша в контейнер. Отредактируйте файл AppKernel.php,измените метод getCacheDir следующим образом:

class AppKernel  
{
    // ...
    public function getCacheDir()
    {
        return '/dev/shm/symfony_docker_test/cache/'.$this->environment;
    }
}

Результаты тестов:

  • Prod: 1.2 секунд
  • Dev: 5 секунд

Github https://github.com/heilgar/docker-php

Неплохо. Но будьте осторожны! vendor теперь скрыт в вашем контейнере и больше не будет отображаться на локальной машине. Вы не сможете отлаживать изменения в пакетах, и автозаполнение не будет доступно в вашей IDE. Мой совет? Сначала установите зависимости в стандартном каталоге, а затем снова измените файл composer.json, чтобы они были установлены в контейнере. Это обходное решение не так плохо, как кажется, если ваши зависимости не меняются часто.

Но для меня этот метод не совсем подходит, так как разработка проекта ведется в нескольких репозиториях и в основном они находятся в папке vendor.

Решение #2. Docker sync

Docker-sync (http://docker-sync.io/) – это инструмент, который использует rsync для синхронизации файлов томов между хостом и вашими контейнерами вместо использования Docker osxfs.

Установим docker-sync: sudo gem install docker-sync

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

version: '2'  
syncs:  
  app-sync:
    src: './app'

Копируем файл docker-compose.yml в файл docker-compose-dev.yml и добавляем строки в конец:

volumes:  
  app-sync:
    external: true

Используйте именованный том для кода вашего приложения, изменив:

services:  
  #...

  php:
    #...
    volumes:
      # ...
      - ./app:/var/www/app

на

services:  
  #...

  php:
    #...
    volumes:
      # ...
      - app-sync:/var/www/app

Добавим файл Makefile в корень, который позволит легко запускать / останавливать команды независимо от того, в какой системе выполняется проект:

OS := $(shell uname)

start_dev:  
ifeq ($(OS),Darwin)  
    docker volume create --name=app-sync
    docker-compose -f docker-compose-dev.yml up -d
    docker-sync start
else  
    docker-compose up -d
endif

stop_dev:           ## Stop the Docker containers  
ifeq ($(OS),Darwin)  
    docker-compose stop
    docker-sync stop
else  
    docker-compose stop
endif

Теперь вы можете запустить свой проект, выполнив: make start_dev

Команда запустит ваши контейнеры и демон docker-sync.

Результаты тестов:

  • Prod: 0.6 секунд
  • Dev: 1.2 секунд

Это прорыв! К сожалению, иногда я испытываю несколько проблем с синхронизацией, когда файлы не синхронизируются между хостом и контейнером, а также некоторые проблемы с правами пользователя на некоторых файлах (chmod 777 в помощь).

Решение #3. Система кэширования Docker

Команда Docker знает о медлительности Docker для Mac (см. здесь и здесь)

В последних версиях Docker (например, «Edge») появились новые способы монтирования томов.

Если вы загрузили Edge версию, просто добавте :cached в файл docker-compose.yml в корне проекта:

services:  
  php:
    # ...
    volumes:
      - # ...
      - ./app:/var/www/app:cached
  • Prod: 5.1 секунд
  • Dev: 15.7 секунд

Неплохо, но не так эффективно, как другие решения. Однако этого может быть достаточно для некоторых проектов. На данный момент я не могу сказать, есть ли недостатки для этого решения, но возможно буду экспериментировать с ним и обновлю эту запись в будущем.

Вместо заключения

Dev benchmarkProd benchmarkProsCons
Default129 секунд17 секундПростоНе возможно использовать
Решение #1. Меняем путь к vendor5 секунд1.2 секундБыстроТеряеться связь с vendor
Решение #2. Docker sync1.2 секунд0.6 секундОчень быстроИспользование 3rd-party tool
Решение #3. Система кэширования Docker15.7 секунд5.1 секундПростое решениеМедленно.
Експерементальное решение.
Категории
  • DevOps
  • Docker
Предыдущая заметка

Поднимаем Symfony в Docker контейнере

Следующая заметка

[Часть 2] RabbitMQ – примеры кода

9 комментариев

  1. Антон19 октября, 2018Ответить

    Docker-sync помог укорить работу с Symfony 4. Подводных камней пока не встретил.

    • windsurfer Автор19 октября, 2018Ответить

      У меня была трабла только с volume когда права на файлы были разные.
      Пока пользуюсь следующим:
      B docker-compose добавил user: ${CURRENT_UID}:
      php:
      user: ${CURRENT_UID}
      # ...
      volumes:
      - # ...
      - ./app:/var/www/app:cached

      и в makefile CURRENT_UID := $(shell id -u):$(shell id -g):

      OS := $(shell uname)
      CURRENT_UID := $(shell id -u):$(shell id -g)

      start_dev:
      ifeq ($(OS),Darwin)
      docker volume create --name=app-sync
      CURRENT_UID=$(CURRENT_UID) docker-compose -f docker-compose-dev.yml up -d
      docker-sync start
      else
      docker-compose up -d
      endif

  2. Бетмен6 августа, 2019Ответить

    У меня через Docker-sync пишет всегда ошибку 404, указываю для app_sync src=”.” так было ранее и работало, может что-то следует ещё добвить?

    • windsurfer Автор28 августа, 2019Ответить

      Проверим, на момент написания статьи работало, сейчас не сильно исполюзую докер на маке, но проверю

  3. Виталий29 марта, 2020Ответить

    Почему то после установки docker-sync, он синхронизирует файлы только после docker-sync clean. Встречал такое поведение?

    • windsurfer Автор29 марта, 2020Ответить

      Тут меня этот вопрос тоже инетерсует, с каким-то обновлением перестало нормально работать при использовании unison – смотрю в сторону rsync но там есть смои нюансы с правами

    • windsurfer Автор29 марта, 2020Ответить

      скажу даже больше, мне помогает только полная перезагрузка

  4. Игорь17 октября, 2020Ответить

    Можно поступить проще, создать именованный том.
    И тогда докер не будет гонять файлы

  5. Alex Deroza8 февраля, 2021Ответить

    Совершенно устаревшие советы. Уже давным давно есть нормальное решение. Даже для если у вас разные FS.

Добавить комментарий Отменить ответ

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте как обрабатываются ваши данные комментариев.




Рубрики

  • Дизайн
    • Иконки
    • Шаблоны
      • PSD Шаблоны
  • Маркетинг
    • SEO
      • e-commerce
    • SMM
    • Контент
  • Разработка
    •  Базы данных
    • CSS
    • DevOps
      • AWS
      • Docker
      • RabbitMQ
    • JavaScript
      • Angular
      • angularjs
      • Reactjs
    • PHP
      • Laravel
      • PHP Data Object/PDO
      • PHPUnit
      • Symfony
    • Python
      • Flask
  • Юмор




Copyright © thewebland.net, 2014 - 2020 | КОПИРОВАНИЕ МАТЕРИАЛОВ САЙТА БЕЗ АКТИВНОЙ ГИПЕРССЫЛКИ НА ОРИГИНАЛ ЗАПРЕЩЕНО