Deploying Dockhand: A Detailed Technical Guide
Dockhand is a modern, intuitive Docker management tool for handling containers, stacks, updates, logs, and multi-host environments. It’s source-available under BSL 1.1 (Business Source License), with full code on GitHub (GitHub - Finsys/dockhand: Dockhand - Docker management you will like.). This guide focuses on deployment, drawing from official documentation and best practices. It’s designed for technical users, emphasizing security, configuration, and scalability. Assume a Linux host unless noted.
Prerequisites
- Docker Engine: Version 20.10 or later (API 1.41+).
- Hardware: Minimum 512 MB RAM (1 GB recommended for production).
- Browser: Latest Chrome, Firefox, Safari, or Edge.
- Database: SQLite (default, embedded) or PostgreSQL 14+ for larger setups.
- Permissions: Dockhand requires Docker socket access for management. Run as non-root where possible.
- Network: For remote hosts, ensure firewall allows necessary ports (e.g., 2375/2376 for TCP, or use agents).
- Security Note: Dockhand has privileged access to Docker. Always enable authentication immediately after launch to mitigate risks. Use reverse proxies for external exposure.
Verify Docker installation:
docker --version
Quick Start: Basic Deployment
For a single-host setup, use Docker or Docker Compose. This mounts the Docker socket for control and persists data.
Using Docker (Simple Run)
Pull and run the latest image:
docker run -d \
--name dockhand \
--restart unless-stopped \
-p 3000:3000 \
-v /var/run/docker.sock:/var/run/docker.sock \
-v dockhand_data:/app/data \
fnsys/dockhand:latest
- Access at
http://localhost:3000. - The
-v dockhand_data:/app/datauses a named volume for persistence (SQLite DB, configs).
Using Docker with Custom Data Directory (Bind Mount)
For relative paths in Compose files (e.g., ./config.yml), match host and container paths:
mkdir -p /opt/dockhand
docker run -d \
--name dockhand \
--restart unless-stopped \
-p 3000:3000 \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /opt/dockhand:/opt/dockhand \
-e DATA_DIR=/opt/dockhand \
fnsys/dockhand:latest
DATA_DIRenv var sets the internal data path.
Using Docker Compose
Create docker-compose.yml:
services:
dockhand:
image: fnsys/dockhand:latest
container_name: dockhand
restart: unless-stopped
ports:
- "3000:3000"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- dockhand_data:/app/data
volumes:
dockhand_data:
Run:
docker compose up -d
First-Time Setup and Security
- Access the UI: Open
http://<host-ip>:3000. Authentication is disabled initially. - Enable Authentication:
- Navigate to Settings > Authentication.
- Create an admin user (strong password required).
- Toggle authentication ON.
- Refresh the page; you’ll be prompted to log in.
- Add Environment:
- Go to Settings > Environments > Add Environment.
- Name it (e.g., “production”).
- Set connection type to “Unix socket” for local host.
- Save and test connection.
- Security Best Practices:
- Immediate Auth: Never leave auth disabled; Dockhand controls all containers.
- Reverse Proxy: Expose via HTTPS only (see examples below).
- Socket Permissions: Avoid
chmod 666 /var/run/docker.sock(high risk). - Vulnerability Scanning: Enable Grype/Trivy in Settings > Environment > Security for image scans on pulls/updates.
- No Telemetry: Verified source-available; no phoning home.
- Hardened Image: Built minimally (no unnecessary deps); audit via GitHub.
Handling Docker Socket Permissions
Dockhand runs as non-root by default but needs socket access. Choose an option based on security needs.
| Option | Description | Pros | Cons | When to Use |
|---|---|---|---|---|
| Match Docker GID | Add container to host’s Docker group. | Simple, non-root. | Requires knowing GID. | Standard Linux setups. |
| Run as Root | Use --user 0:0. |
Easy access. | Elevated privileges. | Quick tests. |
| PUID/PGID | Set env vars for custom UID/GID. | Matches host user. | Setup overhead. | Production with specific users. |
| User Directive | -u <uid>:<gid>. |
Precise control. | Bind mounts only (no named volumes). | Advanced, chown data dir first. |
| Socket Proxy | Use tecnativa/docker-socket-proxy. |
Isolated access. | Extra container. | High-security environments. |
Example: Match Docker GID
Find GID:
stat -c '%g' /var/run/docker.sock # e.g., 999
Docker Compose:
services:
dockhand:
# ... other config
group_add:
- "999"
Example: Socket Proxy (Most Secure)
docker-compose.yml:
services:
socket-proxy:
image: tecnativa/docker-socket-proxy
restart: unless-stopped
environment:
CONTAINERS: 1
IMAGES: 1
NETWORKS: 1
VOLUMES: 1
EVENTS: 1
POST: 1
DELETE: 1
INFO: 1
SYSTEM: 1
ALLOW_START: 1
ALLOW_STOP: 1
ALLOW_RESTARTS: 1
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
networks:
- socket-proxy
dockhand:
image: fnsys/dockhand:latest
restart: unless-stopped
depends_on:
- socket-proxy
ports:
- "3000:3000"
volumes:
- dockhand_data:/app/data
networks:
- socket-proxy
networks:
socket-proxy:
internal: true
volumes:
dockhand_data:
In Dockhand UI: Set environment host to socket-proxy:2375.
Advanced Configuration
Using PostgreSQL (for Scalability)
Env var for connection:
-e DATABASE_URL=postgres://user:pass@host:5432/dockhand
Full Docker example:
docker run -d \
--name dockhand \
-p 3000:3000 \
-e DATABASE_URL=postgres://user:pass@postgres-host:5432/dockhand \
-v /var/run/docker.sock:/var/run/docker.sock \
-v dockhand_data:/app/data \
fnsys/dockhand:latest
Note: No auto-migration from SQLite; backup and import manually if switching.
Moving Data Directory
Stop, copy, restart:
docker stop dockhand
mkdir -p /opt/dockhand
docker run --rm -v dockhand_data:/source:ro -v /opt/dockhand:/target busybox cp -a /source/. /target/
docker rm dockhand
# Restart with new bind mount and DATA_DIR
docker volume rm dockhand_data # Optional
Multi-Host Deployment
For remote hosts, use Hawser Agent (included tool for secure connections).
Install Hawser Agent on Remote Host
Linux script:
curl -fsSL https://raw.githubusercontent.com/Finsys/hawser/main/scripts/install.sh | bash
Docker:
docker run -d \
--name hawser \
--restart unless-stopped \
-v /var/run/docker.sock:/var/run/docker.sock \
-e HAWSER_TOKEN=your_secure_token \
fnsys/hawser:latest
In Dockhand UI:
- Settings > Environments > Add.
- Type: Hawser Standard (LAN) or Edge (NAT/VPS).
- Enter remote IP/token.
- Test connection (WiFi-like icon).
| Type | Connectivity | Security |
|---|---|---|
| Hawser Standard | Inbound to agent. | TLS optional. |
| Hawser Edge | Outbound only (agent calls home). | Ideal for firewalled hosts. |
| Direct TCP | Exposed Docker API. | Use TLS (2376). |
Reverse Proxy Examples
Always proxy for HTTPS/WebSockets (required for terminals/logs).
Nginx
/etc/nginx/sites-enabled/dockhand.conf:
server {
listen 443 ssl;
server_name dockhand.example.com;
ssl_certificate /path/to/cert.crt;
ssl_certificate_key /path/to/key.key;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
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;
}
}
Reload: nginx -s reload.
Traefik (Docker Compose Labels)
Add to Dockhand service:
labels:
- "traefik.enable=true"
- "traefik.http.routers.dockhand.rule=Host(`dockhand.example.com`)"
- "traefik.http.routers.dockhand.entrypoints=websecure"
- "traefik.http.routers.dockhand.tls.certresolver=letsencrypt"
- "traefik.http.services.dockhand.loadbalancer.server.port=3000"
Troubleshooting
- Socket Errors: Check GID/group_add; use proxy if persistent.
- Updates: Enable scheduled checks in Settings > Environment > Updates.
- Logs: UI logs searchable; download via UI.
- Vulnerabilities: Scans run automatically; review in container details.
- Enterprise Features: RBAC, LDAP, audits require paid license ($499+/host/year).
For updates: docker pull fnsys/dockhand:latest && docker compose up -d. Monitor GitHub for releases (BSL → Apache in 2029 per roadmap).
This setup provides a secure, scalable Dockhand deployment. Test in a VM first for production. Refer to Dockhand User Manual for UI usage.