Overview

This guide covers the deployment and configuration of EspoCRM using Docker Compose behind Traefik reverse proxy. EspoCRM serves as Mondo’s customer relationship management solution, accessible at crm.trymondo.com.

Architecture

EspoCRM is deployed as a multi-container application with the following components:

  • MariaDB: Database server storing EspoCRM data
  • EspoCRM: Main application container
  • EspoCRM Daemon: Background process container
  • EspoCRM WebSocket: Real-time communications container

All services use the external traefik-net network for routing through Traefik.

Prerequisites

  • Docker Engine (24.0+)
  • Docker Compose v2
  • Traefik reverse proxy configured and running
  • External traefik-net network
  • DNS configured for crm.trymondo.com

Deployment

Directory Structure

environments/prod/espocrm/
├── docker-compose.yml       # Main configuration file
├── .env                     # Environment variables (not in repo)

Environment Variables

Create a .env file with the following variables:

MYSQL_ROOT_PASSWORD=your_secure_password
MYSQL_DATABASE=espocrm
MYSQL_USER=espocrm_user
MYSQL_PASSWORD=your_secure_password
ESPO_ADMIN_USERNAME=admin
ESPO_ADMIN_PASSWORD=your_secure_password
ESPO_SITE_URL=https://crm.trymondo.com

Never commit the .env file to version control. Store passwords securely in your password manager.

Docker Compose Configuration

The deployment uses a shared image reference and multiple service definitions:

x-espocrm-image: &espocrm-image
  image: espocrm/espocrm:9.0.8

services:
  mariadb:
    image: mariadb:11.7.2
    container_name: espocrm-db
    restart: unless-stopped
    init: true
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      MYSQL_DATABASE: ${MYSQL_DATABASE}
      MYSQL_USER: ${MYSQL_USER}
      MYSQL_PASSWORD: ${MYSQL_PASSWORD}
    volumes:
      - mariadb-data:/var/lib/mysql
    healthcheck:
      test:
        [
          'CMD-SHELL',
          'mariadb-admin ping -h 127.0.0.1 -u root -p$${MYSQL_ROOT_PASSWORD}',
        ]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 20s
    networks:
      - espocrm-net

  espocrm:
    <<: *espocrm-image
    container_name: espocrm
    restart: unless-stopped
    init: true
    depends_on:
      mariadb:
        condition: service_healthy
    environment:
      ESPOCRM_DATABASE_DRIVER: mysql
      ESPOCRM_DATABASE_HOST: mariadb
      ESPOCRM_DATABASE_USER: ${MYSQL_USER}
      ESPOCRM_DATABASE_PASSWORD: ${MYSQL_PASSWORD}
      ESPOCRM_DATABASE_NAME: ${MYSQL_DATABASE}
      ESPOCRM_ADMIN_USERNAME: ${ESPO_ADMIN_USERNAME}
      ESPOCRM_ADMIN_PASSWORD: ${ESPO_ADMIN_PASSWORD}
      ESPOCRM_SITE_URL: ${ESPO_SITE_URL}
    volumes:
      - html-data:/var/www/html
    healthcheck:
      test: ['CMD-SHELL', 'curl -sf http://localhost || exit 1']
      interval: 10s
      timeout: 5s
      retries: 5
    networks:
      - traefik-net
      - espocrm-net
    labels:
      - traefik.enable=true
      - traefik.http.routers.espocrm.rule=Host(`crm.trymondo.com`)
      - traefik.http.routers.espocrm.entrypoints=web,websecure
      - traefik.http.routers.espocrm.tls=true
      - traefik.http.routers.espocrm.tls.certresolver=production
      - traefik.http.services.espocrm.loadbalancer.server.port=80
      - traefik.http.routers.espocrm.middlewares=secureHeaders@file

  espocrm-daemon:
    <<: *espocrm-image
    container_name: espocrm-daemon
    restart: unless-stopped
    init: true
    entrypoint: docker-daemon.sh
    depends_on:
      - espocrm
    volumes:
      - html-data:/var/www/html
    networks:
      - espocrm-net

  espocrm-websocket:
    <<: *espocrm-image
    container_name: espocrm-websocket
    restart: unless-stopped
    init: true
    entrypoint: docker-websocket.sh
    depends_on:
      - espocrm
    environment:
      ESPOCRM_CONFIG_USE_WEB_SOCKET: 'true'
      ESPOCRM_CONFIG_WEB_SOCKET_URL: 'wss://crm.trymondo.com/ws'
      ESPOCRM_CONFIG_WEB_SOCKET_ZERO_M_Q_SUBSCRIBER_DSN: 'tcp://*:7777'
      ESPOCRM_CONFIG_WEB_SOCKET_ZERO_M_Q_SUBMISSION_DSN: 'tcp://espocrm-websocket:7777'
    volumes:
      - html-data:/var/www/html
    networks:
      - traefik-net
      - espocrm-net
    labels:
      - traefik.enable=true
      - traefik.http.routers.espocrm-ws.rule=Host(`crm.trymondo.com`) && PathPrefix(`/ws`)
      - traefik.http.routers.espocrm-ws.entrypoints=web,websecure
      - traefik.http.routers.espocrm-ws.tls=true
      - traefik.http.routers.espocrm-ws.tls.certresolver=production
      - traefik.http.services.espocrm-ws.loadbalancer.server.port=80

volumes:
  mariadb-data:
  html-data:

networks:
  traefik-net:
    external: true
  espocrm-net:
    external: true

Deployment Commands

Deploy the stack with:

cd /opt/apps/espocrm
docker compose up -d

Verify all components are running:

docker compose ps

Configuration Highlights

Traefik Integration

EspoCRM is configured with the following Traefik routing:

  • Main application at crm.trymondo.com
  • WebSocket endpoint at crm.trymondo.com/ws
  • TLS certificate managed by Traefik’s production resolver
  • Security headers applied through Traefik middleware

WebSocket Configuration

Real-time communication is enabled through ZeroMQ and WebSockets:

  • WebSocket URL: wss://crm.trymondo.com/ws
  • Internal ZeroMQ communication between containers
  • Separate Traefik router rule for WebSocket traffic

Volume Management

The deployment uses Docker named volumes:

  • mariadb-data: Persistent storage for the database
  • html-data: Shared volume for EspoCRM application data across all containers

Maintenance

Backup Strategy

EspoCRM data should be backed up regularly using Restic/Backrest:

# Backup database
docker compose exec mariadb mysqldump -u root -p${MYSQL_ROOT_PASSWORD} ${MYSQL_DATABASE} > backup_$(date +%Y%m%d).sql

# Include volumes in Backrest paths
# /var/lib/docker/volumes/espocrm_mariadb-data
# /var/lib/docker/volumes/espocrm_html-data

Updates

To update EspoCRM:

  1. Update the image version tag in docker-compose.yml
  2. Pull the new image:
    docker compose pull
    
  3. Deploy the updated stack:
    docker compose up -d
    
  4. Check logs for any migration issues:
    docker compose logs -f
    

Troubleshooting

Database Connection Issues

If EspoCRM can’t connect to the database:

  1. Check MariaDB container status:
    docker compose ps mariadb
    
  2. Verify network connectivity:
    docker compose exec espocrm ping mariadb
    
  3. Check database credentials:
    docker compose exec mariadb mysql -u ${MYSQL_USER} -p${MYSQL_PASSWORD} -e "SHOW DATABASES;"
    

WebSocket Issues

If real-time updates aren’t working:

  1. Check WebSocket container is running:
    docker compose ps espocrm-websocket
    
  2. Verify WebSocket URL configuration matches the Traefik route.
  3. Test WebSocket connectivity from browser developer tools.

Traefik Routing Problems

If the site is unreachable:

  1. Check Traefik logs:
    docker logs traefik
    
  2. Verify DNS resolution for crm.trymondo.com
  3. Confirm Traefik network is correctly attached to all containers.

Resources

Next Steps

  • Set up monitoring and alerting for EspoCRM services with Prometheus/Grafana
  • Implement automated backups of volumes and database dumps
  • Configure SMTP for email notifications
  • Explore EspoCRM API integrations with other Mondo services

Was this page helpful?