В свете вышедшей в свет новой версии Magento — 2.2.0, решил выложить свой персональный опыт развертывания приложений на базе этой платформы. В статье описывается развертывание приложения именно для разработки модулей, а не для эксплуатации магазина (как говорится, технарям от технаря).
Введение
После довольно продолжительного эволюционирования скриптов автоматизации процесса развертывания Magento у меня сложился следующий набор, который я оформил в виде sample-проекта: flancer32/sample_mage2_app. Проект поднимает приложение для разработки публичного модуля "flancer32/mage2_ext_login_as" (выложен на Packagist'а) и "приватного" модуля "flancer32/sample_mage2_mod_repo" (доступен только с GitHub'а).
Скрипты были созданы и проверены под Ubuntu 16.04 / PHP 7.0.22 / Composer 1.5.2. Используемые в скриптах программы (php, composer, mysql, patch, ...) должны быть установлены глобально.
Должен быть настроен доступ через Composer к соответствующим репозиториям (Magento и Github — файл ~/.composer/auth.json
):
{
"http-basic": {
"repo.magento.com": {
"username": "ab8303e79d1b86ac2676cda700bb93eb",
"password": "00037fe23c3501389f08c7eaaab0cfda"
}
},
"github-oauth": {
"github.com": "9cde8d93840271c509d95707db07a9e1ef374014"
}
}
Просьба создавать собственные параметры доступа и не использовать значения из примера.
Компоненты приложения
В самом общем случае Magento-приложение состоит из следующих частей:
- Платформа Magento 2 (типовые модули);
- Собственные модули web-приложения (включая тему);
- База данных;
- Медиа данные;
- Конфигурация;
Последовательность развертывания
Состав приложения задает последовательность рутинных действий, сводимую в общем случае, к следующей:
- конфигурирование процесса развертывания;
- развертывания Magento2-платформы;
- установка модулей web-приложения;
- инциализация базы данных;
- инициализация медиа-файлов;
- финализация (настройка прав доступа к файлам и т.п.);
Типы скриптов
Все развертывание производится при помощи shell-скриптов, которые можно разделить на три группы:
- головной скрипт (
deploy.sh
); - конфигурационный (
cfg.work.sh
); - рабочий (выполняет определенную часть работы по развертыванию);
Скрипты написаны не в стиле user friendly, а скорее в стиле friendly user — проверка входных параметров и совместимость запрошенных режимов работы друг с другом сведена к минимуму. Предполагается, что пользователь, запускающий скрипт развертывания с указанием параметров, понимает, что они означают и как они совместимы друг с другом.
Головной скрипт
Его задача — определить режим развертывания приложения, подгрузить конфигурацию развертывания и запустить рабочие скрипты в соответствии с заданным режимом. Параметры запуска deploy.sh
:
$ sh deploy.sh -h
Magento2 application deployment script.
Usage: sh deploy.sh -d [work|live] -h -m [developer|production] -E -S
Where:
-d: Web application deployment mode ([work|live], default: work);
-h: This output;
-m: Magento 2 itself deployment mode ([developer|production], default: developer);
-E: Existing DB will be used in 'work' mode);
-S: Skip database initialization (Web UI should be used to init DB);
Развертывание приложения без инициализации базы данных (база инициализируется через Web UI):
$ sh deploy.sh -S
Развертывание приложения с сохранением существующей базы (при повторном развертывании, например):
$ sh deploy.sh -E
Развертывание приложения с переводом Magento 2 в production mode (если мы разрабатываем API, например):
$ sh deploy.sh -m production
Режим развертывания live
предназначен при развертывании приложения для использования в качестве магазина и в данном примере не рассматривается.
Конфигурационный скрипт
Параметры развертывания приложения прописываются в обычном shell-скрипте в виде переменных окружения. Шаблон (cfg.init.sh
), содержащий все доступные переменные, копируется вручную в конфигурационный файл, соответствующий режиму развертывания (cfg.work.sh
или cfg.live.sh
), и заполняется соответствующими параметрами.
#!/usr/bin/env bash
# filesystem permissions
LOCAL_OWNER="owner"
LOCAL_GROUP="www-data"
# Magento 2 installation configuration
# see http://devdocs.magento.com/guides/v2.0/install-gde/install/cli/install-cli-install.html#instgde-install-cli-magento
ADMIN_EMAIL="admin@store.com"
ADMIN_FIRSTNAME="Store"
ADMIN_LASTNAME="Admin"
ADMIN_PASSWORD="..."
ADMIN_USE_SECURITY_KEY="0"
ADMIN_USER="admin"
BACKEND_FRONTNAME="admin"
BASE_URL="http://mage2.host.org:8080/"
CURRENCY="USD"
DB_HOST="localhost"
DB_NAME="mage2"
DB_PASS="..."
DB_USER="www"
LANGUAGE="en_US"
SECURE_KEY="..."
SESSION_SAVE="files"
TIMEZONE="UTC"
USE_REWRITES="0"
USE_SECURE="0"
USE_SECURE_ADMIN="0"
Рабочий скрипт
Рабочие скрипты содержат практически идентичный заголовок, позволяющий
# current directory where from script was launched (to return to in the end)
DIR_CUR="$PWD"
# Root directory (relative to the current shell script, not to the execution point)
# http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_02
DIR_ROOT=${DIR_ROOT:=`cd "$( dirname "$0" )/../../" && pwd`}
и
MODE=${MODE}
IS_CHAINED="yes" # 'yes' - this script is launched in chain with other scripts, 'no'- standalone launch;
if [ -z "$MODE" ]; then
MODE="work"
IS_CHAINED="no"
fi
# check configuration file exists and load deployment config (db connection, Magento installation opts, etc.).
FILE_CFG=${DIR_ROOT}/cfg.${MODE}.sh
if [ -f "${FILE_CFG}" ]; then
if [ "${IS_CHAINED}" = "no" ]; then # this is standalone launch, load deployment configuration;
echo "There is deployment configuration in ${FILE_CFG}."
. ${FILE_CFG}
fi
else
if [ "${IS_CHAINED}" = "no" ]; then # this is standalone launch w/o deployment configuration - exit;
echo "There is no expected configuration in ${FILE_CFG}. Aborting..."
cd ${DIR_CUR}
exit 255
fi
fi
Конфигурирование процесса развертывания
Здесь все просто — запускается конфигурационный скрипт, который задает соответствующие переменные окружения:
FILE_CFG=${DIR_ROOT}/cfg.${MODE}.sh
if [ -f "${FILE_CFG}" ]
then
echo "There is deployment configuration in ${FILE_CFG}."
. ${FILE_CFG}
else
echo "There is no expected configuration in ${FILE_CFG}. Aborting..."
cd ${DIR_CUR}
exit 255
fi
Развертывания Magento2-платформы
По большому счету все сводится к созданию в соответствующем каталоге (work
)
DIR_MAGE=${DIR_ROOT}/${MODE} # root folder for Magento application
...
# (re)create root folder for application deployment
if [ -d "${DIR_MAGE}" ]; then
if [ "${MODE}" = "${MODE_WORK}" ]; then
echo "Re-create '${DIR_MAGE}' folder."
rm -fr ${DIR_MAGE} # remove Magento root folder
mkdir -p ${DIR_MAGE} # ... then create it
fi
else
mkdir -p ${DIR_MAGE} # just create folder if not exist
fi
echo "Magento will be installed into the '${DIR_MAGE}' folder."
приложения через Composer:
composer create-project --repository-url=https://repo.magento.com/ magento/project-community-edition=2.2.0 ${DIR_MAGE}
Таким образом, корневой каталог для конфигурации web-сервера: ${DIR_ROOT}/work
Установка модулей web-приложения
Эта часть процесса зависит от режима развертывания. Сначала донастраивается дескриптор развертывания приложения (work/composer.json
) — здесь важно обратить внимание на версию Composer'а (например, на старых версиях не работает composer config minimum-stability
):
echo "Configure composer.json"
composer config minimum-stability dev
echo "Add custom repositories"
composer config repositories.local '{"type": "artifact", "url": "../deploy/repo/"}' # relative to root Mage dir
затем устанавливаются нужные версии нужных модулей:
echo "Add own modules"
# public module from Packagist
composer require flancer32/mage2_ext_login_as:dev-master
# add private/public GitHub repo & install module from this repo
composer config repositories.sample_repo vcs https://github.com/flancer32/sample_mage2_mod_repo
composer require flancer32/sample_mage2_mod_repo:dev-master
# add zipped module from local repository (see deploy/repo/sample_mage2_mod_zip-0.1.0.zip)
composer require flancer32/sample_mage2_mod_zip
В данном случае мы подключили к приложению два модуля для разработки:
- flancer32/mage2_ext_login_as
- flancer32/sample_mage2_mod_repo
Остается указать IDE, что данные модули находятся под контролем версий:
Опционально можно применить патчи как к сторонним модулям (как в случае с flancer32/sample_mage2_mod_zip
, установленном из zip'а), так и к исходникам самой Magento (в последнее время Magento Team значительно улучшила работу с правками, но все равно бывает необходимость применить известную "таблетку", которая не вошла в крайний релиз):
echo "Apply patches"
patch vendor/flancer32/sample_mage2_mod_zip/etc/module.xml ${DIR_DEPLOY}/patch/mod_sequence.patch
В данном случае патчится сторонний модуль flancer32/sample_mage2_mod_zip
, в который добавляется порядок загрузки:
<module name="Flancer32_SampleZip" setup_version="0.1.0">
<sequence>
<module name="Flancer32_SampleRepo"/>
</sequence>
</module>
Инициализация базы данных
deploy/bin/app/db/work.sh
Также зависит от режима развертывания и от ключей запуска deploy.sh
. Возможен вариант, когда нужно пересоздать базу:
echo "Drop DB '${DB_NAME}'."
mysqladmin -f -u"${DB_USER}" -p"${DB_PASS}" -h"${DB_HOST}" drop "${DB_NAME}"
echo "Create DB '${DB_NAME}'."
mysqladmin -f -u"${DB_USER}" -p"${DB_PASS}" -h"${DB_HOST}" create "${DB_NAME}"
echo "DB '${DB_NAME}' is created."
# Full list of the available options:
# http://devdocs.magento.com/guides/v2.0/install-gde/install/cli/install-cli-install.html#instgde-install-cli-magento
php ${DIR_MAGE}/bin/magento setup:install --admin-firstname="${ADMIN_FIRSTNAME}" --admin-lastname="${ADMIN_LASTNAME}" --admin-email="${ADMIN_EMAIL}" --admin-user="${ADMIN_USER}" --admin-password="${ADMIN_PASSWORD}" --base-url="${BASE_URL}" --backend-frontname="${BACKEND_FRONTNAME}" --key="${SECURE_KEY}" --language="${LANGUAGE}" --currency="${CURRENCY}" --timezone="${TIMEZONE}" --use-rewrites="${USE_REWRITES}" --use-secure="${USE_SECURE}" --use-secure-admin="${USE_SECURE_ADMIN}" --admin-use-security-key="${ADMIN_USE_SECURITY_KEY}" --session-save="${SESSION_SAVE}" --cleanup-database --db-host="${DB_HOST}" --db-name="${DB_NAME}" --db-user="${DB_USER}" --db-password="${DB_PASS}"
или просто подключить приложение к существующей базе:
php ${DIR_MAGE}/bin/magento setup:install --admin-firstname="${ADMIN_FIRSTNAME}" --admin-lastname="${ADMIN_LASTNAME}" --admin-email="${ADMIN_EMAIL}" --admin-user="${ADMIN_USER}" --admin-password="${ADMIN_PASSWORD}" --backend-frontname="${BACKEND_FRONTNAME}" --key="${SECURE_KEY}" --session-save="${SESSION_SAVE}" --db-host="${DB_HOST}" --db-name="${DB_NAME}" --db-user="${DB_USER}" --db-password="${DB_PASS}"
После подключения приложения к базе можно произвести донастройку базы. Например так:
echo "Additional DB setup."
MYSQL_EXEC="mysql -u ${DB_USER} --password=${DB_PASS} -D ${DB_NAME} -e "
${MYSQL_EXEC} "REPLACE INTO core_config_data SET value = '1', path ='fl32_loginas/controls/customers_grid_action'"
В версии 2.2.0 есть возможность прописывать параметры конфигурации через CLI, но напрямую в базе можно задавать не только эти параметры, но и многое другое (например, задавать налоговые ставки).
Инициализация медиа-файлов
В общем случае, при развертывании магазина с темой, требуется инициализация медиа-файлов (из backup'а или клонирование с эталонного сервера). При разработке модулей этот шаг можно пропустить. Пропускаем.
Финализация
Финализацию можно разбить на две части: специфичная для режима развертывания и общая.
В зависимости от режима можно выполнять перевод приложения в developer/production mode, включать/отключать кэш, проводить компиляцию кода:
if [ "${OPT_MAGE_RUN}" = "developer" ]; then
php ${DIR_MAGE}/bin/magento deploy:mode:set developer
php ${DIR_MAGE}/bin/magento cache:disable
php ${DIR_MAGE}/bin/magento setup:di:compile
else
php ${DIR_MAGE}/bin/magento deploy:mode:set production
fi
и запускать команды установленных модулей:
if [ "${OPT_USE_EXIST_DB}" = "no" ]; then
php ${DIR_MAGE}/bin/magento fl32:init:catalog
php ${DIR_MAGE}/bin/magento fl32:init:customers
php ${DIR_MAGE}/bin/magento fl32:init:sales
fi
В конце желательно запустить хоть раз cron и выполнить переиндексацию (чтобы сократить ругань в админке):
php ${DIR_MAGE}/bin/magento indexer:reindex
php ${DIR_MAGE}/bin/magento cron:run
Общая финализация развертывания включает в себя установку прав доступа к файлам:
if [ -z "${LOCAL_OWNER}" ] || [ -z "${LOCAL_GROUP}" ] || [ -z "${DIR_MAGE}" ]; then
echo "Skip file system ownership and permissions setup."
else
echo "Set file system ownership (${LOCAL_OWNER}:${LOCAL_GROUP}) and permissions to '${DIR_MAGE}'..."
chown -R ${LOCAL_OWNER}:${LOCAL_GROUP} ${DIR_MAGE}
find ${DIR_MAGE} -type d -exec chmod 770 {} \;
find ${DIR_MAGE} -type f -exec chmod 660 {} \;
fi
# setup permissions for critical files/folders
chmod u+x ${DIR_MAGE}/bin/magento
chmod -R go-w ${DIR_MAGE}/app/etc
Заключение
Описанный в статье процесс развертывания приложения на базе Magento 2 не является универсальным и может модифицироваться в зависимости от проекта.
Как говорилось в древние времена, очередную версию Windows можно начинать использовать после выхода второго сервис-пака. Всех причастных — с выходом Magento 2.2.0! А Magento Team — стойкости и оптимизма в этой безнадежно проигранной борьбе с непреодолимой сложностью кода и вероломством требований!!!
sashas777
Что то подобное реализовано в Magento Cloud.
Думаю было бы лучше из этих файлов сделать модуль который доавбляет команды в Magento CLI. Тогда можно сразу использовать с помощью php bin/magento
isxam
Плохое решение. Скрипты из статья, насколько я понял, выполняют развертывание приложения и настройку окружения. Magento CLI работает с развернутым приложением.
isxam
Вам не подошли готовые решения для быстрой настройки дев-окружения по каким-то причинам?
github.com/magento/magento2devbox-web
github.com/paliarush/magento2-vagrant-for-developers
flancer Автор
Предпочитаю работать с первоисточниками и самому комбинировать необходимые сервисы/приложения в соответствии с текущим моментом. Тем более, я с Docker'ом "не дружу" — как-то не попался он мне на пути в таком виде, чтобы я с ним "сдружился". У меня скрипты shell'овские и, по-большому, счету, просто автомтатизируют рутинные операции, которые можно сделать вручную с консоли. Никакой скрытой магии. Как я написал в заключении — это не универсальное (суть — сложное), а типовое решение (суть — часто используемое). Под "типовым" я подразумеваю, что при развертывания среды для разработки Magento-модуля нужно:
Все это можно сделать через консоль. И заскриптовать.
А за ссылки — спасибо. Будет интересно глянуть :)