This guide provides comprehensive instructions for deploying the Open LPR application using Docker and Docker Compose.
The Docker deployment includes:
- Multi-stage optimized Dockerfile for production
- Volume persistence for SQLite database and media files
- Environment variable configuration
- Health checks and monitoring
- Gunicorn WSGI server for production performance (included in requirements.txt)
- Multiple deployment options for different use cases
- Docker 20.10+ installed
- Docker Compose 2.0+ installed
- Sufficient disk space for media files and database
- For LlamaCpp deployments: HuggingFace token for model download
- For standard deployment: Qwen3-VL API access (API key and endpoint)
This project provides multiple Docker Compose files for different deployment scenarios:
For users with AMD GPUs that support Vulkan:
# Clone the repository
git clone https://github.com/faisalthaheem/open-lpr.git
cd open-lpr
# Create environment file from template
cp .env.llamacpp.example .env.llamacpp
# Edit the environment file with your settings
nano .env.llamacpp
# Create necessary directories
mkdir -p model_files model_files_cache container-data container-media staticfiles
# Start the application with AMD Vulkan GPU support
docker-compose -f docker-compose-llamacpp-amd-vulcan.yml up -d
# Check the logs to ensure everything is running correctly
docker-compose -f docker-compose-llamacpp-amd-vulcan.yml logs -fPrerequisites:
- AMD GPU with Vulkan support
- ROCm drivers installed
- Sufficient GPU memory (8GB+ recommended)
- HuggingFace token for model download
For users without compatible GPUs or for testing purposes:
# Clone the repository
git clone https://github.com/faisalthaheem/open-lpr.git
cd open-lpr
# Create environment file from template
cp .env.llamacpp.example .env.llamacpp
# Edit the environment file with your settings
nano .env.llamacpp
# Create necessary directories
mkdir -p model_files model_files_cache container-data container-media staticfiles
# Start the application with CPU support
docker-compose -f docker-compose-llamacpp-cpu.yml up -d
# Check the logs to ensure everything is running correctly
docker-compose -f docker-compose-llamacpp-cpu.yml logs -fPrerequisites:
- Sufficient RAM (16GB+ recommended)
- Multi-core CPU for better performance
- HuggingFace token for model download
For users who want to use an external OpenAI-compatible API endpoint:
# Clone the repository
git clone https://github.com/faisalthaheem/open-lpr.git
cd open-lpr
# Create environment file from template
cp .env.example .env
# Edit the environment file with your API settings
nano .env
# Create necessary directories
mkdir -p container-data container-media staticfiles
# Start the application
docker-compose up -d
# Check the logs to ensure everything is running correctly
docker-compose logs -fPrerequisites:
- Access to an OpenAI-compatible API endpoint
- Valid API credentials
Regardless of the deployment option, the application will be available at:
- Web Interface: http://localhost:8000
- API Endpoint: http://localhost:8000/api/v1/
- Health Check: http://localhost:8000/health/
For LlamaCpp deployments, the inference server is available at:
- LlamaCpp Server: http://localhost:8001
- LlamaCpp Health: http://localhost:8001/health
The Docker setup uses the following volume mounts:
./container-data/ → /app/data/ (SQLite database)
./container-media/→ /app/media/ (Uploaded and processed images)
./staticfiles/ → /app/staticfiles/ (Collected static files)
./container-data/ → /app/data/ (SQLite database)
./container-media/→ /app/media/ (Uploaded and processed images)
./staticfiles/ → /app/staticfiles/ (Collected static files)
./model_files/ → /models/ (Downloaded GGUF models)
./model_files_cache/ → /root/.cache/ (HuggingFace cache)
The SQLite database location is controlled by the DATABASE_PATH environment variable:
- Default (Development):
./data/db.sqlite3(project root/data/) - Docker:
/app/data/db.sqlite3(mounted to host ./container-data/)
This approach ensures:
- Database persistence across container restarts
- Easy backup and migration
- Direct access to the database file for maintenance
- Proper volume mounting for containerized deployment
- No permission issues in development environment
The application automatically detects the environment and configures paths accordingly:
- Database:
./data/db.sqlite3 - Logs:
./data/django.log - Media:
./media/ - Static files: Automatically created in
lpr_app/static/if missing
- Database:
/app/data/db.sqlite3(mounted to host ./container-data/) - Logs:
/app/data/django.log(mounted to host ./container-data/) - Media:
/app/media/(mounted to host ./container-media/)
All uploaded and processed images are stored in ./container-media/ on the host:
- Original images:
./container-media/uploads/ - Processed images:
./container-media/processed/
For production deployment:
-
Change default secrets:
SECRET_KEY=generate-a-strong-random-key DJANGO_SUPERUSER_PASSWORD=use-a-strong-password
-
Set DEBUG to False:
DEBUG=False
-
Configure ALLOWED_HOSTS:
ALLOWED_HOSTS=your-domain.com,www.your-domain.com
-
Use HTTPS in production (configure reverse proxy like Nginx)
The Dockerfile is optimized for production with:
- Multi-stage build for smaller image size
- Non-root user for security
- Gunicorn WSGI server with 3 workers
- 120-second timeout for image processing
For higher traffic, you can scale the application:
# Scale to 3 instances
docker-compose up -d --scale lpr-app=3Note: When scaling, consider:
- Using a shared database (PostgreSQL instead of SQLite)
- Shared storage for media files (NFS, S3, etc.)
- Load balancer for distributing traffic
# Build the image
docker build -t open-lpr:latest .
# Run with volume mounts
docker run -d \
--name open-lpr \
-p 8000:8000 \
-v $(pwd)/container-data:/app/data \
-v $(pwd)/container-media:/app/media \
--env-file .env \
open-lpr:latest# View logs
docker-compose logs -f lpr-app
# Execute commands in container
docker-compose exec lpr-app bash
# Create Django superuser manually
docker-compose exec lpr-app python manage.py createsuperuser
# Run migrations
docker-compose exec lpr-app python manage.py migrate
# Collect static files
docker-compose exec lpr-app python manage.py collectstatic --noinput# Backup database
docker-compose exec lpr-app cp /app/data/db.sqlite3 /app/data/db.sqlite3.backup
# Restore database
docker-compose exec lpr-app cp /app/data/db.sqlite3.backup /app/data/db.sqlite3
# Backup media files
tar -czf container-media-backup-$(date +%Y%m%d).tar.gz container-media/-
Container fails to start:
# Check logs docker-compose logs lpr-app # Check configuration docker-compose config
-
Database errors:
# Check database permissions ls -la container-data/ # Run migrations manually docker-compose exec lpr-app python manage.py migrate
-
Permission issues:
# Fix volume permissions sudo chown -R $USER:$USER container-data/ container-media/
-
API connection issues:
- Verify QWEN_API_KEY in .env file
- Check QWEN_BASE_URL accessibility
- Review application logs for API errors
The container includes health checks:
# Check health status
docker-compose ps
# Manual health check
curl http://localhost:8000/health/| Variable | Default | Description |
|---|---|---|
| SECRET_KEY | django-insecure-change-me | Django secret key |
| DEBUG | False | Django debug mode |
| ALLOWED_HOSTS | localhost,127.0.0.1 | Allowed hosts for Django |
| QWEN_API_KEY | - | Qwen3-VL API key (required) |
| QWEN_BASE_URL | https://ollama.computedsynergy.com/v1 | API endpoint URL |
| QWEN_MODEL | qwen3-vl-4b-instruct | AI model name |
| UPLOAD_FILE_MAX_SIZE | 10485760 | Maximum upload size (10MB) |
| MAX_BATCH_SIZE | 10 | Maximum batch processing size |
| DJANGO_SUPERUSER_USERNAME | - | Auto-create superuser username |
| DJANGO_SUPERUSER_EMAIL | - | Auto-create superuser email |
| DJANGO_SUPERUSER_PASSWORD | - | Auto-create superuser password |
| Variable | Default | Description |
|---|---|---|
| HF_TOKEN | - | HuggingFace token for model download (required) |
| MODEL_REPO | unsloth/Qwen3-VL-4B-Instruct-GGUF | HuggingFace model repository |
| MODEL_FILE | Qwen3-VL-4B-Instruct-Q5_K_M.gguf | Model file name |
| MMPROJ_URL | https://huggingface.co/unsloth/Qwen3-VL-4B-Instruct-GGUF/resolve/main/mmproj-BF16.gguf | Multimodal project file URL |
| SECRET_KEY | django-insecure-change-me | Django secret key |
| DEBUG | False | Django debug mode |
| ALLOWED_HOSTS | localhost,127.0.0.1,0.0.0.0 | Allowed hosts for Django |
| UPLOAD_FILE_MAX_SIZE | 10485760 | Maximum upload size (10MB) |
| MAX_BATCH_SIZE | 10 | Maximum batch processing size |
| DATABASE_PATH | /app/data/db.sqlite3 | Database path in container |
| DJANGO_SUPERUSER_USERNAME | - | Auto-create superuser username |
| DJANGO_SUPERUSER_EMAIL | - | Auto-create superuser email |
| DJANGO_SUPERUSER_PASSWORD | - | Auto-create superuser password |
To customize Gunicorn settings, modify the command in docker-compose.yml:
command: ["gunicorn", "--bind", "0.0.0.0:8000", "--workers", "4", "--worker-class", "gevent", "--timeout", "180", "lpr_project.wsgi:application"]For production, consider using PostgreSQL:
- Add PostgreSQL service to docker-compose.yml
- Update DATABASE_URL environment variable
- Install psycopg2 in requirements.txt
For production deployment with Nginx:
server {
listen 80;
server_name your-domain.com;
location / {
proxy_pass http://localhost:8000;
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;
}
location /static/ {
alias /path/to/staticfiles/;
}
location /media/ {
alias /path/to/media/;
}
}For specialized deployment scenarios:
- LlamaCpp and ROCm Resources - Important URLs for local LlamaCpp deployment
- README-llamacpp.md - Local inference with LlamaCpp server
- API Documentation - Complete REST API reference
For issues related to:
- Docker deployment: Check this guide and Docker documentation
- Application functionality: Review the main README.md
- API issues: Check API_DOCUMENTATION.md
For additional help, create an issue in the project repository with:
- Docker version
- Docker Compose version
- Complete error logs
- Environment configuration (without sensitive data)