Docker-окружение для 1С-Битрикс - сервисы, требования, права на файлы
Docker-окружение - это набор контейнеров, которые на машине разработчика
поднимают тот же стек, что работает на боевом хостинге Битрикс: PHP нужной
версии с нужными расширениями, MySQL с нужными настройками, кеш, а при
необходимости - поиск и перехватчик почты. Поднять php:8.4-fpm и mysql:8.0
из Docker Hub можно за пять минут. Но это не значит, что на таком стеке
заработает 1С-Битрикс. Платформа проверяет десятки параметров окружения. Часть
настроек, которые в официальных образах стоят по умолчанию, для Битрикс
несовместимы напрямую. Разберём, из чего должно состоять Docker-окружение под
Битрикс, что именно проверяет платформа при установке и почему типовой контейнер
приходится донастраивать, а не использовать как есть.
Как это работает
«Проверка системы» - это не формальность, а список конкретных условий.
Проверка идёт при установке и потом в «Настройки → Инструменты → Проверка
системы». Битрикс сверяет версию PHP, набор расширений и значения php.ini.
Дальше идут версия и кодировка базы, права на запись в директории и доступность
.htaccess. Пока хотя бы один пункт не пройден, мастер установки не даёт
двигаться дальше. Это тот же список требований, что разобран в статье
«Окружение и
деплой» применительно к BitrixVM. Docker-окружение
проходит ту же проверку, а не более мягкую «локальную» версию.
Официальные образы Docker собраны под универсальный случай, а не под
конкретный продукт, и это расходится с требованиями Битрикс в нескольких
точках. Образ mysql:8.0 из коробки строгий: sql_mode включает
STRICT_TRANS_TABLES и ещё несколько режимов. Ядро Битрикс годами писалось в
расчёте на пустой sql_mode. Без этой правки восстановление резервной копии
падает с ошибкой о недопустимом значении по умолчанию для поля типа TIMESTAMP.
Официальный образ PHP-FPM не содержит AMQP, LDAP и часть других расширений,
которые платформа требует безусловно, а не по желанию. А если веб-сервер nginx,
а не Apache, конфигурация ядра под .htaccess и mod_rewrite просто не
читается. Файлы .htaccess nginx не поддерживает ни при какой настройке.
Правила ЧПУ либо переносят в конфиг nginx вручную, либо включают предусмотренный
Битриксом PHP-фолбэк маршрутизации.
Граница контейнера - это ещё и граница пользователя файловой системы.
Процессы внутри контейнера работают от своего пользователя. Часто это www-data
с UID 33 или 82, в зависимости от базового образа. Те же файлы на хосте
редактирует разработчик под своим UID. Когда исходники подключены через bind
mount, PHP из контейнера создаёт файлы кеша с одним владельцем, а редактор на
хосте - с другим: в результате в контейнере или на хосте периодически всплывает
Permission denied. На Linux-хосте несовпадение UID видно сразу; на macOS и
Windows Docker Desktop транслирует права прозрачнее, но сам факт разных
пользователей по разные стороны границы остаётся.
Файловая система хоста и файловая система контейнера - разные вещи, и на macOS
это особенно заметно. Только в /bitrix/ у Битрикс лежат десятки тысяч файлов
- ядро, компоненты, языковые файлы. При обычном bind mount каждое обращение к файлу на macOS и Windows проходит через прослойку виртуализации. Это ощутимо медленнее прямого доступа на Linux- хосте, где контейнер работает поверх того же ядра ОС. Docker Desktop уже переключился на VirtioFS вместо более медленного gRPC FUSE и заметно сократил разрыв. Но для проекта с таким количеством мелких файлов разница с нативной линуксовой скоростью всё равно ощущается. Заметнее всего она в админке и при установке зависимостей.
Кодировка и часовой пояс - это не разовая настройка, а согласованность между
сервисами. Начиная с версии продукта 24.0.0 Битрикс поставляется только в
UTF-8. MySQL 8 с версии 8.0.1 сам по умолчанию использует utf8mb4 с
сортировкой utf8mb4_0900_ai_ci. В этой части свежий официальный образ уже
соответствует требованиям без правок. С часовым поясом сложнее: согласованно он
не выставляется нигде по умолчанию. У контейнера PHP, контейнера MySQL и хоста
может быть разный TZ. Тогда дата создания записи в админке, время срабатывания
агента и метка в логе веб-сервера расходятся между собой без единой видимой
причины.
Чем это отличается от BitrixVM. BitrixVM - это готовый и уже согласованный
набор сервисов. Туда входят nginx- фронтенд, Apache-бэкенд, база, memcached и
Redis, Sphinx и push-сервер на Node.js. Сверху идут консольное меню управления и
служба автоподстройки памяти процессов под объём RAM. Docker даёт куда более
гибкую среду именно для разработки. Окружение легко поднять и снести, а разные
версии PHP живут рядом без конфликта портов и системных пакетов. Но большую
часть того, что в BitrixVM уже собрано и протестировано, в Docker приходится
добирать руками. Это свой образ с нужными расширениями PHP, отдельный контейнер
под Sphinx и перевод .htaccess под nginx. У самого 1С-Битрикс есть публичный
репозиторий bitrix-tools/env-docker. Он собирает под Docker Compose большую
часть этого набора: nginx, PHP, базу на выбор, Redis, Memcached, Sphinx. Туда же
входят служебный контейнер для агентов по расписанию, push-сервер и отправка
почты через msmtp. Сами разработчики отмечают, что это окружение для
тестирования и разработки. К продакшену без дополнительной настройки
безопасности оно не готово.
Примеры
1. Состав окружения: docker-compose.yml
services: php: build: ./docker/php # свой Dockerfile - пример 2 volumes: - ./:/home/bitrix/www environment: TZ: Europe/Moscow depends_on: mysql: condition: service_healthy
nginx: image: nginx:1.27 volumes: - ./:/home/bitrix/www - ./docker/nginx/site.conf:/etc/nginx/conf.d/default.conf:ro ports: - "8080:80" depends_on: - php
mysql: image: mysql:8.0 command: --sql-mode="" # см. пример 3 - почему это обязательно environment: MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD} MYSQL_DATABASE: bitrix TZ: Europe/Moscow volumes: - db_data:/var/lib/mysql healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] interval: 5s retries: 10
redis: image: redis:7 command: --maxmemory 256mb --maxmemory-policy allkeys-lru
mailpit: # перехватчик почты, практика сообщества - см. справочник image: axllent/mailpit ports: - "8025:8025"
volumes: db_data:Результат запуска:
$ docker compose up -d$ docker compose psNAME IMAGE STATUSbitrix-php-1 bitrix-php Up (healthy)bitrix-nginx-1 nginx:1.27 Upbitrix-mysql-1 mysql:8.0 Up (healthy)bitrix-redis-1 redis:7 Upbitrix-mailpit-1 axllent/mailpit UpЗдесь пять сервисов вместо привычных «веб плюс база». Кеш и перехватчик почты для разработки не опциональны, а входят в минимальный состав. Без них счётчики, сессии под нагрузкой и письма заказа либо не тестируются вовсе, либо тестируются отправкой на реальные ящики.
2. Проверка требований платформы
FROM php:8.4-fpm
RUN apt-get update && apt-get install -y \ libfreetype6-dev libjpeg62-turbo-dev libzip-dev \ libldap2-dev librabbitmq-dev \ && docker-php-ext-configure gd --with-freetype --with-jpeg \ && docker-php-ext-configure ldap \ && docker-php-ext-install gd zip ldap mysqli opcache pcntl \ && pecl install amqp && docker-php-ext-enable amqp
COPY docker/php/zz-bitrix.ini /usr/local/etc/php/conf.d/zz-bitrix.inizz-bitrix.ini - тот же набор критических параметров, что и для обычного
хостинга (подробности и полный список - в статье «Окружение и
деплой»): memory_limit, max_execution_time,
upload_max_filesize, mbstring.func_overload = 0, включённый акселератор.
Префикс zz- не случаен - PHP подключает файлы conf.d/ по алфавиту, и имя с
zz- гарантирует, что эти значения подключатся после образовских настроек по
умолчанию и переопределят их.
Проверка после сборки:
$ docker compose exec php php -m | grep -Ei "gd|ldap|amqp|mbstring|zip"amqpgdldapmbstringzip
$ docker compose exec php php -i | grep -E "memory_limit|max_execution_time|short_open_tag"memory_limit => 256M => 256Mmax_execution_time => 300 => 300short_open_tag => On => OnБез этих расширений «Проверка системы» в админке отчитается по каждому
отсутствующему пункту отдельной строкой. До установки ту же роль играет скрипт
bitrix_server_test.php, который кладут в корень сайта. Мастер установки не
пустит дальше шага проверки, пока список не станет пустым.
3. Работа с базой: sql_mode и кодировка
Восстановление боевого бэкапа на образе MySQL 8 без правок выглядит так:
$ docker compose exec -T mysql mysql -uroot -p bitrix < backup/dbase.sqlERROR 1067 (42000) at line 4218: Invalid default value for 'TIMESTAMP_X'Причина - строгий sql_mode по умолчанию: ONLY_FULL_GROUP_BY,
STRICT_TRANS_TABLES, NO_ZERO_DATE, NO_ZERO_IN_DATE,
ERROR_FOR_DIVISION_BY_ZERO, NO_ENGINE_SUBSTITUTION. Ядро Битрикс на этот
режим не рассчитано, и та же ошибка при переносе на строгий MySQL 8 регулярно
всплывает у разработчиков и на обычном хостинге, а не только в Docker. После
добавления command: --sql-mode="" в сервис MySQL (пример 1) проверка отдаёт
пустое значение:
$ docker compose exec mysql mysql -uroot -p -e "SHOW VARIABLES LIKE 'sql_mode'"+---------------+-------+| Variable_name | Value |+---------------+-------+| sql_mode | |+---------------+-------+Кодировку при этом отдельно донастраивать не нужно. В отличие от sql_mode,
здесь свежий официальный образ уже соответствует требованиям:
$ docker compose exec mysql mysql -uroot -p -e "SHOW VARIABLES LIKE 'character_set_server'"+----------------------+---------+| Variable_name | Value |+----------------------+---------+| character_set_server | utf8mb4 |+----------------------+---------+С версии 8.0.1 utf8mb4 и сортировка utf8mb4_0900_ai_ci - значения по
умолчанию в самом MySQL, а не особая настройка под Битрикс.
4. Права на файлы
# docker/php/Dockerfile, продолжение примера 2ARG UID=1000ARG GID=1000RUN groupmod -o -g ${GID} www-data \ && usermod -o -u ${UID} -g www-data www-dataUSER www-dataservices: php: build: context: ./docker/php args: UID: ${UID:-1000} GID: ${GID:-1000}Запуск с UID и GID текущего пользователя хоста:
$ UID=$(id -u) GID=$(id -g) docker compose up -d --build$ docker compose exec php ls -la bitrix/cache | head -2drwxr-xr-x 4 www-data www-data 128 ... .$ ls -la bitrix/cache | head -2drwxr-xr-x 4 vadim staff 128 ... .Имена владельца отличаются: www-data в контейнере и реальный пользователь на
хосте. А числовой UID совпадает, и именно он определяет права в Unix. Файл,
созданный процессом контейнера, редактируется с хоста без sudo. В обратную
сторону запись тоже проходит без ошибок.
5. Восстановление из бэкапа против чистой установки
Для нового проекта - чистая установка, скрипт кладут в примонтированный каталог с исходниками и открывают в браузере:
$ docker compose exec php sh -c \ "cd /home/bitrix/www && wget https://www.1c-bitrix.ru/download/scripts/bitrixsetup.php"# мастер: лицензия -> ключ + отметка "для разработки" + кодировка -># проверка системы -> параметры БД -> структура -> администраторДля действующего проекта - восстановление из резервной копии: в тот же каталог
кладут архив и restore.php, дальше тоже через браузер:
$ cp backup/*.tar.gz restore.php .# мастер: распаковка -> восстановление БД -> удаление служебных файловПосле восстановления домен в базе всё ещё указывает на боевой адрес, а не на
localhost - в «Настройки → Сайты» нужно поправить путь и домен сайта на
локальный, иначе будут редиректы на старый адрес или 404 на части страниц.
Лицензионный ключ отдельно покупать не нужно. Соглашение разрешает вторую копию
продукта под тем же ключом при двух условиях. Она отмечена как «Установка
предназначена для разработки» и не открыта в публичный доступ. Без этой отметки
рассинхронизация системы обновлений между копиями даёт ошибку
ERROR_WRONG_CODE.
Справочник
| Сервис | Роль | Ключевые параметры |
|---|---|---|
| PHP-FPM (свой образ) | выполняет код Битрикс | версия 8.2+ (рекомендуется 8.4+), обязательные расширения, включённый OPcache, memory_limit и лимиты загрузки файлов |
| nginx или Apache с mod_php | отдаёт статику, маршрутизирует запросы | nginx не читает .htaccess вообще - нужен перевод правил в конфиг или встроенный PHP-фолбэк маршрутизации ЧПУ |
| MySQL 8.0+ / MariaDB 10.x-11.x | хранит данные | пустой sql_mode, utf8mb4 с utf8mb4_0900_ai_ci (MySQL 8) или utf8mb4_unicode_ci (MariaDB) |
| Redis или Memcached | кеш, хранилище сессий под нагрузкой | не идёт «бесплатно» в контейнере веб-сервера - отдельный сервис в compose-файле |
| Sphinx (по необходимости) | полнотекстовый поиск вместо встроенного в модуль «Поиск» | связь по протоколу MySQL на порту 9306, real-time индекс, обязательная переиндексация после запуска |
| SMTP-перехватчик почты (по необходимости, практика сообщества) | ловит письма заказа и уведомлений для просмотра, не отправляя их реальным адресатам | например Mailpit - открытый инструмент с веб-интерфейсом на отдельном порту |
| cron-контейнер | выполняет агенты и почтовые события по расписанию, а не «на хитах» | тот же образ, что и PHP-FPM, но с процессом cron вместо веб-сервера |
Частые ошибки
«Переменная sql_mode в MySQL должна быть пустая» на проверке системы или
ошибка при восстановлении бэкапа. Официальный образ MySQL 8 включает строгий
sql_mode по умолчанию (STRICT_TRANS_TABLES и другие режимы), а ядро Битрикс
рассчитано на пустое значение. Решение - sql-mode="" в параметрах запуска
контейнера или конфиге MySQL.
ЧПУ-адреса отдают 404, хотя в компоненте и в админке всё настроено
правильно. Правила маршрутизации ядра рассчитаны на .htaccess и Apache
mod_rewrite. А в контейнере веб-сервером работает nginx, который .htaccess
не читает ни при какой настройке. Решение - перенести нужные правила в конфиг
nginx вручную или включить штатный PHP-фолбэк маршрутизации, которым пользуется
и официальный Docker-репозиторий 1С-Битрикс.
Permission denied при записи в кеш или upload, либо все файлы в git
выглядят изменёнными по правам доступа. Процесс в контейнере пишет файлы от
своего пользователя с одним UID. На хосте с теми же файлами работает разработчик
под другим UID. Решение - собирать образ PHP с ARG UID/GID, подставляя
значения текущего пользователя хоста при сборке.
Админка и установка зависимостей заметно тормозят на Mac, хотя тот же проект
на боевом сервере работает быстро. Причина - bind mount поверх прослойки
виртуализации. У Битрикс только в /bitrix/ лежат десятки тысяч файлов. Каждое
обращение к ним медленнее, чем на Linux-хосте без такой прослойки. Проверьте в
настройках Docker Desktop, что для обмена файлами используется VirtioFS, а не
более медленный старый режим.
После переноса рабочей копии в контейнер обновления перестают ставиться с
ERROR_WRONG_CODE. Копия не отмечена как «Установка предназначена для
разработки», либо автопроверка обновлений включена сразу на двух копиях продукта
под одним ключом. Решение - проставить отметку и отключить автопроверку на
dev-копии, оставив её только на боевой.
Правки кода не применяются, пока не перезапустишь контейнер. В образ
скопирован php.ini с боевыми настройками OPcache (opcache.revalidate_freq = 0, validate_timestamps = Off) - акселератор не перечитывает изменённые файлы.
Для локальной разработки нужен противоположный режим:
opcache.validate_timestamps = On и низкий revalidate_freq, тогда правки
подхватываются на следующий запрос.
Частые вопросы
Чем Docker-окружение отличается от BitrixVM для локальной разработки?
BitrixVM - готовый и уже согласованный стек с консольным меню и автоподстройкой памяти, все нужные сервисы идут из коробки (подробно - в статье «Окружение и деплой»). Docker даёт больше гибкости именно для разработки: лёгкий подъём и снос окружения, несколько проектов с разными версиями PHP без конфликта портов, - но состав BitrixVM (нужные расширения PHP, Sphinx, перевод .htaccess под nginx) в Docker чаще всего приходится собирать самостоятельно. У самого 1С-Битрикс есть публичный репозиторий bitrix-tools/env-docker, который собирает большую часть этого набора под Docker Compose, но сами разработчики называют его окружением для тестирования, а не готовым к продакшену решением.
Можно ли взять любой официальный образ MySQL и PHP с Docker Hub и сразу поставить Битрикс?
Скачать и запустить - да, но «Проверка системы» и восстановление резервной копии, скорее всего, не пройдут без правок. Официальный образ MySQL 8 по умолчанию включает строгий sql_mode (STRICT_TRANS_TABLES и другие режимы), а ядро Битрикс рассчитано на пустое значение. Образ PHP-FPM по умолчанию не содержит часть обязательных расширений вроде AMQP и LDAP. Кодировку при этом донастраивать не придётся: с версии MySQL 8.0.1 utf8mb4 с сортировкой utf8mb4_0900_ai_ci - значения по умолчанию.
Как накатить существующий проект в Docker - восстановлением бэкапа или чистой установкой?
Для действующего проекта - восстановлением: архив резервной копии и restore.php кладут в примонтированный каталог с исходниками и открывают мастер восстановления в браузере, как на обычном хостинге. Чистую установку через bitrixsetup.php используют для нового проекта с нуля. После восстановления на локальный домен обязательно проверьте путь к сайту в «Настройки → Сайты» - иначе будут редиректы на старый адрес или 404 на части страниц.
Нужен ли отдельный лицензионный ключ для локальной Docker-копии?
Нет, лицензионное соглашение разрешает вторую копию продукта - публичную и для разработки - под одним ключом. При установке или в свойствах копии нужно поставить отметку «Установка предназначена для разработки»: это защищает от ошибки ERROR_WRONG_CODE при рассинхронизации системы обновлений и требует отключить автопроверку обновлений на dev-копии. Использовать такую копию как публичный рабочий сайт нельзя - это нарушение лицензии вплоть до блокировки коммерческого ключа.
Почему сайт в Docker на Mac открывается медленнее, чем на обычном хостинге?
Из-за границы файловой системы между хостом и контейнером: только в /bitrix/ у Битрикс лежат десятки тысяч файлов, и на macOS при обычном bind mount каждое обращение к ним проходит через прослойку виртуализации. Docker Desktop уже переключился на VirtioFS вместо более медленного режима и заметно сократил разрыв, но на Linux-хосте, где такой прослойки нет вообще, тот же проект всё равно будет быстрее.
Связанные темы
- Окружение и деплой - требования платформы и BitrixVM, с которыми сверяют Docker-окружение
- Архитектура платформы - структура
/bitrix/и/local/, которую пробрасывают в контейнер - Инфраструктура сервера - Sphinx и ручная настройка nginx и Apache без готового окружения
- Кеширование - что делать в коде Битрикс с сервисом Redis или Memcached после того, как он поднят
- Тестирование и выкладка - место Docker-окружения в цепочке разработки, тестового стенда и боевого сервера
- Раздел Основы
Первоисточники
- Требования к серверному ПО
- Требования к хостингу
- Курс: BitrixEnv и Docker-окружение
- Курс: маркер «Установка предназначена для разработки»
- Курс: проблемы обновлений и ERROR_WRONG_CODE
- Форум: sql_mode в MySQL должна быть пустая
- Скрипт проверки сервера bitrix_server_test.php
- Официальный репозиторий bitrix-tools/env-docker
- Docker Docs: bind mounts
- Docker Docs: синхронизированные файловые ресурсы (VirtioFS)
- Docker Docs: справочник файла Compose