Docker containerizes FreeScout into isolated, reproducible environments. This guide shows you how to deploy FreeScout with docker-compose in under 30 minutes.
Docker is ideal if you:
- Want to test FreeScout before committing to a full VPS
- Run multiple applications on one server
- Need easy scaling and rollbacks
- Prefer automation over manual configuration
Why Docker?
Pros:
- ✅ Install in 5 minutes (not 4 hours)
- ✅ Reproducible — same setup on any machine
- ✅ Easy scaling — run 2 containers instead of 1
- ✅ Easy updates — pull new image, restart
- ✅ Isolation — FreeScout doesn't affect other apps
Cons:
- ❌ Slightly more resources than bare metal
- ❌ Steeper learning curve (container concepts)
- ❌ Logs and debugging require Docker knowledge
Best for: Developers, small teams, testing, or teams already using Docker.
Prerequisites
You need:
- A VPS or local machine with Linux (Ubuntu 20.04+)
- Docker installed (
apt install docker.io) - Docker Compose installed (
apt install docker-compose) - A domain name (optional, but recommended)
- 2GB+ RAM for the container
Step 1: Install Docker & Docker Compose
sudo apt update && sudo apt upgrade -y
sudo apt install -y docker.io docker-compose git
sudo usermod -aG docker $USER # Run Docker without sudo
Verify installation:
docker --version
docker-compose --version
Step 2: Create Docker Compose File
Create a directory for FreeScout:
mkdir -p ~/freescout
cd ~/freescout
Create docker-compose.yml:
cat > docker-compose.yml << 'EOF'
version: '3.8'
services:
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: root_password_here
MYSQL_DATABASE: freescout
MYSQL_USER: freescout
MYSQL_PASSWORD: freescout_password
volumes:
- mysql_data:/var/lib/mysql
healthcheck:
test: ["CMD", "mysqldump", "--no-data", "-u", "root", "--password=root_password_here", "freescout"]
interval: 10s
timeout: 5s
retries: 5
freescout:
image: freescoutapp/freescout:latest
depends_on:
mysql:
condition: service_healthy
environment:
APP_URL: http://localhost:8080
APP_ENV: production
APP_KEY: base64:change_me_to_a_random_string
DB_HOST: mysql
DB_PORT: 3306
DB_DATABASE: freescout
DB_USERNAME: freescout
DB_PASSWORD: freescout_password
MAIL_DRIVER: smtp
MAIL_HOST: smtp.sendgrid.net
MAIL_PORT: 587
MAIL_USERNAME: apikey
MAIL_PASSWORD: your-sendgrid-api-key
MAIL_ENCRYPTION: tls
MAIL_FROM_ADDRESS: support@your-domain.com
MAIL_FROM_NAME: "Your Support"
ports:
- "8080:80"
volumes:
- freescout_storage:/var/www/html/storage
- freescout_public:/var/www/html/public
command: >
sh -c "php artisan migrate --force &&
php artisan freescout:after-app-update &&
php artisan storage:link &&
php-fpm"
queue:
image: freescoutapp/freescout:latest
depends_on:
- mysql
- freescout
environment:
APP_URL: http://localhost:8080
APP_ENV: production
APP_KEY: base64:change_me_to_a_random_string
DB_HOST: mysql
DB_PORT: 3306
DB_DATABASE: freescout
DB_USERNAME: freescout
DB_PASSWORD: freescout_password
volumes:
- freescout_storage:/var/www/html/storage
command: php artisan queue:work database --sleep=3 --tries=3 --timeout=60
volumes:
mysql_data:
freescout_storage:
freescout_public:
EOF
Replace these values:
root_password_here— strong password for MySQL rootfreescout_password— password for freescout useryour-sendgrid-api-key— your SendGrid API keysupport@your-domain.com— your support emailAPP_KEY— generate a random string:php -r "echo base64_encode(random_bytes(32));"
Step 3: Generate APP_KEY
Generate a cryptographically secure key:
docker run --rm freescoutapp/freescout php -r "echo base64_encode(random_bytes(32));"
Copy the output and paste it into docker-compose.yml for both freescout and queue services.
Step 4: Start the Containers
cd ~/freescout
docker-compose up -d
This starts three containers:
- mysql — database
- freescout — main application (port 8080)
- queue — background worker for emails
Check they're running:
docker-compose ps
You should see three containers with status Up.
Step 5: Wait for Initialization
FreeScout takes 30–60 seconds to initialize on first run:
docker-compose logs -f freescout
Wait until you see:
[info] Starting PHP-FPM...
Then press Ctrl+C.
Step 6: Access FreeScout
Open your browser to:
http://localhost:8080
(If running on a remote server, use the server's IP instead.)
Complete the web installer:
- Check system requirements (all should be green)
- Create admin account
- Configure your first mailbox
- Set email preferences
Step 7: Set Up Reverse Proxy with NGINX (for HTTPS)
If you want HTTPS with a domain, add NGINX:
Create nginx.conf:
cat > nginx.conf << 'EOF'
upstream freescout {
server freescout:80;
}
server {
listen 80;
server_name your-domain.com www.your-domain.com;
location / {
proxy_pass http://freescout;
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;
}
}
EOF
Update docker-compose.yml to add NGINX service:
nginx:
image: nginx:latest
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf
- ./ssl:/etc/nginx/ssl
depends_on:
- freescout
Restart:
docker-compose down
docker-compose up -d
Step 8: Add SSL with Let's Encrypt (Optional)
If using NGINX reverse proxy:
sudo apt install -y certbot
sudo certbot certonly --standalone -d your-domain.com -d www.your-domain.com
Copy certificates to your docker folder:
mkdir -p ~/freescout/ssl
sudo cp /etc/letsencrypt/live/your-domain.com/fullchain.pem ~/freescout/ssl/
sudo cp /etc/letsencrypt/live/your-domain.com/privkey.pem ~/freescout/ssl/
sudo chown $USER:$USER ~/freescout/ssl/*
Update nginx.conf with SSL configuration (advanced topic — see NGINX SSL docs).
Docker Commands You'll Need
Check Logs
# All services
docker-compose logs -f
# Specific service
docker-compose logs -f freescout
docker-compose logs -f queue
Restart Services
# Restart all
docker-compose restart
# Restart one service
docker-compose restart freescout
Stop Everything
docker-compose down
Update FreeScout (Pull Latest Image)
docker-compose pull freescout
docker-compose up -d freescout
Access MySQL Console
docker-compose exec mysql mysql -u freescout -p freescout
View Resource Usage
docker stats
Docker Volumes Explained
Three volumes are created:
- mysql_data — stores database (persistent)
- freescout_storage — stores uploads, logs, cache (persistent)
- freescout_public — stores public files (persistent)
Even if containers crash or are deleted, volumes persist. Data is never lost.
To back up volumes:
docker run --rm -v freescout_mysql_data:/data -v $(pwd):/backup alpine tar czf /backup/mysql_backup.tar.gz /data
Scaling with Docker
Run Multiple Queue Workers
Edit docker-compose.yml:
queue1:
image: freescoutapp/freescout:latest
# ... same config ...
queue2:
image: freescoutapp/freescout:latest
# ... same config ...
queue3:
image: freescoutapp/freescout:latest
# ... same config ...
Three workers = 3x email processing speed.
Run on Docker Swarm or Kubernetes
For enterprise deployment, you can orchestrate FreeScout across multiple machines using Docker Swarm or Kubernetes. Advanced topic — beyond this guide.
Common Docker Issues
| Issue | Cause | Fix |
|---|---|---|
| "Cannot connect to Docker daemon" | Docker not started | sudo systemctl start docker |
| Port 8080 already in use | Another app using port | Change port in docker-compose.yml: 8081:80 |
| MySQL won't start | Data corruption | docker-compose down && docker volume rm freescout_mysql_data (⚠️ loses data) |
| Emails not sending | SMTP credentials wrong | Check env vars in docker-compose.yml |
| Queue not working | Queue container crashed | docker-compose logs queue to see errors |
Docker vs Traditional VPS
| | Docker | VPS | |---|---|---| | Setup time | 5 min | 4 hours | | Portability | Run anywhere | Locked to one server | | Resource overhead | ~10% more | None | | Scaling | Easy (more containers) | Hard (migrate VPS) | | Backups | Volume snapshots | Full disk backups | | Learning curve | Medium | Low | | Best for | Developers, testing, teams with Docker experience | Traditional sysadmins, long-term production |
Want FreeScout Docker deployment configured and optimized?
We handle the full FreeScout installation on your server — SSL, email, security hardening, and a 1-hour onboarding call. Done in 24 hours.
One-time fee · 30-day support · Money-back guarantee
Next Steps
- Persistent Storage: Move data to a network volume (NFS, Ceph) for production
- Monitoring: Add Prometheus/Grafana for container metrics
- Auto-scaling: Use Kubernetes for automatic scaling based on load
- CI/CD: Automate FreeScout updates with GitLab CI or GitHub Actions
For now, you have a working FreeScout instance in 30 minutes with zero Linux configuration. That's the power of Docker.
Resources
- Docker Documentation — official Docker guide
- Docker Compose Reference — compose file specification
- FreeScout on Docker Hub — official Docker image
- FreeScout GitHub — source code and releases