256 lines
6.7 KiB
Markdown
256 lines
6.7 KiB
Markdown
# 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\Faces`
|
|
- `D:\AppData\Storage`
|
|
- `D:\AppData\Logs`
|
|
|
|
## Initial Setup
|
|
|
|
### 1. Create Host Directories
|
|
Before starting the container, create the required directories on the Windows host:
|
|
|
|
```powershell
|
|
# 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:
|
|
|
|
```powershell
|
|
# 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:
|
|
```powershell
|
|
# 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:
|
|
|
|
```yaml
|
|
volumes:
|
|
- ./ServiceHost/certs:/app/certs:ro
|
|
- D:/AppData/Faces:/app/Faces
|
|
- D:/AppData/Storage:/app/Storage
|
|
- D:/AppData/Logs:/app/Logs
|
|
```
|
|
|
|
### Start the Application
|
|
```powershell
|
|
docker-compose up -d
|
|
```
|
|
|
|
## Alternative: Docker Run Command
|
|
|
|
If you prefer using `docker run` instead of docker-compose:
|
|
|
|
```powershell
|
|
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
|
|
```powershell
|
|
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
|
|
```powershell
|
|
# 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
|
|
```powershell
|
|
# 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:
|
|
```csharp
|
|
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
|
|
```powershell
|
|
# 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)
|
|
```powershell
|
|
# 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
|
|
```powershell
|
|
# 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
|
|
```powershell
|
|
# 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
|
|
1. Check container logs:
|
|
```powershell
|
|
docker logs gozareshgir-servicehost
|
|
```
|
|
|
|
2. Verify mount points:
|
|
```powershell
|
|
docker inspect gozareshgir-servicehost --format='{{json .Mounts}}' | ConvertFrom-Json
|
|
```
|
|
|
|
3. Test write access (see Verification section above)
|
|
|
|
## Migration Notes
|
|
|
|
### Moving to a Different Server
|
|
1. Stop the container:
|
|
```powershell
|
|
docker-compose down
|
|
```
|
|
|
|
2. Copy the data:
|
|
```powershell
|
|
robocopy "D:\AppData" "\\NewServer\D$\AppData" /MIR /Z
|
|
```
|
|
|
|
3. On the new server, ensure directories exist and have correct permissions
|
|
|
|
4. Start the container on the new server:
|
|
```powershell
|
|
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:
|
|
```powershell
|
|
Get-PSDrive D | Select-Object Used,Free
|
|
```
|
|
|
|
## Security Best Practices
|
|
|
|
1. **Restrict permissions** to specific service accounts (not Everyone)
|
|
2. **Enable NTFS encryption** for sensitive data:
|
|
```powershell
|
|
cipher /e "D:\AppData\Faces"
|
|
cipher /e "D:\AppData\Storage"
|
|
```
|
|
3. **Regular backups** with retention policy
|
|
4. **Firewall rules** to restrict access to the host
|
|
5. **Audit logging** for file access:
|
|
```powershell
|
|
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
|
|
|