Problem: CapRover's serviceUpdateOverride in captain-definition doesn't always apply automatically, causing "Docker socket NOT found" errors. Solution: Manual docker service update command to apply the mount. Changes: - Added CAPROVER_TROUBLESHOOTING.md with complete step-by-step fix - Manual docker service update command - Verification steps - Common issues and solutions - SELinux/AppArmor troubleshooting - Created fix-caprover-docker-mount.sh automated script - Finds service automatically - Applies mount - Verifies configuration - Shows service status - Enhanced backend/app.py diagnostics - Lists /var/run directory contents - Shows Docker-related files - Better error messages explaining the issue - Explicit note when mount is missing - Updated backend/requirements.txt - Docker SDK 7.0.0 -> 7.1.0 (fixes URL scheme error) - Updated CAPROVER_DEPLOYMENT.md - Prominent warning about serviceUpdateOverride limitation - New Step 4: Verify and Apply Docker Socket Mount - Quick fix command prominently displayed - Links to troubleshooting guide - Updated troubleshooting section with manual fix - Updated QUICKSTART.md - Warning after backend deployment instructions - Quick fix command for both deployment options - Links to troubleshooting guide This provides users with immediate solutions when encountering the "Cannot connect to Docker" error, which is now properly diagnosed and can be fixed with a single command. https://claude.ai/code/session_01NfGGGQ9Zn6ue7PRZpAoB2N
12 KiB
CapRover Deployment Guide
This guide provides comprehensive instructions for deploying the Docker Swarm Terminal application on CapRover.
Overview
CapRover uses Docker Swarm under the hood, which affects how containers interact with the Docker daemon. This application requires access to the Docker socket to manage containers.
Architecture
- Frontend: Next.js application (deployed separately)
- Backend: Flask API that requires Docker socket access
Backend Deployment (Critical Configuration)
Understanding the Docker Socket Issue
The backend needs to access the Docker daemon to list and manage containers. In a Docker Swarm environment (which CapRover uses), containers don't automatically have access to the Docker socket. This requires special configuration.
Captain Definition Configuration
The backend/captain-definition file contains critical configuration:
{
"schemaVersion": 2,
"dockerfilePath": "./Dockerfile",
"serviceUpdateOverride": {
"TaskTemplate": {
"ContainerSpec": {
"Mounts": [
{
"Type": "bind",
"Source": "/var/run/docker.sock",
"Target": "/var/run/docker.sock",
"ReadOnly": false
}
],
"User": "root",
"Env": [
"DOCKER_HOST=unix:///var/run/docker.sock"
]
},
"RestartPolicy": {
"Condition": "any",
"Delay": 5000000000,
"MaxAttempts": 0
}
},
"Mode": {
"Replicated": {
"Replicas": 1
}
}
}
}
Key Configuration Elements:
-
Mounts: Binds the host's Docker socket into the container
Source:/var/run/docker.sock(host socket)Target:/var/run/docker.sock(container socket)ReadOnly:false(allows write operations)
-
User: Set to
rootto ensure socket access permissions -
Environment Variables: Sets
DOCKER_HOSTto explicitly point to the socket -
RestartPolicy: Ensures the service recovers from failures
-
Replicas: Set to 1 (multiple replicas can't share the same socket)
⚠️ IMPORTANT: serviceUpdateOverride Limitation
The serviceUpdateOverride in captain-definition may not be applied automatically by CapRover. This is a known limitation with some CapRover versions.
If you see "Docker socket NOT found" in your logs, you MUST manually apply the Docker socket mount after deployment.
Quick Fix (run on your CapRover server):
# SSH into your CapRover server
ssh root@your-server.com
# Apply the mount (replace with your service name)
docker service update \
--mount-add type=bind,source=/var/run/docker.sock,target=/var/run/docker.sock \
srv-captain--terminalbackend
See CAPROVER_TROUBLESHOOTING.md for detailed instructions.
Security Considerations
IMPORTANT: Granting Docker socket access to a container is a security-sensitive operation. The container effectively has root access to the host system.
- Only use this in trusted environments
- Consider implementing additional authentication/authorization
- Monitor container logs for suspicious activity
- Restrict network access to the backend API
Step-by-Step Deployment
1. Create the Backend App in CapRover
# Login to your CapRover CLI
caprover login
# Create a new app
caprover apps:create terminalbackend
2. Configure the App
In the CapRover dashboard:
- Go to your app settings
- Enable HTTP Settings → HTTPS
- Set environment variables (if needed):
ADMIN_USERNAME(default: admin)ADMIN_PASSWORD(default: admin123)
3. Deploy the Backend
From the backend directory:
# Navigate to backend directory
cd backend
# Deploy to CapRover
caprover deploy
Or manually:
- Create a tarball:
tar -cf backend.tar . - Upload via CapRover dashboard
- Wait for deployment to complete
4. CRITICAL: Verify and Apply Docker Socket Mount
After deployment, check if the Docker socket is mounted:
a) Check Application Logs (in CapRover dashboard):
Look for:
✓ Docker socket exists at /var/run/docker.sock
✓ Docker connection verified on startup
If you see:
✗ Docker socket NOT found at /var/run/docker.sock
Then the serviceUpdateOverride wasn't applied. You must manually apply it.
b) Manually Apply the Mount (run on your CapRover server):
# SSH into your CapRover server
ssh root@your-server.com
# Find your service name
docker service ls | grep terminalbackend
# Should show something like: srv-captain--terminalbackend
# Apply the Docker socket mount
docker service update \
--mount-add type=bind,source=/var/run/docker.sock,target=/var/run/docker.sock \
srv-captain--terminalbackend
c) Verify the Mount Was Applied:
docker service inspect srv-captain--terminalbackend \
--format '{{json .Spec.TaskTemplate.ContainerSpec.Mounts}}' | python3 -m json.tool
Should show:
[
{
"Type": "bind",
"Source": "/var/run/docker.sock",
"Target": "/var/run/docker.sock"
}
]
d) Wait for Service Restart:
The service will automatically restart with the new configuration. Monitor:
docker service ps srv-captain--terminalbackend
e) Check Logs Again:
In CapRover dashboard, refresh the logs. You should now see:
✓ Docker socket exists at /var/run/docker.sock
✓ Docker connection verified on startup
See CAPROVER_TROUBLESHOOTING.md for detailed troubleshooting.
5. Test the API
# Health check
curl https://terminalbackend.wardcrew.com/api/health
# Login
curl -X POST https://terminalbackend.wardcrew.com/api/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"admin123"}'
# List containers (replace TOKEN with the token from login response)
curl https://terminalbackend.wardcrew.com/api/containers \
-H "Authorization: Bearer TOKEN"
Frontend Deployment
The frontend is a standard Next.js application and doesn't require Docker socket access.
Captain Definition
{
"schemaVersion": 2,
"dockerfilePath": "./Dockerfile"
}
Environment Variables
Set these in the CapRover dashboard:
NEXT_PUBLIC_API_URL: Your backend URL (e.g.,https://terminalbackend.wardcrew.com)
Deployment Steps
cd frontend
caprover deploy
Troubleshooting
"Cannot connect to Docker" Error
This is the most common issue! CapRover's serviceUpdateOverride often doesn't apply automatically.
Quick Fix (Run on CapRover Server)
# SSH into your CapRover server
ssh root@your-server.com
# Apply the Docker socket mount manually
docker service update \
--mount-add type=bind,source=/var/run/docker.sock,target=/var/run/docker.sock \
srv-captain--terminalbackend
# Verify it worked
docker service inspect srv-captain--terminalbackend \
--format '{{json .Spec.TaskTemplate.ContainerSpec.Mounts}}' | python3 -m json.tool
📖 See CAPROVER_TROUBLESHOOTING.md for complete step-by-step instructions.
Diagnostic Checklist
If the quick fix doesn't work, check:
-
Check logs in CapRover dashboard for:
✗ Docker socket NOT found at /var/run/docker.sock -
Verify socket exists on host:
ls -la /var/run/docker.sock -
Check service is running as root:
docker service inspect srv-captain--terminalbackend \ --format '{{.Spec.TaskTemplate.ContainerSpec.User}}'Should return:
root -
Check Docker version compatibility:
docker version -
Review SELinux/AppArmor if on RHEL/Ubuntu:
getenforce # Should be Permissive or Disabled for testing
Common Issues
Socket not found:
- ✅ Solution: Manually apply mount (see Quick Fix above)
- The
serviceUpdateOverridewasn't applied by CapRover
Permission denied:
- ✅ Solution: Ensure service runs as root:
docker service update --user root srv-captain--terminalbackend
Connection refused / "Not supported URL scheme http+docker":
- ✅ Solution: Update docker library version in
requirements.txttodocker==7.1.0 - Redeploy the application
Viewing Logs
In CapRover dashboard:
- Go to your app
- Click "App Logs"
- Look for diagnostic output
Or via CLI:
caprover logs terminalbackend
Force Redeploy
Sometimes CapRover needs a fresh deployment:
- Delete the app in CapRover dashboard
- Recreate it
- Deploy again
Or update the app version:
# Add a label or update Dockerfile
# Then redeploy
caprover deploy
Testing Docker Access Manually
SSH into the CapRover server and run:
# Find your container
docker ps | grep terminalbackend
# Execute into the container
docker exec -it <container_id> bash
# Inside container, test Docker access
python3 << EOF
import docker
client = docker.from_env()
print(client.ping())
print(client.containers.list())
EOF
Advanced Configuration
Restricting Container Access
To limit which containers the backend can see/manage, you could:
- Use Docker socket proxy (like tecnativa/docker-socket-proxy)
- Filter containers by label in the backend code
- Implement RBAC in the backend API
High Availability
For production:
- This configuration only supports 1 replica (Docker socket can't be shared)
- For HA, consider using Docker Swarm API directly instead of socket
- Or deploy backend on a dedicated manager node
Monitoring
Add health checks and monitoring:
"HealthCheck": {
"Test": ["CMD", "curl", "-f", "http://localhost:5000/api/health"],
"Interval": 30000000000,
"Timeout": 10000000000,
"Retries": 3
}
Complete Architecture Diagram
┌─────────────────────────────────────────────────┐
│ CapRover (Docker Swarm) │
│ │
│ ┌──────────────────┐ ┌─────────────────┐ │
│ │ Frontend │ │ Backend │ │
│ │ (Next.js) │─────▶│ (Flask) │ │
│ │ │ API │ │ │
│ └──────────────────┘ │ /var/run/ │ │
│ │ docker.sock │ │
│ │ (mounted) │ │
│ └────────┬────────┘ │
│ │ │
│ ┌────────▼────────┐ │
│ │ Docker Daemon │ │
│ │ (Host) │ │
│ └─────────────────┘ │
└─────────────────────────────────────────────────┘
References
Support
If you continue to experience issues:
- Check the application logs (detailed diagnostics are now included)
- Verify your CapRover version is up to date
- Ensure Docker is running properly on the host
- Review CapRover firewall/network settings