Локальная разработка в Docker
Хочу поделиться тем, как я в своей работе использую Docker для локальной разработки сайтов. Я не до конца понимаю, как оно там внутри устроено и частично тут будет описано то, как я работаю «по наитию». Если у кого-то будут комментарии и предложения, буду рад услышать, как этот воркфлоу можно оптимизировать.
Главное, что нам понадобится — это Docker.
Скачать его можно по этой ссылке: https://www.docker.com/get-started.

Создание каждого проекта начинается с файла docker-compose.yml в корне проекта:
Здесь указываются реквизиты подключения к создаваемой базе данных (саму базу создавать не нужно) и путь к корню сайта внутри виртуального контейнера — /var/doodle.
Там же, в корне, создаём папку .docker, в ней будет лежать файл Dockerfile — здесь команды, которые будут выполнены при создании контейнера для PHP. Обычно из проекта в проект файл не меняется, там всё стандартно — .docker/Dockerfile
И в этой же папке будем хранить конфиг сервера, в файле vhost.conf — .docker/vhost.conf, он тоже стандартный, единственное, указываем правильный путь к публичной директории. У меня это /var/doodle/www.
Вот так выглядит набор файлов на первом этапе:

Теперь запускаем создание контейнеров — docker-compose up -d. В первый раз будут скачиваться нужные файлы, будет происходить установка контейнеров и прочее. В дальнейшем эта команда просто запустит уже готовые контейнеры.
После того, как всё будет готово, загружаем MODX в папку www и можем запустить его установку по адресу http://localhost/setup/.
В качестве хоста для базы данных на MacOS нужно использовать host.docker.internal. Логин, пароль и имя базы данных указываем те, которые мы указали в docker-compose.yml

После установки MODX можно добавить в корень проекта .gitignore, чтобы лишние файлы в репозиторий не выгружались — .gitignore. И создать, собственно, git-репозиторий:
Думаю, всем более-менее понятно, что в репозитории легко хранятся файловые элементы. Но в MODX до сих пор очень плотно приходится работать с базой данных и в команде нужно как-то синхронизировать записи в таблицах, саму структуру и пр.
Поэтому в командной работе приходится плотно знакомиться с миграциями. Миграции — это просто скрипты, которые производят операции в базе данных. То есть вместо того, чтобы создавать ресурс через админку MODX, вам нужно писать скрипт, который будет это делать — через newObject или runProcessor.
Для миграций удобно использовать phinx. Его просто установить через composer:
Настройки миграций хранятся в файле phinx.php — здесь мы подключаем конфиг MODX, соответственно, реквизиты подключения к базе данных берём из этого конфига. Так же указываем шаблон для создания новых миграций db/modx_migration_template.php, где вы можете сохранить требуемую вам структуру файла миграций. Этот шаблон будет использоваться для всех новых команд.
Так как база данных у нас работает внутри контейнера, для выполнения команд, которые требуют подключения к базе данных, нужно запускать их изнутри. Команда, чтобы «войти» в контейнер:
Мы окажемся в папке /var/www/html. Перейдём в папку проекта и создадим нашу первую миграцию:
Эта команда создаст файл в папке db/migrations. Вот так выглядит переименование главной страницы — db/migrations/20211010090307_first_migration.php, а вот так можно установить нужные пакеты — db/migrations/20211010092235_install_packages.php
Но все эти сложности нужны не просто так, а для реализации командной разработки и лёгкого деплоя. Давайте, разберёмся, как теперь выгрузить нашу работу на продакшен.
Первая сложность, с которой мы столкнёмся — это доступы к базе данных в конфиг-файле. Во-первых, хранить пароль к базе данных от продакшена в гитхабе — это плохая идея. А во-вторых, у каждого локальные доступы к базе данных будут свои, нужно это предусмотреть. Отредактируем www/core/config/config.inc.php — в начале файла проверим наличие локального конфига с доступами:
Таким образом в файле config.environment.inc.php мы будем переопределять доступы к базе данных. Этот файл уже добавлен в .gitignore и в репозиторий выгружаться не будет. Так же нужно отредактировать файлы config.core.php — поменять там пути на относительные.

Разворачивать «продакшен» будем на modhost.pro. Создаём новый сайт с чистым MODX. Когда сайт будет установлен, просто удаляем папку www и клонируем репозиторий в корень аккаунта:
Чтобы сайт был доступен извне, создадим символическую ссылку для папки www
И укажем доступы к базе данных в файле doodle/www/core/config/config.environment.inc.php:
Теперь останется запустить миграции:
На этом всё — продакшен развёрнут. Можно продолжать разработку локально, в разных ветках. А деплой будет заключаться в стягивании изменений из гитхаба и запуске миграций:
Главное, что нам понадобится — это Docker.
Скачать его можно по этой ссылке: https://www.docker.com/get-started.

Создание каждого проекта начинается с файла docker-compose.yml в корне проекта:
version: "3"
services:
nginx:
image: nginx:latest
stdin_open: true
tty: true
ports:
- 80:80
volumes:
- 'nfsmount:/var/doodle'
- ./.docker/vhost.conf:/etc/nginx/conf.d/default.conf:delegated
depends_on:
- php
php:
build: '.docker/'
volumes:
- 'nfsmount:/var/doodle'
mariadb:
image: mariadb
ports:
- 3306:3306
command: [
'--character-set-server=utf8mb4',
'--collation-server=utf8mb4_unicode_ci'
]
volumes:
- ../mysql-data/database:/var/lib/mysql
environment:
MYSQL_DATABASE: doodle
MYSQL_ROOT_USER: root
MYSQL_ROOT_PASSWORD: trOgyy&gd34Kf
volumes:
nfsmount:
driver: local
driver_opts:
type: nfs
o: addr=host.docker.internal,rw,nolock,hard,nointr,nfsvers=3
device: ":${PWD}"Здесь указываются реквизиты подключения к создаваемой базе данных (саму базу создавать не нужно) и путь к корню сайта внутри виртуального контейнера — /var/doodle.
Там же, в корне, создаём папку .docker, в ней будет лежать файл Dockerfile — здесь команды, которые будут выполнены при создании контейнера для PHP. Обычно из проекта в проект файл не меняется, там всё стандартно — .docker/Dockerfile
И в этой же папке будем хранить конфиг сервера, в файле vhost.conf — .docker/vhost.conf, он тоже стандартный, единственное, указываем правильный путь к публичной директории. У меня это /var/doodle/www.
Вот так выглядит набор файлов на первом этапе:

Теперь запускаем создание контейнеров — docker-compose up -d. В первый раз будут скачиваться нужные файлы, будет происходить установка контейнеров и прочее. В дальнейшем эта команда просто запустит уже готовые контейнеры.
После того, как всё будет готово, загружаем MODX в папку www и можем запустить его установку по адресу http://localhost/setup/.
В качестве хоста для базы данных на MacOS нужно использовать host.docker.internal. Логин, пароль и имя базы данных указываем те, которые мы указали в docker-compose.yml

После установки MODX можно добавить в корень проекта .gitignore, чтобы лишние файлы в репозиторий не выгружались — .gitignore. И создать, собственно, git-репозиторий:
git init && git add -A && git commit -m "Initial commit"Думаю, всем более-менее понятно, что в репозитории легко хранятся файловые элементы. Но в MODX до сих пор очень плотно приходится работать с базой данных и в команде нужно как-то синхронизировать записи в таблицах, саму структуру и пр.
Поэтому в командной работе приходится плотно знакомиться с миграциями. Миграции — это просто скрипты, которые производят операции в базе данных. То есть вместо того, чтобы создавать ресурс через админку MODX, вам нужно писать скрипт, который будет это делать — через newObject или runProcessor.
Для миграций удобно использовать phinx. Его просто установить через composer:
composer require robmorgan/phinxНастройки миграций хранятся в файле phinx.php — здесь мы подключаем конфиг MODX, соответственно, реквизиты подключения к базе данных берём из этого конфига. Так же указываем шаблон для создания новых миграций db/modx_migration_template.php, где вы можете сохранить требуемую вам структуру файла миграций. Этот шаблон будет использоваться для всех новых команд.
Так как база данных у нас работает внутри контейнера, для выполнения команд, которые требуют подключения к базе данных, нужно запускать их изнутри. Команда, чтобы «войти» в контейнер:
docker exec -it doodle_php_1 bashМы окажемся в папке /var/www/html. Перейдём в папку проекта и создадим нашу первую миграцию:
cd /var/doodle/
vendor/bin/phinx create FirstMigrationЭта команда создаст файл в папке db/migrations. Вот так выглядит переименование главной страницы — db/migrations/20211010090307_first_migration.php, а вот так можно установить нужные пакеты — db/migrations/20211010092235_install_packages.php
Но все эти сложности нужны не просто так, а для реализации командной разработки и лёгкого деплоя. Давайте, разберёмся, как теперь выгрузить нашу работу на продакшен.
Первая сложность, с которой мы столкнёмся — это доступы к базе данных в конфиг-файле. Во-первых, хранить пароль к базе данных от продакшена в гитхабе — это плохая идея. А во-вторых, у каждого локальные доступы к базе данных будут свои, нужно это предусмотреть. Отредактируем www/core/config/config.inc.php — в начале файла проверим наличие локального конфига с доступами:
<?php
/**
* MODX Configuration file
*/
if (file_exists(__DIR__ . '/config.environment.inc.php')) {
/* Include configuration for the current environment. */
include __DIR__ . '/config.environment.inc.php';
} else {
$database_type = 'mysql';
$database_server = 'host.docker.internal';
$database_user = 'root';
$database_password = 'trOgyy&gd34Kf';
$database_connection_charset = 'utf8mb4';
$dbase = 'doodle';
$table_prefix = 'modx_';
$database_dsn = 'mysql:host=host.docker.internal;dbname=doodle;charset=utf8mb4';
}
// ...Таким образом в файле config.environment.inc.php мы будем переопределять доступы к базе данных. Этот файл уже добавлен в .gitignore и в репозиторий выгружаться не будет. Так же нужно отредактировать файлы config.core.php — поменять там пути на относительные.

Разворачивать «продакшен» будем на modhost.pro. Создаём новый сайт с чистым MODX. Когда сайт будет установлен, просто удаляем папку www и клонируем репозиторий в корень аккаунта:
rm -rf www && git clone git@github.com:ilyautkin/doodle.gitЧтобы сайт был доступен извне, создадим символическую ссылку для папки www
ln -s doodle/www wwwИ укажем доступы к базе данных в файле doodle/www/core/config/config.environment.inc.php:
<?php
$database_type = 'mysql';
$database_server = '127.0.0.1';
$database_user = 's27685';
$database_password = 'dfHdhDFi67FDy5';
$database_connection_charset = 'utf8mb4';
$dbase = 's27685';
$table_prefix = 'fnO7CLkAJH1e_';
$database_dsn = 'mysql:host=127.0.0.1;dbname=s27685;charset=utf8mb4';Теперь останется запустить миграции:
cd doodle
php7.3 /usr/bin/composer.phar install
php7.3 vendor/bin/phinx migrateНа этом всё — продакшен развёрнут. Можно продолжать разработку локально, в разных ветках. А деплой будет заключаться в стягивании изменений из гитхаба и запуске миграций:
git pull && php7.3 vendor/bin/phinx migrate Комментарии: 35
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
Единственное, на докере разворачиваю стек с nodejs и mongo, там вместо host.docker.internal обычно указываю название контейнера базы данных.
git pull это еще не ответы на все вопросы. В чем смысл разрабатывать в докере если контейнер не выгружается на сервер? Я вот еще раз прочел пошагово инструкцию и вижу, что Илья создает инфраструктуру из докер контейнеров у себя локально, а вот на сервер то это не попадает? Туда идут только исходные коды из git? Разве смысл контейнеризации не в том, чтобы один и тот же контейнер запустить как у себя локально так и на сервере? Где в инструкции установка докера на сервере? Где копирование контейнеров на сервер, где их запуск?
спроситьиспользовать, увидит, что всё не так страшно и даже modx можно вписать в современный стек разработки.Само-собой предполагается, что нужно почитать ещё материалы по теме, но чтобы попробовать — вполне достаточно.
Надо оно для modx или нет — решает каждый сам для себя, конечно. Я однозначно рекомендую попробовать, хотя бы для своего роста как разработчика. Чтобы потом легко перейти на современную разработку в любой команде.
Самое крутое, что я пока вижу в Doker'е — возможность разбить один большой сервис на кучу микросервисов, которые можно легко сопровождать/обновлять по отдельности + масштабирование + отказоустойчивость. Да, есть накладные расходы, но оно того однозначно стоит.
Собираюсь некоторые старые разработки перевести на Doker + k8s.
На базе этого решения функционирует текущая версия modx.pro.
Здесь конечно не миграции, но тоже php код который позволяет создать, удалить, обновить любые элементы внутри базы данных.
Так же с помощью миграции создаётся, например, раздел «Новости». Его ID сохраняется в настройках контекста. В итоге на продакшене раздел наполняется ресурсами но разработчику не требуется учитывать эти ресурсы — он всегда использует актуальный ID. У каждого разработчика, на тестовом сервере, на продакшене ID-шники разные, но это никого не парит.
Если на несложных проектах это не очень критично, то на большом проекте где и так есть проблемы с производительностью, страницы через докер грузятся у меня на маке по 10-20 секунд, работать невозможно. На винде чуть получше, но все равно хуже virtualBox'a в 2-4 раза.
Проверили очевидные гипотезы, почему это может происходить, убрали прямой mount папок из OS в контейнер (оставили заливку по ssh), вынесли файлы в отдельный volume, проверили что WSL v==2 на винде, и еще кучу всяких советов из инета. Но увы, по прежнему тормозит.
Кто-нибудь сталкивался с такими проблемами?
Поделитесь опытом, пожалуйста.
ресурс, чанк, сниппет, MIGX-конфиг и т.д. Особенно MIGX-конфиг сейчас нужен ?
По конфигам MIGX я делал так — создавал конфиг через интерфейс, потом экспортировал его и в миграции было что-то типа такого:
Если когда-нибудь решите выложить остальное открыто на гитхаб, обещаю вам сходу 5 звезд от нашей команды ??
В случае с Docker этого делать не нужно. Новому разработчику требуется только
Чуть-чуть попить чай (установка может занимать несколько минут) — и всё, можешь приступать к работе.
Все выполняю как вы описали, но вылезла куча ошибок еще на этапе построения образов.
На компьютере — Kubuntu.
А если порты (или что-то еще наверное) нужно подбирать под каждую машину отдельно (а кого то занят локальный порт 3306 а у кого-то нет) то теряется вся универсальность докера.
Расскажите, продолжаете ли вы с командой пользоваться для разработки на modx докером?
Обнаружились какие-то минусы?
Здравствуйте, подскажите пожалуйста в связи с чем может быть вызвана данная ошибка при запуске команды — docker-compose up -d?
- Error response from daemon: error while mounting volume '/var/lib/docker/volumes/docker-test_nfsmount/_data': error resolving passed in network volume address: lookup host.docker.internal: no such host
Нужно ли предоставить какие-либо дополнительные данные от меня, чтобы понять в чем может быть проблема?Error response from daemon: error while mounting volume '/var/lib/docker/volumes/doodle_nfsmount/_data': failed to mount local volume: mount :/Users/catsmeatman/Projects/doodle:/var/lib/docker/volumes/doodle_nfsmount/_data, data: addr=192.168.65.254,nolock,hard,nointr,nfsvers=3: connection refused