Dans cet article, je vous propose d’installer SuiteCRM dans un Docker en quelques étapes simples. Vous pouvez ainsi mettre en place un CRM puissant et complètement opérationnel en moins d’une heure.
Les bénéfices d’un Docker sont multiples :
- l’environnement est contrôlé, avec la bonne version de PHP et les dépendances requises ;
- possibilité d’installer en quelques minutes sur n’importe quel serveur ;
- il suffit de compléter avec un Docker MariaDB pour fournir une base de données (voir fichier
compose.yaml
ci-dessous) et vous obtenez un système fonctionnel ; - il est facile d’installer d’autres Dockers sur le même réseau local, avec des applications qui peuvent interagir avec SuiteCRM : n8n, mautic, applications dédiées,… Vous pouvez ainsi construire un « stack marketing » entièrement personnalisé, complètement sécurisé et pour un coût très maîtrisé ;
- si besoin, le Docker peut être déplacé sur un autre serveur en quelques minutes.
Il est quand même souhaitable que vous ayez un peu d’expérience avec la mise en place d’un Docker, le montage des volumes, et la création des fichiers de configuration.
Dans mon cas, les Dockers qui servent des applications web sont placés derrière un reverse proxy Traefik Proxy. Si vous préférez une autre solution, il faut modifier le fichier compose.yaml
en conséquence.
De manière générale, il y a plusieurs paramètres qui pourraient être légèrement différents en fonction de votre installation, mais en tout cas, cette configuration est plutôt robuste. Elle fonctionne en production pour moi depuis plusieurs années.
Version de SuiteCRM et mise en place
Le docker que je vous propose permet d’installer SuiteCRM 7.x ou 8.x. À la date de rédaction (début 2024), je teste encore la migration de mes installations de production de la version 7.14.2 vers la version 8.5.
Le docker fournit l’environnement, il ne vous reste qu’à télécharger la version qui vous convient et installer les fichiers dans le volume qui est monté par le fichier docker compose.
SuiteCRM API v8
Une des forces majeures de SuiteCRM est son API, qui permet à d’autres applications d’interagir avec SuiteCRM, par exemple:
- création ou synchronisation de contacts ou d’autres enregistrements depuis Woo, WordPress ou d’autres applications web ;
- ajout automatique de notes ou de documents aux contacts ;
- extraction de données pour traitement par d’autres applications ;
- …
Le fichier entrypoint.sh
vérifie à chaque démarrage du docker que les clés numériques pour l’utilisation de l’API sont bien présentes. Si elles n’existent pas, elles sont créées automatiquement. Le docker que je vous propose est donc prêt pour l’interactivité !
Les fichiers à créer
Voici les fichiers dans la structure qui va servir à la construction du docker (vous pouvez adapter le Dockerfile en fonction des endroits où vous placez les différents fichiers) :
. ├── Dockerfile └── conf ├── apache │ ├── apache.conf │ └── vhost.conf ├── cron-suitecrm ├── entrypoint.sh └── php ├── php.conf └── php.ini
Le fichier Dockerfile
Le fichier Dockerfile
lui-même est basé sur une version donnée de PHP, ce qui permet d’être aligné avec la matrice de compatibilité de SuiteCRM version 7.x et version 8.x. Il contient un serveur Apache qui servira l’application pour le web.
FROM php:8.2-apache LABEL vendor="The Moto Company / SL Data Tech" LABEL maintainer="Steph Legrand" # define timezone ENV TZ=Europe/Paris RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone EXPOSE 80 RUN apt-get update && apt-get install -y \ cron \ openssl \ unzip \ zip # Install additional dependencies RUN apt-get update && apt-get install -y \ libicu-dev \ libcurl4-openssl-dev \ libmagickwand-dev \ libpng-dev \ libzip-dev \ libxml2-dev \ libbz2-dev \ libonig-dev \ libgmp-dev \ libldb-dev \ libldap2-dev \ libc-client-dev \ libkrb5-dev \ && rm -rf /var/lib/apt/lists/* # Install PHP extensions RUN docker-php-ext-configure imap --with-kerberos --with-imap-ssl \ && docker-php-ext-install \ pdo_mysql \ gd \ curl \ zip \ xml \ mbstring \ bz2 \ intl \ gmp \ opcache \ soap \ imap \ ldap \ mysqli # apache config COPY conf/apache/apache.conf /etc/apache2/conf-available/suitecrm.conf COPY conf/apache/vhost.conf /etc/apache2/sites-available/suitecrm.conf RUN a2enmod rewrite remoteip RUN a2dissite 000-default \ && a2ensite suitecrm \ && a2enconf suitecrm RUN ln -sf /proc/self/fd/1 /var/log/apache2/access.log && \ ln -sf /proc/self/fd/1 /var/log/apache2/error.log # php config COPY conf/php/php.ini /usr/local/etc/php/conf.d/suitecrm.ini # cron config COPY conf/cron-suitecrm /etc/cron.d/suitecrm # entrypoint config COPY conf/entrypoint.sh /entrypoint.sh RUN chmod +x /entrypoint.sh WORKDIR /app/suitecrm ENTRYPOINT [ "/entrypoint.sh" ] CMD ["apache2-foreground"]
Le fichier entrypoint.sh
Voici ensuite le fichier entrypoint.sh
. Il est exécuté à chaque démarrage du docker. Dans ce cas précis, son rôle est de :
- vérifier la version de SuiteCRM et appliquer les bonnes permissions aux répertoires et fichiers ;
- changer le répertoire de base pour Apache en fonction de la version ;
- générer si besoin les clés SSL pour Oauth2 (pour permettre le fonctionnement de l’API v8) et vérifier les permissions ;
- enfin, lancer le serveur Apache.
Certains trouveront qu’il est excessif d’exécuter ceci à chaque démarrage, vous pouvez modifier ce fichier comme vous le souhaitez. Pour moi, ça permet d’être certain que les changements apportés manuellement aux modules personnalisés (notamment quelques scripts PHP) ont bien les bonnes permissions.
#!/bin/bash if [ "$1" = 'apache2-foreground' ]; then # this is run only for main docker execution echo "[ tmc ] This is a SuiteCRM docker by The Moto Company / SL Daata Tech" > /dev/stdout if [ -f "/app/suitecrm/public/index.php" ]; then # Scenario 1: SuiteCRM 8 - /app/suitecrm/public/index.php exists echo "[ tmc ] running SuiteCRM 8 configuration" > /dev/stdout api_root_path="/app/suitecrm/public/legacy/Api" echo "[ tmc ] api root path set to " $api_root_path > /dev/stdout # web server root is /app/suitecrm/public # nothing more to do in apache conf files echo "[ tmc ] web server root set " > /dev/stdout # set permissions for SuiteCRM 8 directory structure echo "[ tmc ] setting permissions for SuiteCRM 8 directories..." > /dev/stdout cd /app/suitecrm find . -type d -not -perm 2755 -exec chmod 2755 {} \; find . -type f -not -perm 0644 -exec chmod 0644 {} \; find . ! -user www-data -exec chown www-data:www-data {} \; chmod +x bin/console echo "[ tmc ] done." > /dev/stdout else # Scenario 2: SuiteCRM 7 - /app/suitecrm/public/index.php does not exist echo "[ tmc ] running SuiteCRM 7 configuration" > /dev/stdout api_root_path="/app/suitecrm/Api" echo "[ tmc ] api root path set to " $api_root_path > /dev/stdout # update apache conf files: # Set web server root to /app/suitecrm echo "[ tmc ] updating web server root..." > /dev/stdout sed -ri 's#DocumentRoot .*#DocumentRoot /app/suitecrm#' /etc/apache2/sites-available/suitecrm.conf sed -ri 's#<Directory /app/suitecrm/public>#<Directory /app/suitecrm>#' /etc/apache2/conf-available/suitecrm.conf echo "[ tmc ] done." > /dev/stdout # set permissions for SuiteCRM 7 directory structure echo "[ tmc ] setting permissions for SuiteCRM 7 directories..." > /dev/stdout cd /app/suitecrm chown -R www-data:www-data . chmod -R 755 . chmod -R 775 cache custom modules themes data upload chmod 775 config_override.php 2>/dev/null echo "[ tmc ] done." > /dev/stdout fi # start cron echo "[ tmc ] starting cron " > /dev/stdout service cron start # Generate SSL keys for OAuth2 if private key does not exist if [ ! -f "$api_root_path/V8/OAuth2/private.key" ]; then echo "[ tmc ] no SSL keys found - generating SSL keys in " $api_root_path > /dev/stdout openssl genrsa -out "$api_root_path/V8/OAuth2/private.key" 2048 openssl rsa -in "$api_root_path/V8/OAuth2/private.key" \ -pubout -out "$api_root_path/V8/OAuth2/public.key" fi # Set ownership and permissions for SSL keys if [ -f "$api_root_path/V8/OAuth2/private.key" ]; then echo "[ tmc ] setting ownership and permissions for SSL keys in " $api_root_path > /dev/stdout chown www-data:www-data "$api_root_path/V8/OAuth2"/*.key chmod 600 "$api_root_path/V8/OAuth2"/*.key fi # end instructions that are run only for main docker execution fi echo "[ tmc ] init complete. starting apache" > /dev/stdout exec "$@"
Les autres fichiers de configuration
Vous pouvez adapter les valeurs dans le fichier php.ini
en fonction de votre serveur hôte et de vos besoins en ressources pour SuiteCRM.
php.ini
date.timezone = Europe/Paris memory_limit = 1G upload_max_filesize = 512M post_max_size = 512M max_execution_time = 600 display_errors = off log_errors = on fastcgi_logging = off catch_workers_output = yes decorate_workers_output = no error_log = /proc/self/fd/1 log_level = notice
php.conf
; this file contains additional directives ; currently it does not seems necessary ; global directives go into php.ini --> conf.d/suitecrm.ini [global] error_log = /proc/self/fd/2 log_level = notice [www] catch_workers_output = yes decorate_workers_output = no pm.max_children = 50 pm.start_servers = 15 pm.min_spare_servers = 15 pm.max_spare_servers = 25 pm.max_requests = 500
Les fichiers suivants servent à configurer le serveur Apache. Principalement, il faut dire à Apache qu’il est derrière un reverse proxy, et que le répertoire de base est /app/suitecrm/public
(modifié en cas de besoin par entrypoint.sh
, suivant la version de SuiteCRM).
Vous pouvez évidemment modifier le nom du serveur.
apache.conf
<Directory /app/suitecrm/public> Options -Indexes +FollowSymLinks AllowOverride All Require all granted </Directory> LogLevel error ServerTokens Prod ServerSignature Off ServerName themoto.company RemoteIPHeader X-Forwarded-For RemoteIPInternalProxy 172.16.0.0/12
vhost.conf
<VirtualHost *:80> ServerName themoto.company ServerAlias * # this lets apache know that we're behind a https proxy SetEnvIf X-Forwarded-Proto "https" HTTPS=on DocumentRoot /app/suitecrm/public ErrorLog "/var/log/apache2/error.log" LogFormat "%h %l %u %t \"%r\" %>s %b" common CustomLog "/var/log/apache2/access.log" common </VirtualHost>
Enfin, rien de très spécial pour le fichier de configuration cron, qui sert à mettre en place les tâches programmées de SuiteCRM.
cron-suitecrm
* * * * * www-data cd /var/www/suitecrm; php -f cron.php > /dev/null 2>&1
Voilà, tout est en place ! Une fois que tous les fichiers sont créés, il faut compiler le docker avec la commande :
docker build --network=host -t mysuitecrm .
Le fichier compose.yaml
Pour lancer le serveur et accéder à SuiteCRM, il faut ensuite créer un fichier compose.yaml
dans un autre répertoire, avec votre « stack » – ici un serveur de base de données, et le docker SuiteCRM.
Les paramètres « traefik » dans « labels » permettent d’utiliser le reverse proxy. C’est évidemment à adapter selon votre installation. Traefik gère automatiquement la récupération des certificats Let’s Encrypt pour le protocole HTTPS. C’est très efficace ! Mais n’oubliez pas de pointer un champ A dans vos enregistrements DNS vers votre serveur pour « your.suitecrm.url »
services: suitecrm-db: image: mariadb container_name: suitecrm-db restart: always networks: - my-network environment: - MARIADB_ROOT_PASSWORD=your-root-password - MARIADB_USER=suite - MARIADB_DATABASE=suite - MARIADB_PASSWORD=suite-user-password volumes: - ./mariadb-data:/var/lib/mysql suitecrm-app: image: mysuitecrm container_name: suitecrm-app networks: - my-network restart: always environment: - SUITECRM_DATABASE_HOST=suitecrm-db - SUITECRM_DATABASE_PORT_NUMBER=3306 - SUITECRM_DATABASE_USER=suite - SUITECRM_DATABASE_NAME=suite - SUITECRM_DATABASE_PASSWORD=user-password - SUITECRM_HOST=your.suitecrm.url volumes: - ./suitecrm-data:/app/suitecrm depends_on: - suitecrm-db labels: - traefik.enable=true - traefik.http.routers.suitecrm.rule=Host(`your.suitecrm.url`) - traefik.http.routers.suitecrm.entrypoints=websecure # - traefik.http.routers.suitecrm.middlewares=server-whitelist@file networks: prometheus: name: my-network external: true
Voilà !
Il faut ensuite copier les fichiers d’installation de SuiteCRM dans ./suitecrm-data
, puis il ne reste qu’à démarrer le stack avec :
docker compose up -d
(ou docker-compose, avec un tiret, si vous utilisez une version plus ancienne de compose)
Vous avez maintenant une version opérationnelle de SuiteCRM.
Bon travail !