You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This Docker Compose configuration sets up **Dockhand** with a Tailscale sidecar container, enabling secure access to your self-hosted Docker management interface over your private Tailscale network. With this setup, your Dockhand instance remains private and accessible only from authorized devices on your Tailnet, ensuring that container management and infrastructure controls are never exposed to the public internet.
4
+
5
+
## Dockhand
6
+
7
+
[**Dockhand**](https://github.com/Finsys/dockhand) is a modern, lightweight Docker management UI focused on real-time container operations and multi-environment orchestration. It provides an intuitive interface for managing containers, images, volumes, networks, and Docker Compose stacks across local or remote Docker hosts.
8
+
9
+
Dockhand is designed for operators and homelab environments that want a clean, responsive alternative to heavier container management platforms, while still retaining full control over their infrastructure.
10
+
11
+
## Key Features
12
+
13
+
- Container Management – Start, stop, restart, and inspect containers in real time.
14
+
- Compose Stack Support – Deploy and manage Docker Compose applications.
15
+
- Multi-Environment Support – Connect to and manage multiple Docker hosts.
16
+
- Live Logs & Terminal – Stream logs and access container terminals directly from the UI.
- Git-Based Deployments – Deploy stacks from Git repositories with optional sync.
19
+
- Docker-Native – Built specifically for Docker environments.
20
+
- Open Source – Community-driven and self-hostable.
21
+
22
+
## Why Self-Host?
23
+
24
+
A Docker management interface has full control over your infrastructure. Exposing such a tool publicly significantly increases risk, as it can allow attackers to manipulate containers, access secrets, or pivot deeper into your network.
25
+
26
+
Self-hosting Dockhand ensures that you maintain full ownership and operational control. When combined with Tailscale, Dockhand becomes a secure, private control plane for your Docker environments, accessible only from authenticated devices within your Tailnet. This dramatically reduces the attack surface while preserving remote management convenience.
27
+
28
+
## Configuration Overview
29
+
30
+
In this deployment, a Tailscale sidecar container (for example `tailscale-dockhand`) runs the Tailscale client and joins your private Tailscale network. The main `dockhand` service uses:
31
+
32
+
```plain
33
+
network_mode: service:tailscale-dockhand
34
+
```
35
+
36
+
This configuration routes all inbound and outbound traffic through the Tailscale interface, ensuring that the Dockhand web interface and Docker API interactions are accessible only via your Tailscale network.
37
+
38
+
By avoiding public port mappings and relying exclusively on Tailnet access, you create a secure-by-default Docker management setup suitable for homelabs, remote infrastructure, and internal DevOps environments.
# Make sure you have updated/checked the .env file with the correct variables.
12
+
# All the ${ xx } need to be defined there.
13
+
# Tailscale Sidecar Configuration
14
+
tailscale:
15
+
image: tailscale/tailscale:latest # Image to be used
16
+
container_name: tailscale-${SERVICE} # Name for local container management
17
+
hostname: ${SERVICE} # Name used within your Tailscale environment
18
+
environment:
19
+
- TS_AUTHKEY=${TS_AUTHKEY}
20
+
- TS_STATE_DIR=/var/lib/tailscale
21
+
- TS_SERVE_CONFIG=/config/serve.json # Tailscale Serve configuration to expose the web interface on your local Tailnet - remove this line if not required
- TS_LOCAL_ADDR_PORT=127.0.0.1:41234 # The <addr>:<port> for the healthz endpoint
25
+
#- TS_ACCEPT_DNS=true # Uncomment when using MagicDNS
26
+
- TS_AUTH_ONCE=true
27
+
configs:
28
+
- source: ts-serve
29
+
target: /config/serve.json
30
+
volumes:
31
+
- ./config:/config # Config folder used to store Tailscale files - you may need to change the path
32
+
- ./ts/state:/var/lib/tailscale # Tailscale requirement - you may need to change the path
33
+
devices:
34
+
- /dev/net/tun:/dev/net/tun # Network configuration for Tailscale to work
35
+
cap_add:
36
+
- net_admin # Tailscale requirement
37
+
#ports:
38
+
# - 0.0.0.0:${SERVICEPORT}:${SERVICEPORT} # Binding port ${SERVICEPORT} to the local network - may be removed if only exposure to your Tailnet is required
39
+
# If any DNS issues arise, use your preferred DNS provider by uncommenting the config below
40
+
# dns:
41
+
# - ${DNS_SERVER}
42
+
healthcheck:
43
+
test: ["CMD", "wget", "--spider", "-q", "http://127.0.0.1:41234/healthz"] # Check Tailscale has a Tailnet IP and is operational
44
+
interval: 1m# How often to perform the check
45
+
timeout: 10s# Time to wait for the check to succeed
46
+
retries: 3# Number of retries before marking as unhealthy
47
+
start_period: 10s# Time to wait before starting health checks
48
+
restart: always
49
+
50
+
# ${SERVICE}
51
+
application:
52
+
image: ${IMAGE_URL} # Image to be used
53
+
network_mode: service:tailscale # Sidecar configuration to route ${SERVICE} through Tailscale
54
+
container_name: app-${SERVICE} # Name for local container management
55
+
environment:
56
+
- HOST_DATA_DIR=/app/data
57
+
volumes:
58
+
- /var/run/docker.sock:/var/run/docker.sock
59
+
- ./dockhand-data:/app/data # Data directory for Dockhand - you may need to change the path
60
+
depends_on:
61
+
tailscale:
62
+
condition: service_healthy
63
+
healthcheck:
64
+
test: ["CMD", "curl", "-fsS", "http://127.0.0.1:41234/healthz"] # Check if ${SERVICE} is responding
65
+
interval: 1m# How often to perform the check
66
+
timeout: 10s# Time to wait for the check to succeed
67
+
retries: 3# Number of retries before marking as unhealthy
68
+
start_period: 30s# Time to wait before starting health checks
0 commit comments