SuiteCRM в Docker Compose: готовый файл
SuiteCRM — открытый форк SugarCRM, на котором до сих пор держится немало отделов продаж: лиды, сделки, воронки, отчёты, интеграции по REST API. Ставить его классическим способом — распаковывать архив в /var/www, вручную выкручивать права на PHP и гонять миграции руками — долго и хрупко. Docker Compose решает это одной командой: контейнер с PHP-FPM и Apache, отдельный контейнер MySQL, том для данных — и через 10-15 минут у вас рабочая CRM, которую легко переносить и бэкапить.
Содержание
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Что понадобится
SuiteCRM — тяжеловат для PHP-приложения: он тянет за собой Apache/PHP-FPM, MySQL и приличный объём кеша сборки (SugarCRM исторически не отличается лёгкостью). Минимальные ориентиры для теста:
- 2 vCPU, 4 ГБ RAM — для одного-двух пользователей и знакомства с системой;
- 4 vCPU, 8 ГБ RAM — для рабочей команды из 5-15 человек с активной работой в модулях отчётов;
- от 100 ГБ SSD — под систему, MySQL и вложения (SuiteCRM любит хранить файлы прямо в томе
upload).
Если планируете CRM на полсотни и больше сотрудников с историей звонков, вложениями и интеграциями — почитайте отдельно про выделенный сервер для CRM на сотни пользователей, там разбор конфигураций и цены подробнее. Для Compose-варианта из этой статьи хватит обычного VPS.
На сервере нужен Docker и Docker Compose plugin. Если их ещё нет — краткая инструкция для Ubuntu 24.04 есть в статье «Ubuntu 24.04: установка Docker с нуля», для Debian 12 аналогично в «Debian 12: установка Docker с нуля». Проверить, что всё стоит:
docker --version
docker compose version
Структура проекта и docker-compose.yml
Создаём рабочую директорию и файл окружения:
mkdir -p ~/suitecrm && cd ~/suitecrm
Файл .env — здесь держим пароли и версию образа, чтобы не светить их в docker-compose.yml:
cat > .env <<'EOF'
SUITECRM_VERSION=7
MYSQL_ROOT_PASSWORD=change_me_root
MYSQL_DATABASE=suitecrm
MYSQL_USER=suitecrm
MYSQL_PASSWORD=change_me_db
SUITECRM_ADMIN_USER=admin
SUITECRM_ADMIN_PASSWORD=change_me_admin
SUITECRM_SITE_URL=http://your-domain.example
EOF
Пароли обязательно замените на свои — сгенерировать можно через openssl rand -base64 24.
Теперь сам docker-compose.yml. Используем официальный образ bitnami/suitecrm, который избавляет от ручной сборки контейнера с Apache и PHP — внутри уже настроенный веб-сервер, PHP 8.x с нужными расширениями и entrypoint, который сам прогоняет установку при первом старте:
version: "3.8"
services:
mysql:
image: mariadb:10.11
container_name: suitecrm-mysql
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: ${MYSQL_DATABASE}
MYSQL_USER: ${MYSQL_USER}
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
volumes:
- mysql_data:/var/lib/mysql
healthcheck:
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
interval: 15s
timeout: 5s
retries: 10
networks:
- suitecrm-net
suitecrm:
image: bitnami/suitecrm:${SUITECRM_VERSION}
container_name: suitecrm-app
restart: unless-stopped
depends_on:
mysql:
condition: service_healthy
environment:
SUITECRM_DATABASE_HOST: mysql
SUITECRM_DATABASE_PORT_NUMBER: 3306
SUITECRM_DATABASE_NAME: ${MYSQL_DATABASE}
SUITECRM_DATABASE_USER: ${MYSQL_USER}
SUITECRM_DATABASE_PASSWORD: ${MYSQL_PASSWORD}
SUITECRM_USERNAME: ${SUITECRM_ADMIN_USER}
SUITECRM_PASSWORD: ${SUITECRM_ADMIN_PASSWORD}
SUITECRM_EMAIL: admin@example.com
SUITECRM_HOST: ${SUITECRM_SITE_URL}
volumes:
- suitecrm_data:/bitnami/suitecrm
ports:
- "127.0.0.1:8080:8080"
networks:
- suitecrm-net
volumes:
mysql_data:
suitecrm_data:
networks:
suitecrm-net:
driver: bridge
Обратите внимание на ports: 127.0.0.1:8080:8080 — порт не торчит наружу напрямую, доступ к нему будет только через nginx-reverse-proxy на сервере. Это осознанное решение: PHP-приложение с бизнес-данными не должно быть доступно из интернета мимо TLS-терминации и защитного слоя реверс-прокси.
Поднимаем:
docker compose up -d
docker compose logs -f suitecrm
Первый старт займёт пару минут — entrypoint создаёт схему БД, разворачивает демо-данные (если не отключены) и генерирует конфиг config.php. Дождитесь строки вида suitecrm 20:xx:xx.xx INFO ==> SuiteCRM setup finished! в логе.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверPublish URL и частая ошибка с редиректами
Ключевой момент, о который спотыкается почти каждый, кто ставит SuiteCRM за прокси: приложение жёстко запоминает site_url при установке и хранит его прямо в БД (таблица config, поле site_url) и в config.php. Если позже сменить домен или поставить nginx с другим внешним адресом — начнутся бесконечные редиректы или битые ссылки на статику.
Поэтому переменную SUITECRM_SITE_URL в .env нужно сразу выставить в тот адрес, по которому CRM будет доступна снаружи (со схемой https://, если сразу планируете TLS), а не в localhost или внутренний IP. Если всё же ошиблись — поправить можно вручную:
docker exec -it suitecrm-app bash
# внутри контейнера:
mysql -h mysql -u suitecrm -p suitecrm -e \
"UPDATE config SET value='https://your-domain.example' WHERE category='site' AND name='site_url';"
и то же самое в config.php (директория /bitnami/suitecrm смонтирована как том, файл можно поправить прямо с хоста через docker exec или docker cp).
nginx как reverse proxy и HTTPS
Контейнер слушает 127.0.0.1:8080, снаружи ставим системный nginx. Общий подход к настройке реверс-прокси на VPS подробно разобран в статье «nginx как reverse proxy на Ubuntu 24.04» — здесь только конфиг под SuiteCRM:
server {
listen 80;
server_name your-domain.example;
client_max_body_size 100M;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 300s;
}
}
client_max_body_size 100M важен для SuiteCRM: он позволяет прикреплять к сделкам и письмам файлы приличного размера, и без этой строки nginx будет резать загрузку вложений ошибкой 413.
Дальше — сертификат Let's Encrypt через certbot, шаги подробно расписаны в «Как установить и настроить Let's Encrypt SSL на VPS». После выпуска сертификата не забудьте синхронизировать site_url в SuiteCRM на https://, как описано выше — иначе получите смешанный контент и разлогинивание при переходах между модулями.
Первичная настройка после установки
Зайдите на https://your-domain.example, залогиньтесь под SUITECRM_ADMIN_USER / SUITECRM_ADMIN_PASSWORD. Дальше стоит сразу пройтись по нескольким пунктам, которые в дефолтной сборке настроены на «минимум»:
- Admin → System Settings — проверить
Default Locale(часовой пояс, формат даты), по умолчанию образ ставит UTC. - Admin → Scheduler — SuiteCRM использует cron-задачи для отправки email-уведомлений, обработки очередей и напоминаний. Нужно добавить в crontab хоста (или отдельный sidecar-контейнер) вызов раз в минуту:
* * * * * docker exec suitecrm-app php -f /bitnami/suitecrm/cron.php > /dev/null 2>&1
Без этой строки уведомления и запланированные задачи просто не будут выполняться — это частая причина жалоб «письма не уходят», хотя SMTP настроен верно.
- Admin → Email Settings — исходящую почту лучше настроить сразу на внешний SMTP (Postfix на отдельном сервере или сторонний сервис), а не через встроенный sendmail контейнера — он для продакшена не годится. Если решите поднять собственный почтовый сервер, у нас есть разбор настройки Postfix на Ubuntu 24.04.
- Удалить демо-данные, если ставили не для теста — Admin → Studio → Demo Data (или пересоздать окружение с
SUITECRM_SKIP_BOOTSTRAP=noи очищеннымDEMO_DATA=noв переменных окружения перед первым запуском).
Бэкап и обновления
SuiteCRM хранит данные в двух местах: MySQL (записи, настройки) и файловая система тома suitecrm_data (вложения, кастомные модули, upload/). Бэкапить нужно оба.
Дамп БД:
docker exec suitecrm-mysql sh -c \
'exec mysqldump -u root -p"$MYSQL_ROOT_PASSWORD" suitecrm' > suitecrm_$(date +%F).sql
Архив файлового тома:
docker run --rm -v suitecrm_suitecrm_data:/data -v $(pwd):/backup alpine \
tar czf /backup/suitecrm_files_$(date +%F).tar.gz -C /data .
(имя тома может отличаться — уточните через docker volume ls, Compose обычно добавляет префикс из имени проекта).
Для регулярных автоматических бэкапов с ротацией и выгрузкой во внешнее хранилище общая методика описана в статье про бэкап MySQL на сервере — принципы там применимы и к MariaDB-контейнеру SuiteCRM, разница только в том, что команды выполняются через docker exec, а не напрямую.
Обновление версии — меняем тег образа в .env (SUITECRM_VERSION), затем:
docker compose pull suitecrm
docker compose up -d suitecrm
Перед обновлением на новую мажорную версию обязательно снимите оба бэкапа выше — у SuiteCRM были случаи, когда миграция схемы между значимыми релизами требовала ручного вмешательства при нестандартных кастомизациях.
Производительность и что делать, если тормозит
SuiteCRM написан на «классическом» PHP-стеке SugarCRM и по отзывчивости заметно уступает современным CRM на Node/Go. На слабом VPS (1-2 vCPU) типичная жалоба — модуль отчётов (Reports) или список из нескольких тысяч записей открывается заметно дольше, чем хотелось бы; насколько именно — сильно зависит от объёма данных и конкретного железа, ориентируйтесь на собственные замеры, а не на чужие цифры. Что реально помогает:
- PHP OPcache — в образе bitnami обычно включён по умолчанию, но стоит проверить
php -i | grep opcache.enableвнутри контейнера; - Отдельный volume под MySQL на SSD — если сервер на HDD-хранилище, MySQL станет узким местом раньше PHP;
- Индексы в кастомных полях — если добавляете свои поля через Studio и потом фильтруете по ним списки, добавьте индекс через Admin → Studio → поле → Advanced, иначе выборки на больших таблицах будут идти полным сканом;
- Вертикальное масштабирование vCPU/RAM — для SuiteCRM это чаще эффективнее, чем горизонтальное: приложение не рассчитано на несколько инстансов из коробки без вынесения сессий в Redis/Memcached.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Можно ли использовать PostgreSQL вместо MySQL?
Официально SuiteCRM поддерживает только MySQL/MariaDB (и историческую поддержку MSSQL для энтерпрайз-версии). PostgreSQL не поддерживается, менять СУБД в этом docker-compose.yml не стоит.
Как перенести существующую установку SuiteCRM в Docker?
Экспортируйте дамп MySQL с исходного сервера, скопируйте содержимое upload/ и custom/ в новый том, поднимите контейнеры с пустой БД, остановите их, залейте дамп напрямую в volume MySQL через docker exec mysql mysql -u root -p suitecrm < dump.sql, замените site_url на новый адрес и перезапустите.
Нужен ли отдельный контейнер для cron, или хватит crontab хоста?
Оба варианта рабочие. Если сервер обслуживает только этот проект, проще добавить строку в crontab хоста, как показано выше. Если хотите изолировать всё в docker-compose.yml, можно добавить отдельный сервис на том же образе с командой while true; do php /bitnami/suitecrm/cron.php; sleep 60; done вместо стандартного entrypoint.
Почему после установки не приходят email-уведомления?
В 9 случаях из 10 — не настроен Scheduler (см. пункт выше про cron.php) или не прописан внешний SMTP в Admin → Email Settings; встроенный sendmail контейнера в большинстве облачных сетей блокируется провайдером на уровне 25 порта.
Сколько занимает установка с нуля?
Сама команда docker compose up -d и первичная инициализация занимают 3-7 минут в зависимости от скорости диска и сети сервера; дальше — настройка DNS, выпуск сертификата и первичная конфигурация, это ещё 10-15 минут.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →