6.7 KiB
Docker Bind Mounts Setup for Windows Server
Overview
This application uses bind mounts (not Docker volumes) to store business-critical files directly on the Windows host filesystem.
Directory Structure
Container Paths (inside Docker)
/app/Faces- User face recognition data/app/Storage- Uploaded files and documents/app/Logs- Application logs
Windows Host Paths
D:\AppData\FacesD:\AppData\StorageD:\AppData\Logs
Initial Setup
1. Create Host Directories
Before starting the container, create the required directories on the Windows host:
# Create directories if they don't exist
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. Set Permissions (Windows Server)
Grant full access to the directories for the Docker container:
# Grant full control to Everyone (or specific user account)
icacls "D:\AppData\Faces" /grant Everyone:F /T
icacls "D:\AppData\Storage" /grant Everyone:F /T
icacls "D:\AppData\Logs" /grant Everyone:F /T
Note: For production, replace Everyone with a specific service account:
# Example with specific user
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
Docker Compose Configuration
The docker-compose.yml is already configured with bind mounts:
volumes:
- ./ServiceHost/certs:/app/certs:ro
- D:/AppData/Faces:/app/Faces
- D:/AppData/Storage:/app/Storage
- D:/AppData/Logs:/app/Logs
Start the Application
docker-compose up -d
Alternative: Docker Run Command
If you prefer using docker run instead of docker-compose:
docker run -d `
--name gozareshgir-servicehost `
-p 5003:80 `
-p 5004:443 `
-v "D:/AppData/Faces:/app/Faces" `
-v "D:/AppData/Storage:/app/Storage" `
-v "D:/AppData/Logs:/app/Logs" `
-v "${PWD}/ServiceHost/certs:/app/certs:ro" `
--env-file ./ServiceHost/.env `
--add-host=host.docker.internal:host-gateway `
--restart unless-stopped `
gozareshgir-servicehost:latest
Verification
1. Check if directories are mounted correctly
docker exec gozareshgir-servicehost ls -la /app
You should see:
drwxr-xr-x Faces
drwxr-xr-x Storage
drwxr-xr-x Logs
2. Test write access
# Create a test file from within the container
docker exec gozareshgir-servicehost sh -c "echo 'test' > /app/Storage/test.txt"
# Verify it appears on the host
Get-Content "D:\AppData\Storage\test.txt"
# Clean up
Remove-Item "D:\AppData\Storage\test.txt"
3. Verify from the host side
# Create a file on the host
"test from host" | Out-File -FilePath "D:\AppData\Storage\host-test.txt"
# Check if visible in container
docker exec gozareshgir-servicehost cat /app/Storage/host-test.txt
# Clean up
Remove-Item "D:\AppData\Storage\host-test.txt"
Application Code Compatibility
The application uses:
Path.Combine(env.ContentRootPath, "Faces");
Path.Combine(env.ContentRootPath, "Storage");
Where env.ContentRootPath = /app in the container.
No code changes required - the bind mounts map exactly to these paths.
Data Persistence & Safety
✅ Benefits of Bind Mounts:
- Files persist on host even if container is removed
- Direct backup from Windows Server (e.g., Windows Backup, robocopy)
- Can be accessed by other applications/services on the host
- No Docker volume management needed
- Easy to migrate to a different server
✅ Safety:
- Data survives
docker-compose down - Data survives
docker rm - Data survives container rebuilds
- Can be included in host backup solutions
⚠️ Important:
- Do NOT delete the host directories (
D:\AppData\*) - Ensure adequate disk space on D: drive
- Regular backups of
D:\AppData\recommended
Backup Strategy
Manual Backup
# Create a timestamped backup
$timestamp = Get-Date -Format "yyyyMMdd_HHmmss"
robocopy "D:\AppData" "D:\Backups\AppData_$timestamp" /MIR /Z /LOG:"D:\Backups\backup_$timestamp.log"
Scheduled Backup (Task Scheduler)
# Create a scheduled task for daily backups
$action = New-ScheduledTaskAction -Execute "robocopy" -Argument '"D:\AppData" "D:\Backups\AppData" /MIR /Z'
$trigger = New-ScheduledTaskTrigger -Daily -At 2am
Register-ScheduledTask -Action $action -Trigger $trigger -TaskName "GozareshgirBackup" -Description "Daily backup of application data"
Troubleshooting
Issue: Permission Denied
# Fix 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: Directory Not Found
# Ensure directories exist
Test-Path "D:\AppData\Faces"
Test-Path "D:\AppData\Storage"
Test-Path "D:\AppData\Logs"
# Create if missing
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"
Issue: Files Not Appearing
-
Check container logs:
docker logs gozareshgir-servicehost -
Verify mount points:
docker inspect gozareshgir-servicehost --format='{{json .Mounts}}' | ConvertFrom-Json -
Test write access (see Verification section above)
Migration Notes
Moving to a Different Server
-
Stop the container:
docker-compose down -
Copy the data:
robocopy "D:\AppData" "\\NewServer\D$\AppData" /MIR /Z -
On the new server, ensure directories exist and have correct permissions
-
Start the container on the new server:
docker-compose up -d
Performance Considerations
- Bind mounts on Windows have good performance for most workloads
- For high-frequency writes, consider using SSD storage for
D:\AppData - Monitor disk space regularly:
Get-PSDrive D | Select-Object Used,Free
Security Best Practices
- Restrict permissions to specific service accounts (not Everyone)
- Enable NTFS encryption for sensitive data:
cipher /e "D:\AppData\Faces" cipher /e "D:\AppData\Storage" - Regular backups with retention policy
- Firewall rules to restrict access to the host
- Audit logging for file access:
auditpol /set /subcategory:"File System" /success:enable /failure:enable
Last Updated: January 2026
Tested On: Windows Server 2019/2022 with Docker Desktop or Docker Engine