# Save this as docker-compose.yml
services:
mautic_web:
image: mautic/mautic:6.0.3-apache
container_name: mautic_web
restart: unless-stopped
ports:
- "8:80"
volumes:
- mautic_config:/var/www/html/config
- mautic_docroot:/var/www/html/docroot
- mautic_media:/var/www/html/docroot/media
- mautic_logs:/var/www/html/var/logs
- mautic_cron:/opt/mautic/cron
- mautic_var:/var/www/html/var # ✅ Share /var directory
environment:
MAUTIC_DB_NAME: ${MAUTIC_DB_NAME}
MAUTIC_DB_HOST: ${MAUTIC_DB_HOST}
MAUTIC_DB_PORT: ${MAUTIC_DB_PORT}
MAUTIC_DB_USER: ${MAUTIC_DB_USER}
MAUTIC_DB_PASSWORD: ${MAUTIC_DB_PASSWORD}
MAUTIC_ADMIN_EMAIL: ${MAUTIC_ADMIN_EMAIL}
MAUTIC_ADMIN_USERNAME: ${MAUTIC_ADMIN_USERNAME}
MAUTIC_ADMIN_PASSWORD: ${MAUTIC_ADMIN_PASSWORD}
MAUTIC_URL: ${MAUTIC_URL}
MAUTIC_TRUSTED_PROXIES: ${MAUTIC_TRUSTED_PROXIES}
DOCKER_MAUTIC_ROLE: mautic_web
DOCKER_MAUTIC_WORKERS_CONSUME_EMAIL: ${DOCKER_MAUTIC_WORKERS_CONSUME_EMAIL}
DOCKER_MAUTIC_WORKERS_CONSUME_HIT: ${DOCKER_MAUTIC_WORKERS_CONSUME_HIT}
DOCKER_MAUTIC_WORKERS_CONSUME_FAILED: ${DOCKER_MAUTIC_WORKERS_CONSUME_FAILED}
depends_on:
- db
mautic_worker:
build:
context: .
dockerfile: Dockerfile.worker
container_name: mautic_worker
restart: unless-stopped
volumes:
- mautic_config:/var/www/html/config
- mautic_docroot:/var/www/html/docroot
- mautic_media:/var/www/html/docroot/media
- mautic_logs:/var/www/html/var/logs
- mautic_var:/var/www/html/var
environment:
MAUTIC_DB_NAME: ${MAUTIC_DB_NAME}
MAUTIC_DB_HOST: ${MAUTIC_DB_HOST}
MAUTIC_DB_PORT: ${MAUTIC_DB_PORT}
MAUTIC_DB_USER: ${MAUTIC_DB_USER}
MAUTIC_DB_PASSWORD: ${MAUTIC_DB_PASSWORD}
MAUTIC_ADMIN_EMAIL: ${MAUTIC_ADMIN_EMAIL}
MAUTIC_ADMIN_USERNAME: ${MAUTIC_ADMIN_USERNAME}
MAUTIC_ADMIN_PASSWORD: ${MAUTIC_ADMIN_PASSWORD}
MAUTIC_URL: ${MAUTIC_URL}
MAUTIC_TRUSTED_PROXIES: ${MAUTIC_TRUSTED_PROXIES}
depends_on:
- db
mautic_cron:
image: mautic/mautic:6.0.3-apache
container_name: mautic_cron
restart: unless-stopped
volumes:
- mautic_config:/var/www/html/config
- mautic_docroot:/var/www/html/docroot
- mautic_media:/var/www/html/docroot/media
- mautic_logs:/var/www/html/var/logs
- mautic_cron:/opt/mautic/cron
- mautic_var:/var/www/html/var # ✅ Share /var directory
environment:
MAUTIC_DB_NAME: ${MAUTIC_DB_NAME}
MAUTIC_DB_HOST: ${MAUTIC_DB_HOST}
MAUTIC_DB_PORT: ${MAUTIC_DB_PORT}
MAUTIC_DB_USER: ${MAUTIC_DB_USER}
MAUTIC_DB_PASSWORD: ${MAUTIC_DB_PASSWORD}
MAUTIC_ADMIN_EMAIL: ${MAUTIC_ADMIN_EMAIL}
MAUTIC_ADMIN_USERNAME: ${MAUTIC_ADMIN_USERNAME}
MAUTIC_ADMIN_PASSWORD: ${MAUTIC_ADMIN_PASSWORD}
MAUTIC_URL: ${MAUTIC_URL}
MAUTIC_TRUSTED_PROXIES: ${MAUTIC_TRUSTED_PROXIES}
DOCKER_MAUTIC_ROLE: mautic_cron
DOCKER_MAUTIC_WORKERS_CONSUME_EMAIL: ${DOCKER_MAUTIC_WORKERS_CONSUME_EMAIL}
DOCKER_MAUTIC_WORKERS_CONSUME_HIT: ${DOCKER_MAUTIC_WORKERS_CONSUME_HIT}
DOCKER_MAUTIC_WORKERS_CONSUME_FAILED: ${DOCKER_MAUTIC_WORKERS_CONSUME_FAILED}
depends_on:
- db
db:
image: mariadb:10.6
container_name: mautic_db
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: ${MYSQL_DATABASE}
MYSQL_USER: ${MYSQL_USER}
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
volumes:
- mautic_db_data:/var/lib/mysql
volumes:
mautic_config:
mautic_docroot:
mautic_media:
mautic_logs:
mautic_cron:
mautic_var:
mautic_db_data:
# Save this as startup.sh and then hit 'sudo chmod +x startup.sh'
#!/bin/bash
echo "🚀 Starting custom Mautic worker..."
# Import contacts every 1 min
while true; do
php /var/www/html/bin/console mautic:import --env=prod
sleep 60
done &
# Update segments every 5 min
while true; do
php /var/www/html/bin/console mautic:segments:update --env=prod
sleep 300
done &
# Trigger campaign events every 5 min
while true; do
php /var/www/html/bin/console mautic:campaigns:trigger --env=prod
sleep 300
done &
# Update campaign membership every 5 min
while true; do
php /var/www/html/bin/console mautic:campaigns:update --env=prod
sleep 300
done &
# Send emails every 2 min
while true; do
php /var/www/html/bin/console mautic:messages:send --env=prod
sleep 120
done &
# Export queued contact exports every 3 min
while true; do
php /var/www/html/bin/console mautic:contacts:scheduled_export
sleep 180
done &
# Start async consumers
php /var/www/html/bin/console messenger:consume email --env=prod &
php /var/www/html/bin/console messenger:consume hit --env=prod &
php /var/www/html/bin/console messenger:consume failed --env=prod &
wait
# Save this as Dockerfile.worker
FROM mautic/mautic:6.0.3-apache
COPY startup.sh /startup.sh
RUN chmod +x /startup.sh
CMD ["/startup.sh"]
# Save this as .env
# Database
MYSQL_ROOT_PASSWORD=rootpassword
MYSQL_DATABASE=mautic
MYSQL_USER=root
MYSQL_PASSWORD=rootpassword
MAUTIC_DB_NAME=mautic
MAUTIC_DB_HOST=db
MAUTIC_DB_PORT=3306
MAUTIC_DB_USER=root
MAUTIC_DB_PASSWORD=rootpassword
# Admin
MAUTIC_ADMIN_EMAIL=<[email protected]>
MAUTIC_ADMIN_USERNAME=admin
MAUTIC_ADMIN_PASSWORD=<yourdesiredpassword>
# Mautic config
MAUTIC_URL=https://<yourdomain.com>
MAUTIC_TRUSTED_PROXIES=["0.0.0.0/0"]
DOCKER_MAUTIC_WORKERS_CONSUME_EMAIL=2
DOCKER_MAUTIC_WORKERS_CONSUME_HIT=2
DOCKER_MAUTIC_WORKERS_CONSUME_FAILED=2
After all your files are saved (should be in the same folder), type
docker compose build mautic_worker && docker compose up -d
And boom! You now just have to go through the mautic setup wizard and set that up.
One note: Once you set up mautic, go into the Settings > configuration > queue, then change the options from “sync” to “doctrine” / default as seen here. Do this for all 3 sections that ask for scheme, host etc.

And there you go! You have a functional Mautic installation now with all the major features!
Happy emailing!