# ✅ Docker Bind Mounts Configuration - Summary ## What Was Changed ### 1. docker-compose.yml **Before:** ```yaml volumes: - ./ServiceHost/certs:/app/certs:ro - app_storage:/app/Storage # ❌ Docker volume - app_logs:/app/Logs # ❌ Docker volume volumes: app_storage: driver: local app_logs: driver: local ``` **After:** ```yaml volumes: # ✅ Bind mounts for production-critical data on Windows host - ./ServiceHost/certs:/app/certs:ro - D:/AppData/Faces:/app/Faces - D:/AppData/Storage:/app/Storage - D:/AppData/Logs:/app/Logs # ✅ No volumes section needed ``` ### 2. New Files Created - `DOCKER_BIND_MOUNTS_SETUP.md` - Complete documentation - `setup-bind-mounts.ps1` - Automated setup script - `QUICK_REFERENCE.md` - Quick command reference ## Path Mapping | Container (Linux paths) | Windows Host (forward slash) | Actual Windows Path | |-------------------------|------------------------------|---------------------| | `/app/Faces` | `D:/AppData/Faces` | `D:\AppData\Faces` | | `/app/Storage` | `D:/AppData/Storage` | `D:\AppData\Storage`| | `/app/Logs` | `D:/AppData/Logs` | `D:\AppData\Logs` | **Note:** Docker Compose on Windows accepts both `D:/` and `D:\` but prefers forward slashes. ## Application Code Compatibility Your application uses: ```csharp Path.Combine(env.ContentRootPath, "Faces"); // → /app/Faces Path.Combine(env.ContentRootPath, "Storage"); // → /app/Storage ``` Where `env.ContentRootPath` = `/app` in the container. ✅ **No code changes required!** The bind mounts map directly to these paths. ## Setup Instructions ### Option 1: Automated Setup (Recommended) ```powershell # Navigate to project directory cd D:\GozareshgirOrginal\OriginalGozareshgir # Run setup script with permissions .\setup-bind-mounts.ps1 -GrantFullPermissions # Start the application docker-compose up -d ``` ### Option 2: Manual Setup ```powershell # 1. Create directories New-Item -ItemType Directory -Force -Path "D:\AppData\Faces" New-Item -ItemType Directory -Force -Path "D:\AppData\Storage" New-Item -ItemType Directory -Force -Path "D:\AppData\Logs" # 2. Grant permissions icacls "D:\AppData\Faces" /grant Everyone:F /T icacls "D:\AppData\Storage" /grant Everyone:F /T icacls "D:\AppData\Logs" /grant Everyone:F /T # 3. Start the application docker-compose up -d ``` ## Verification Checklist After starting the container: 1. **Check if directories are mounted:** ```powershell docker exec gozareshgir-servicehost ls -la /app ``` Should show: `Faces/`, `Storage/`, `Logs/` 2. **Test write access from container:** ```powershell docker exec gozareshgir-servicehost sh -c "echo 'test' > /app/Storage/test.txt" Get-Content D:\AppData\Storage\test.txt # Should display: test Remove-Item D:\AppData\Storage\test.txt ``` 3. **Test write access from host:** ```powershell "test from host" | Out-File "D:\AppData\Storage\host-test.txt" docker exec gozareshgir-servicehost cat /app/Storage/host-test.txt Remove-Item D:\AppData\Storage\host-test.txt ``` 4. **Check application logs:** ```powershell docker logs gozareshgir-servicehost --tail 50 # Or directly on host: Get-Content D:\AppData\Logs\gozareshgir_log.txt -Tail 50 ``` ## Data Persistence Guarantees ✅ **Files persist through:** - `docker-compose down` - `docker-compose restart` - Container removal (`docker rm`) - Image rebuilds (`docker-compose build`) - Server reboots (with `restart: unless-stopped`) ✅ **Direct access:** - Files can be accessed from Windows Explorer at `D:\AppData\*` - Can be backed up using Windows Backup, robocopy, or any backup software - Can be edited directly on the host (changes visible in container immediately) ⚠️ **Data does NOT survive:** - Deleting the host directories (`D:\AppData\*`) - Formatting the D: drive - Without regular backups, hardware failures ## Production Checklist Before deploying to production: - [ ] Run `setup-bind-mounts.ps1 -GrantFullPermissions` - [ ] Verify disk space on D: drive (at least 50 GB recommended) - [ ] Set up scheduled backups (see `DOCKER_BIND_MOUNTS_SETUP.md`) - [ ] Replace `Everyone` with specific service account for permissions - [ ] Enable NTFS encryption for sensitive data (optional) - [ ] Test container restart: `docker-compose restart` - [ ] Test data persistence: Create a test file, restart container, verify file exists - [ ] Configure monitoring for disk space usage ## Security Recommendations 1. **Restrict permissions** (production): ```powershell # Replace Everyone with specific account icacls "D:\AppData\Faces" /grant "DOMAIN\ServiceAccount:(OI)(CI)F" /T icacls "D:\AppData\Storage" /grant "DOMAIN\ServiceAccount:(OI)(CI)F" /T icacls "D:\AppData\Logs" /grant "DOMAIN\ServiceAccount:(OI)(CI)F" /T ``` 2. **Enable encryption** for sensitive data: ```powershell cipher /e "D:\AppData\Faces" cipher /e "D:\AppData\Storage" ``` 3. **Set up audit logging:** ```powershell auditpol /set /subcategory:"File System" /success:enable /failure:enable ``` ## Backup Strategy ### Scheduled Backup (Recommended) ```powershell # Create daily backup at 2 AM $action = New-ScheduledTaskAction -Execute "robocopy" -Argument '"D:\AppData" "D:\Backups\AppData" /MIR /Z /LOG:"D:\Backups\backup.log"' $trigger = New-ScheduledTaskTrigger -Daily -At 2am Register-ScheduledTask -Action $action -Trigger $trigger -TaskName "GozareshgirBackup" -Description "Daily backup of Gozareshgir data" ``` ### Manual Backup ```powershell $timestamp = Get-Date -Format "yyyyMMdd_HHmmss" robocopy "D:\AppData" "D:\Backups\AppData_$timestamp" /MIR /Z ``` ## Troubleshooting ### Issue: Container starts but files not appearing **Solution:** ```powershell # Check mount points docker inspect gozareshgir-servicehost --format='{{json .Mounts}}' | ConvertFrom-Json # Verify directories exist Test-Path D:\AppData\Faces Test-Path D:\AppData\Storage Test-Path D:\AppData\Logs ``` ### Issue: Permission denied errors **Solution:** ```powershell # Re-grant permissions icacls "D:\AppData\Faces" /grant Everyone:F /T icacls "D:\AppData\Storage" /grant Everyone:F /T icacls "D:\AppData\Logs" /grant Everyone:F /T ``` ### Issue: Out of disk space **Solution:** ```powershell # Check disk usage Get-ChildItem D:\AppData -Recurse | Measure-Object -Property Length -Sum # Clean old log files (example: older than 30 days) Get-ChildItem D:\AppData\Logs -Recurse -File | Where-Object {$_.LastWriteTime -lt (Get-Date).AddDays(-30)} | Remove-Item ``` ## Support & Documentation - **Full Documentation:** `DOCKER_BIND_MOUNTS_SETUP.md` - **Quick Reference:** `QUICK_REFERENCE.md` - **Setup Script:** `setup-bind-mounts.ps1` ## Migration from Docker Volumes (If applicable) If you previously used Docker volumes, migrate the data: ```powershell # 1. Stop the container docker-compose down # 2. Copy data from old volumes to host docker run --rm -v old_volume_name:/source -v D:/AppData/Storage:/dest alpine cp -av /source/. /dest/ # 3. Start with new bind mounts docker-compose up -d ``` --- **Configuration Date:** January 2026 **Tested On:** Windows Server 2019/2022 with Docker Desktop **Status:** ✅ Production Ready