«У меня локально работает» — фраза, из-за которой сорваны десятки релизов. Один разработчик собрал проект на PHP 8.1 с одним набором расширений, второй — на 7.4 из старого пакета, на бою крутится BitrixVM с третьей конфигурацией, и в итоге баг, который не воспроизводится ни у кого, кроме клиента. Docker решает ровно эту боль: окружение перестаёт быть свойством конкретной машины и становится кодом, который лежит в репозитории рядом с проектом и одинаково поднимается у всех.
Ниже — практический разбор контейнеризации 1С-Битрикс: из каких сервисов собрать стек, как написать Dockerfile и docker-compose, куда положить тома под /upload, ядро и базу, как не сломать права www-data, чем отличается dev-сборка от прод и как всё это подготовить к CI/CD. Это выжимка из наших проектов по разработке на 1С-Битрикс — без хайпа вокруг контейнеров, только то, что реально помогает командам.
Коротко
- Docker превращает окружение в код: одинаковые PHP, расширения и версии сервисов у всей команды и на всех контурах.
- Минимальный стек — nginx + php-fpm + mysql/percona, плюс memcached/redis под кэш и push-сервер под чат.
- Постоянные данные (
/upload, ядро, БД) выносим в тома; процесс php-fpm и владелец файлов — один пользователь www-data. - Настройки БД и кэша читаем из переменных окружения в
.settings.php— один образ на dev, стейдж и прод. - Начинать проще с dev-окружения, а прод в контейнеры переносить вместе с настройкой CI/CD и деплоя.
Зачем контейнеризировать 1С-Битрикс
1С-Битрikс — платформа требовательная к окружению: конкретные версии PHP, набор расширений (mbstring, gd, mysqli, opcache, zip, xml), параметры opcache и памяти, правильно настроенный nginx с обработкой ЧПУ и композита. Собрать это вручную можно, но воспроизвести один в один на пяти машинах разработчиков и трёх серверах — задача, которая обычно проваливается. Контейнеризация делает окружение декларативным: вы описываете его один раз в Dockerfile и docker-compose, и дальше оно одинаково разворачивается где угодно.
Практическая ценность контейнеров для Битрикс-проекта складывается из нескольких вещей:
- Одинаковое окружение у всех. Новый разработчик клонирует репозиторий, выполняет одну команду
docker compose upи через минуты получает рабочий стек — без ручной установки PHP, MySQL и настройки конфигов. - Версионирование окружения. Обновили PHP с 8.1 до 8.2 — это одна строка в Dockerfile и один коммит. Откат — это откат коммита, а не мучительная переустановка пакетов на сервере.
- Изоляция проектов. Два проекта с разными версиями PHP и MySQL спокойно живут на одной машине в своих контейнерах, не конфликтуя по портам и системным пакетам.
- Паритет dev и прод. Чем ближе окружение разработки к боевому, тем меньше сюрпризов на релизе. Контейнеры дают этот паритет почти бесплатно.
- Дорога к CI/CD. Образ, который собирается в пайплайне, тестируется и выкатывается на сервер, — естественное продолжение контейнеризации. Без неё автоматический деплой строить сложнее.
Важно понимать, что Docker не ускоряет сам Битрикс и не заменяет грамотную настройку кэша и базы. Он решает задачу воспроизводимости и управляемости окружения, а не производительности приложения как такового. Если проект тормозит из-за неоптимальных запросов или отсутствия композита, контейнеры этого не вылечат — они лишь сделают так, чтобы вы чинили одну и ту же проблему в одинаковых условиях у всех.
Docker против BitrixVM: что выбрать
BitrixVM (bitrix-env) — официальное преднастроенное окружение от 1С-Битрикс: виртуальная машина с готовым стеком nginx + Apache/php-fpm + MySQL + memcached + push-сервер и текстовым меню управления. Она закрывает большинство задач «из коробки» и не требует знания системного администрирования. Мы подробно разбирали её в отдельной статье про хостинг и инфраструктуру на BitrixVM. Docker решает ту же задачу окружения, но принципиально иначе — разбивая монолит ВМ на отдельные сервисы-контейнеры, описанные кодом.
Не стоит воспринимать выбор как «или-или навсегда». Многие команды используют BitrixVM на проде и Docker на разработке, а миграцию прода в контейнеры делают эволюционно. Но чтобы выбирать осознанно, полезно видеть отличия по ключевым осям:
| Критерий | BitrixVM | Docker |
|---|---|---|
| Порог входа | Низкий: меню, всё преднастроено | Выше: нужно собрать стек и понять сети/тома |
| Воспроизводимость | Ручная, через бэкап ВМ | Полная, окружение как код в репозитории |
| Версионирование окружения | Нет из коробки | Есть: Dockerfile под git |
| Изоляция проектов на машине | Одна ВМ — один стек | Много проектов рядом в своих контейнерах |
| Официальная поддержка | Да, от 1С-Битрикс | Нет, стек собираете сами |
| Путь к CI/CD | Через доп. обвязку | Естественный: собрал образ — выкатил |
| Обновление стека (PHP, MySQL) | Через меню bitrix-env | Строка в Dockerfile + пересборка |
Резюме простое. Если проект небольшой, команда одна и админить некому — BitrixVM даёт результат быстрее и с меньшими рисками. Если проектов много, в команде несколько разработчиков, нужен паритет окружений и вы движетесь к автоматическому деплою — Docker окупается за счёт повторяемости и управляемости, хотя и требует первоначальных вложений в настройку стека.
Из чего собрать окружение: сервисы стека
Контейнерное окружение для Битрикса — это набор сервисов, каждый в своём контейнере, соединённых внутренней сетью Docker. Минимальный работоспособный набор и типовые роли выглядят так:
- nginx — веб-сервер и обратный прокси. Принимает HTTP/HTTPS, отдаёт статику напрямую, а запросы к PHP проксирует на php-fpm по протоколу FastCGI. Здесь же живут правила ЧПУ, обработка композита и заголовки кэширования.
- php-fpm — интерпретатор PHP с ядром Битрикса. Основной «рабочий» контейнер: сюда монтируется код, тут настроены расширения, opcache и лимиты памяти.
- mysql или percona — база данных. Percona Server — совместимая с MySQL сборка с улучшенным движком и диагностикой; Битрикс работает и с тем, и с другим. Важны версия, кодировка utf8mb4 и настройки innodb.
- memcached или redis — хранилище кэша. Битрикс умеет складывать managed-кэш и данные в memcached или redis, что разгружает диск и базу. Для одной ноды достаточно memcached, redis удобнее при кластеризации и когда нужен персистентный кэш.
- push-сервер (nodejs) — сервер очередей сообщений для модуля «Пуш и очередь»: онлайн-чаты, уведомления, обновления в реальном времени. В BitrixVM он идёт из коробки, в Docker его поднимают отдельным контейнером на Node.js.
К этому набору по мере надобности добавляют вспомогательные контейнеры: cron/агенты (об этом ниже отдельный раздел), mailhog или аналог для перехвата почты на dev, adminer/phpMyAdmin для работы с базой, sphinx/manticore если используется полнотекстовый поиск. Принцип один: один процесс — один контейнер, связь между ними по именам сервисов внутри сети compose.
| Сервис | Роль в стеке | За что отвечает |
|---|---|---|
| nginx | Веб-сервер / прокси | HTTP(S), статика, ЧПУ, композит, проксирование PHP |
| php-fpm | Приложение | Ядро Битрикса, расширения, opcache |
| mysql / percona | Хранилище данных | Инфоблоки, заказы, пользователи, настройки |
| memcached / redis | Кэш | Managed-кэш, сессии, ускорение чтения |
| push (node) | Реалтайм | Чаты, уведомления, очередь сообщений |
| cron / agents | Фоновые задачи | Агенты Битрикса, обмены, регламентные задания |
Dockerfile для php-fpm под Битрикс
Сердце сборки — образ php-fpm с нужными расширениями и настройками под Битрикс. За основу берут официальный образ php:8.x-fpm и доустанавливают то, что требует платформа. Битриксу нужны как минимум mysqli/pdo_mysql, mbstring, gd, zip, xml, opcache, а также корректная локаль и часовой пояс.
FROM php:8.2-fpm
# Системные пакеты для сборки расширений
RUN apt-get update && apt-get install -y --no-install-recommends \
libfreetype6-dev libjpeg62-turbo-dev libpng-dev \
libzip-dev libicu-dev libxml2-dev \
&& rm -rf /var/lib/apt/lists/*
# Расширения PHP, которые требует ядро Битрикс
RUN docker-php-ext-configure gd --with-freetype --with-jpeg \
&& docker-php-ext-install -j"$(nproc)" \
mysqli pdo_mysql mbstring gd zip intl opcache soap
# memcached-клиент под кэш
RUN pecl install memcached && docker-php-ext-enable memcached
# Свои php.ini-настройки под Битрикс
COPY php/bitrix.ini /usr/local/etc/php/conf.d/zzz-bitrix.ini
WORKDIR /var/www/html
Отдельным файлом подключают php.ini с параметрами, которые Битрикс проверяет в мониторе производительности: увеличенные лимиты памяти и загрузки, включённый opcache с достаточным размером, отключённый вывод ошибок в прод. Короткий фрагмент такого конфига:
; php/bitrix.ini
memory_limit = 512M
upload_max_filesize = 1024M
post_max_size = 1024M
max_input_vars = 10000
mbstring.func_overload = 0
opcache.enable = 1
opcache.memory_consumption = 256
opcache.max_accelerated_files = 100000
opcache.revalidate_freq = 0
date.timezone = Europe/Moscow
Обратите внимание на opcache.revalidate_freq: на dev его держат в 0 или 2, чтобы изменения кода подхватывались сразу, а на проде увеличивают и часто выключают opcache.validate_timestamps, чтобы opcache не проверял файлы на каждом запросе. Это одно из ключевых различий dev- и прод-сборки, к которому мы ещё вернёмся.
docker-compose: связываем сервисы
Dockerfile описывает один образ, а docker-compose — как сервисы соединяются в единое окружение: какие порты открыты, какие тома примонтированы, кто от кого зависит и какие переменные окружения получает. Ниже сокращённый пример compose-файла для Битрикса с базовым стеком.
services:
nginx:
image: nginx:1.25
ports:
- "80:80"
volumes:
- ./:/var/www/html:cached
- ./docker/nginx/site.conf:/etc/nginx/conf.d/default.conf:ro
depends_on:
- php
php:
build: ./docker/php
volumes:
- ./:/var/www/html:cached
environment:
DB_HOST: mysql
DB_NAME: sitemanager
DB_LOGIN: bitrix
DB_PASSWORD: ${DB_PASSWORD}
CACHE_HOST: memcached
depends_on:
- mysql
- memcached
mysql:
image: percona:8.0
command: --sql-mode="" --innodb-flush-log-at-trx-commit=2
environment:
MYSQL_DATABASE: sitemanager
MYSQL_USER: bitrix
MYSQL_PASSWORD: ${DB_PASSWORD}
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
volumes:
- db-data:/var/lib/mysql
memcached:
image: memcached:1.6
volumes:
db-data:
Несколько важных моментов в этом файле. Во-первых, nginx и php монтируют одну и ту же кодовую базу — nginx отдаёт статику и знает пути, php исполняет скрипты. Во-вторых, php обращается к базе по имени сервиса mysql, а к кэшу по имени memcached — Docker резолвит эти имена во внутренние адреса сети. В-третьих, пароль базы не зашит в файл, а приходит из переменной ${DB_PASSWORD}, которую compose берёт из .env рядом с проектом. Наконец, данные MySQL лежат в именованном томе db-data, поэтому переживают пересоздание контейнера.
Для команды такой файл — единая точка правды об окружении. Обновили версию Percona — поправили тег образа, зафиксировали в git, все подтянули изменение при следующем docker compose up. Добавили redis или push-сервер — дописали ещё один сервис. Никаких «а установи себе локально вот это» в переписке.
Тома: /upload, ядро и база
Контейнеры по своей природе эфемерны: удалили и пересоздали — и всё, что было внутри, исчезло. Для Битрикса это неприемлемо: пользовательские файлы, ядро и база должны переживать любые пересоздания. Поэтому правильная работа с томами — не деталь, а фундамент. Данные Битрикса делятся на три класса, и с каждым обращаются по-своему.
- Пользовательские файлы —
/upload. Загруженные картинки, документы, сгенерированные ресайзы. Их обязательно выносят в постоянный том (bind-mount на dev или именованный/сетевой том на проде). Потерять/upload— значит потерять весь контент, привязанный к инфоблокам. - Ядро и код —
/bitrixи проект. На dev код монтируют с хоста, чтобы редактировать в IDE и сразу видеть изменения. На проде код чаще запекают в образ (immutable-подход) и раздают тем же образом на все ноды, а изменяемые части (/upload,/bitrix/cache) держат в томах. - База данных —
/var/lib/mysql. Всегда в именованном или внешнем томе. Держать данные MySQL внутри контейнера без тома — прямой путь потерять базу при первом же пересоздании.
Отдельная тонкость — каталоги кэша /bitrix/cache и /bitrix/managed_cache. Их можно и не выносить в постоянное хранилище (кэш регенерируется), но на macOS их часто монтируют в отдельные тома или держат внутри контейнера, чтобы не гонять тысячи мелких файлов через медленную проброшенную ФС. О производительности томов на macOS — в разделе про проблемы.
| Данные | Тип тома | Что будет при потере |
|---|---|---|
| /upload | Постоянный (том/сетевой) | Потеря всех загруженных файлов |
| Данные MySQL | Именованный том | Потеря базы целиком |
| Код / ядро | bind-mount (dev) / в образе (прод) | Восстанавливается из git/образа |
| /bitrix/cache | Том или внутри контейнера | Регенерируется, просадка на прогрев |
| Логи | Том или stdout | Потеря истории, если не собраны |
Права и владелец файлов (www-data)
Проблема прав — самая частая боль новичков в контейнеризации Битрикса, и почти всегда она про одно: процесс php-fpm и владелец файлов должны совпадать. В официальных образах php-fpm работает от пользователя www-data с UID и GID 33. Значит, каталоги, в которые Битрикс пишет, — корень проекта, /upload, /bitrix/cache, /bitrix/managed_cache, /bitrix/tmp — должны принадлежать www-data и быть доступны на запись.
Если этого не сделать, симптомы узнаваемы: не создаётся кэш, не загружаются файлы, установщик модулей ругается на права, монитор производительности показывает ошибки записи. На проде, где код запечён в образ, права выставляют на этапе сборки. На dev, где код монтируется с хоста, начинается самое интересное: у локального пользователя UID обычно 1000, а не 33, и файлы, созданные в контейнере под www-data, оказываются недоступны на редактирование на хосте, и наоборот.
Классическое решение — параметризовать UID/GID контейнерного пользователя под хостовые через build-аргументы:
# Dockerfile (фрагмент)
ARG UID=1000
ARG GID=1000
RUN groupmod -g ${GID} www-data \
&& usermod -u ${UID} www-data
# docker-compose.yml (фрагмент)
php:
build:
context: ./docker/php
args:
UID: ${UID:-1000}
GID: ${GID:-1000}
Так контейнерный www-data получает тот же UID, что и разработчик на хосте, и файлы становятся общими для редактирования без конфликтов. На Linux это критично, на macOS и Windows проброс ФС работает через виртуализацию и обычно сглаживает разницу UID, но параметризация всё равно считается хорошим тоном.
chmod -R 777 на боевом проекте. Это открывает файлы на запись всем и является дырой в безопасности. Правильный путь — привести владельца к www-data (chown -R www-data:www-data) и выставить осмысленные права 755/644, а изменяемым каталогам — доступ на запись для владельца.
Переменные окружения и .settings.php
Чтобы один и тот же образ работал на dev, стейджинге и проде, настройки не должны быть зашиты в код. Битрикс хранит параметры подключения к базе и кэшу в файлах bitrix/.settings.php и bitrix/php_interface/dbconn.php. В контейнерном подходе эти значения читают из переменных окружения через getenv(), а сами переменные прокидывают через environment или env-файл в docker-compose.
<?php
// bitrix/.settings.php (фрагмент секции connections)
return [
'connections' => [
'value' => [
'default' => [
'className' => '\\Bitrix\\Main\\DB\\MysqliConnection',
'host' => getenv('DB_HOST') ?: 'mysql',
'database' => getenv('DB_NAME') ?: 'sitemanager',
'login' => getenv('DB_LOGIN') ?: 'bitrix',
'password' => getenv('DB_PASSWORD') ?: '',
'options' => 2,
],
],
'readonly' => true,
],
// ...
];
Такой подход даёт сразу несколько выгод. Секреты не попадают в git и в образ — пароль базы живёт только в окружении контейнера или в системе секретов оркестратора. Хост базы указывается именем сервиса (mysql), поэтому один и тот же файл работает в любой среде, где сервис так называется. А переключение между контурами сводится к смене env-файла, а не к правке кода.
Аналогично настраивают кэш: в .settings.php в секции cache указывают тип (memcached/redis) и адрес хранилища из переменной окружения. Так на dev можно использовать простой файловый кэш или memcached, а на проде — redis-кластер, не меняя ни строчки в кодовой базе.
.env.example с полным списком переменных без реальных значений, а настоящий .env добавьте в .gitignore. Новый разработчик копирует пример, подставляет свои значения — и окружение поднимается, а секреты не утекают в историю коммитов.
Dev-окружение под команду
Главный приз контейнеризации на старте — единое dev-окружение, которое поднимается у всех одинаково и одной командой. Чтобы это работало на практике, а не только в теории, стоит соблюсти несколько принципов организации.
- Всё окружение — в репозитории. Dockerfile, docker-compose, конфиги nginx и php, скрипты инициализации лежат в каталоге
docker/внутри проекта под git. Никаких «локальных» файлов, которых нет у коллег. - Одна команда на запуск. Заверните инициализацию в Makefile или простой скрипт:
make upсобирает образы, поднимает сервисы, накатывает дамп базы для разработки. Разработчик не должен помнить последовательность из десяти команд. - Дамп базы для разработки. Договоритесь, откуда берётся стартовая база: обезличенный дамп с прода или сид-набор данных. Автоматизируйте его загрузку при первом старте.
- Единые версии. Зафиксируйте версии PHP, MySQL/Percona и расширений тегами образов. Обновление версии — через коммит, а не через «у меня уже новее».
- Локальный домен и почта. Настройте удобный локальный домен и перехват исходящей почты (mailhog), чтобы тестовые письма не уходили реальным клиентам и были видны в веб-интерфейсе.
- Документация в README. Короткая инструкция «клонируй — скопируй .env — make up» экономит часы онбординга каждому новому человеку в команде.
Когда это выстроено, онбординг нового разработчика сокращается с «день на настройку окружения» до «полчаса до первого коммита». А главное — исчезает целый класс багов «работает только у меня», потому что «у меня» и «у всех» теперь физически одно и то же окружение.
Проблемные места контейнеризации
Битрикс — большая и старая платформа, спроектированная под классический сервер, поэтому в контейнерах у неё есть характерные болевые точки. Их лучше знать заранее, чтобы не наступать вслепую.
Производительность томов на macOS. Самая известная проблема. Файловая система хоста пробрасывается в контейнер через виртуализацию, и каждое обращение к файлу проходит через прослойку. Битрикс на старте читает десятки тысяч мелких файлов ядра, поэтому bind-mount всего проекта на macOS даёт заметные тормоза — страница, которая на Linux открывается за 200 мс, на маке может грузиться секунды. Лечится это выносом ядра, vendor и каталогов кэша в именованные тома, включением делегированного режима (:cached/:delegated) и использованием VirtioFS в свежих Docker Desktop. На Linux монтирование нативное, проблемы нет.
Cron и агенты. Битрикс по умолчанию запускает агенты на хитах пользователей, но правильная эксплуатация требует cron. В одном контейнере php-fpm cron не запущен — нужен либо отдельный контейнер с планировщиком, либо supervisor. Об этом отдельный раздел ниже.
Композит и pull-соединения. Модуль «Композитный сайт» и push/pull-технология требуют аккуратной настройки на уровне nginx: правильного проксирования, заголовков и, для pull, отдельного push-сервера. В контейнерах это не сложнее, чем на BitrixVM, но конфиг nginx нужно перенести осознанно, а не скопировать частично. Про сам композит и его влияние на скорость мы писали в статье про композитный сайт на Битрикс.
Память под ORM и большие операции. D7-ORM, обмены с 1С, экспорт больших выборок и построение фасетов легко упираются в лимит памяти контейнера. По умолчанию контейнер может быть ограничен по RAM жёстче, чем хост, и процесс убивается OOM-киллером без внятной ошибки в логах приложения. Лимиты памяти php (memory_limit) и лимиты контейнера нужно согласовать и заложить запас под пиковые операции обмена и индексации.
| Проблема | Симптом | Решение |
|---|---|---|
| Тома на macOS | Медленная загрузка страниц | Тома под ядро/кэш, VirtioFS, :cached |
| Агенты не идут | Обмены и задачи не выполняются | Cron в отдельном контейнере/supervisor |
| Композит/pull | Не работает realtime, чат | Push-сервер + корректный nginx-конфиг |
| OOM при обмене | Процесс убит без явной ошибки | Согласовать memory_limit и лимит контейнера |
| Разные UID | Файлы не редактируются на хосте | Параметризация UID/GID через build-args |
Cron и агенты в контейнере
Агенты Битрикса — это отложенные и регламентные задачи: обмены, отправка отложенных писем, пересчёт, чистка. На классическом сервере их выносят на cron, вызывающий /bitrix/php_interface/cron/agents.php через php-cli, чтобы задачи не зависели от того, зашёл ли на сайт живой пользователь. В контейнерах ту же логику воспроизводят одним из двух способов.
- Отдельный контейнер cron. Поднимают ещё один контейнер из того же php-образа, но с запущенным cron (или supervisor, дёргающим агенты по расписанию). Он монтирует ту же кодовую базу и те же тома, что и php-fpm, и работает в фоне независимо от веб-трафика. Это чистый подход: веб-процесс и фоновые задачи разделены.
- Внешний планировщик. Cron на хосте или в оркестраторе периодически выполняет
docker compose exec php php -f /var/www/html/bitrix/php_interface/cron/agents.php. Проще в настройке, но привязывает запуск задач к внешней системе.
Ключевой момент — перевести агенты в режим запуска на cron в настройках главного модуля (константа BX_CRONTAB) и в самих настройках, чтобы они перестали выполняться на хитах. Иначе задачи будут идти двумя путями сразу или конкурировать. Тонкости работы агентов, cron и фоновых заданий мы разбираем в отдельном материале рубрики Разработка и архитектура.
/upload, агенты будут падать или работать не с теми данными.
Подготовка к CI/CD и деплою
Контейнеризация раскрывается полностью, когда становится основой автоматического деплоя. Идея в том, что образ, собранный и протестированный в пайплайне, — это и есть артефакт, который едет на сервер. Ничего не собирается «на бою», исключается класс проблем «на сервере другая версия». Путь к этому строится поэтапно.
- Сборка образа в пайплайне. На каждый коммит/тег CI собирает образ приложения (php-fpm с запечённым кодом и vendor из composer), прогоняет линтеры и тесты и публикует образ в реестр с тегом версии.
- Неизменяемый артефакт. Один и тот же образ проходит через стейджинг и прод. Это гарантирует, что тестировали ровно то, что поедет в продакшен.
- Миграции и обновления. Обновления модулей и структуры базы Битрикса выносят в отдельный контролируемый шаг деплоя, а не оставляют на «мастер обновлений» вручную. Миграции прогоняют до переключения трафика.
- Прогрев кэша. После выката новый контейнер прогревают (первые запросы, регенерация managed-кэша), чтобы пользователи не попали на «холодный» сайт с просадкой скорости.
- Переключение и откат. Трафик переключают на новый контейнер, старый держат наготове для мгновенного отката. Тома с
/uploadи базой при этом общие и не пересоздаются.
Отдельная дисциплина — что попадает в образ, а что остаётся в томах. В образ запекают неизменяемое: код, ядро, vendor, ассеты. В томах живёт изменяемое: /upload, база, кэш, логи. Такое разделение делает деплой предсказуемым: выкатка новой версии не трогает пользовательские данные, а откат не теряет заказы. Полный разбор конвейера — в нашей статье про CI/CD и деплой Битрикс.
Прод против дева: чем отличаются сборки
Одна из главных ошибок — думать, что dev-окружение и прод должны быть идентичны на 100%. Паритет важен по стеку (версии PHP, MySQL, расширения), но по настройкам dev и прод сознательно расходятся. Понимание этих различий экономит много нервов.
| Параметр | Dev | Прод |
|---|---|---|
| Код | bind-mount с хоста | Запечён в образ (immutable) |
| opcache.validate_timestamps | Включён (видеть правки) | Выключен (максимум скорости) |
| Вывод ошибок | На экран, debug на | В лог, display_errors off |
| Кэш | Файловый / memcached | Redis, композит включён |
| Композит | Часто выключен | Включён |
| Данные | Обезличенный дамп | Боевая база в томе |
| Мониторинг/лимиты | Мягкие | Жёсткие лимиты, метрики, алерты |
Из таблицы видно главное правило: dev оптимизируют под скорость разработки, прод — под скорость и надёжность работы. На dev важно сразу видеть изменения кода и подробные ошибки, поэтому opcache не кэширует агрессивно, а debug включён. На проде наоборот — код неизменяем, opcache выкручен на максимум, ошибки уходят в лог, а не на экран пользователю, включён композит и настроены лимиты с мониторингом. Реализуют это одним образом с разными переменными окружения и, при необходимости, разными compose-файлами (docker-compose.override.yml для dev).
Частые ошибки
- Держат данные MySQL внутри контейнера без тома — при первом же пересоздании база теряется целиком.
- Забывают вынести
/uploadв постоянное хранилище — вместе с контейнером исчезают все загруженные файлы. - Лечат права через
chmod -R 777вместо приведения владельца к www-data — получают дыру в безопасности и не решают корень проблемы. - Расходятся UID процесса php-fpm и владельца файлов — Битрикс не может писать кэш, а на dev файлы не редактируются на хосте.
- Зашивают пароль базы и секреты в Dockerfile или в git — секреты утекают в историю и в образ.
- Оставляют агенты на хитах вместо cron — обмены и регламентные задачи выполняются нестабильно или дублируются.
- На macOS монтируют весь проект bind-mount без оптимизации — сайт открывается по несколько секунд из-за медленной проброшенной ФС.
- Не согласуют
memory_limitphp с лимитом памяти контейнера — тяжёлые обмены и ORM-выборки убиваются OOM без понятной ошибки.
/upload в образ? Нет — /upload это изменяемые пользовательские данные, им место в постоянном томе. В образ запекают только неизменяемое: код, ядро, vendor и ассеты.
Чек-лист внедрения
Сведём всё в практический список, по которому удобно проверять готовность контейнерного окружения перед раздачей команде и выходом на прод:
- Стек описан кодом. Dockerfile и docker-compose с сервисами nginx + php-fpm + mysql/percona + memcached/redis (+ push при необходимости) лежат в репозитории.
- Расширения PHP на месте. Образ php проходит проверки монитора производительности Битрикса: mysqli, mbstring, gd, zip, intl, opcache и корректные лимиты.
- Тома настроены. База MySQL и
/uploadвынесены в постоянные тома, кэш обработан с учётом macOS. - Права согласованы. Владелец файлов — www-data, UID/GID параметризованы под хост, никаких 777.
- Настройки в env. Подключение к базе и кэшу читается из переменных окружения в
.settings.php, секреты не в git, есть.env.example. - Cron поднят. Агенты переведены на cron в отдельном контейнере или через внешний планировщик, режим BX_CRONTAB включён.
- Dev запускается одной командой.
make upили скрипт поднимает стек и накатывает дамп; онбординг описан в README. - Прод-сборка отделена. Код запекается в образ, opcache и композит настроены под прод, различия dev/прод вынесены в переменные и override-файлы.
- Путь к CI/CD размечен. Понятно, где собирается образ, как проходят миграции, прогрев кэша и переключение трафика с возможностью отката.
Вывод
Docker не делает Битрикс быстрее сам по себе — он делает окружение воспроизводимым, версионируемым и одинаковым у всех, а это лечит целый класс проблем «работает только у меня» и открывает дорогу к автоматическому деплою. Начните с малого: соберите контейнерное dev-окружение из nginx, php-fpm и базы, добейтесь запуска одной командой, аккуратно решите вопросы томов, прав www-data и переменных окружения. Когда команда привыкнет и стек обкатается, тем же образом переносите на прод вместе с настройкой CI/CD. Так контейнеризация из модного слова становится рабочим инструментом, который экономит часы на каждом релизе и новом человеке в команде.