MAATRIX / Блог / SuiteCRM в Docker Compose: готовый файл

SuiteCRM в Docker Compose: готовый файл

MAATRIX

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. Дальше стоит сразу пройтись по нескольким пунктам, которые в дефолтной сборке настроены на «минимум»:

  1. Admin → System Settings — проверить Default Locale (часовой пояс, формат даты), по умолчанию образ ставит UTC.
  2. Admin → Scheduler — SuiteCRM использует cron-задачи для отправки email-уведомлений, обработки очередей и напоминаний. Нужно добавить в crontab хоста (или отдельный sidecar-контейнер) вызов раз в минуту:
   * * * * * docker exec suitecrm-app php -f /bitnami/suitecrm/cron.php > /dev/null 2>&1

Без этой строки уведомления и запланированные задачи просто не будут выполняться — это частая причина жалоб «письма не уходят», хотя SMTP настроен верно.

  1. Admin → Email Settings — исходящую почту лучше настроить сразу на внешний SMTP (Postfix на отдельном сервере или сторонний сервис), а не через встроенный sendmail контейнера — он для продакшена не годится. Если решите поднять собственный почтовый сервер, у нас есть разбор настройки Postfix на Ubuntu 24.04.
  2. Удалить демо-данные, если ставили не для теста — 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 ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →