4.0 KiB
Source: https://dockhand.pro/
Deploy
Must have Docker installed: https://wiki.gabesville.com/books/docker/page/install-docker
Run the docker command to install and run Dockhand:
sudo docker run -d -p 3000:3000 --name dockhand --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v /srv/docker/dockhand/dockhand_data:/app/data fnsys/dockhand:latest
Go to http://IPADDRESS:3000 to access
If firewall(UFW) is enabled you may need to allow port 3000 (test first before creating the rule)
Updating
- CD to location you want the update script created
sudo nano update-dockhand.sh- Copypasta into file:
sudo docker stop dockhand
sleep 10s
sudo docker rm dockhand
sudo docker image rm -f fnsys/dockhand:latest
sleep 10s
sudo docker run -d -p 3000:3000 --name dockhand --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v /srv/docker/dockhand/dockhand_data:/app/data fnsys/dockhand:latest
sudo chmod u+x update-dockhand.sh- to run:
bash update-dockhand.sh
How variables and secrets are handled:
This document summarizes how environment variables and secrets behave when using Dockerhand to deploy a stack from a compose.yaml and .env file.
Mental Model
Dockerhand has two different injection mechanisms:
| Type | When injected | Usable in ${VAR} |
Available in container |
|---|---|---|---|
| Variables | Before docker compose |
✅ Yes | ✅ Yes |
| Secrets | At container runtime | ❌ No | ✅ Yes |
Key takeaway:
Dockerhand secrets do not participate in Docker Compose variable interpolation.
.env File Usage
Use .env for:
- Non-secret defaults
- Local development
- Structural configuration
Example:
DB_USERNAME=postgres
DB_HOSTNAME=database
DB_PORT=5432
DB_DATABASE_NAME=immich
IMMICH_VERSION=release
UPLOAD_LOCATION=/mnt/media
⚠️ Do not rely on .env for secrets in production.
❌ What Does NOT Work (Common Pitfall)
This fails when DB_PASSWORD is marked as a secret in Dockerhand:
environment:
DB_PASSWORD: ${DB_PASSWORD}
Reason:
Secrets are injected after Compose parsing
${DB_PASSWORD} resolves to empty
✅ Correct Pattern for Dockerhand Secrets
Rule
Never interpolate secrets with ${VAR}.
Declare the variable name only.
compose.yaml (Canonical Pattern)
Application container (e.g. Immich)
services:
immich-server:
env_file:
- .env
environment:
DB_USERNAME:
DB_PASSWORD:
DB_HOSTNAME:
DB_PORT:
DB_DATABASE_NAME:
Database container (Postgres)
services:
database:
environment:
POSTGRES_USER:
POSTGRES_PASSWORD:
Dockerhand Configuration
Variables (non-secret)
DB_USERNAME=postgres
POSTGRES_USER=postgres
Secrets
DB_PASSWORD=********
POSTGRES_PASSWORD=********
✔ Secrets are injected by name
✔ Containers receive them at runtime
✔ No ${VAR} expansion involved
Why This Works
Compose does not attempt interpolation
Dockerhand injects secrets directly into container environments
Applications read expected variables normally
No accidental empty passwords
No secret leakage via docker inspect
Postgres-Specific Notes
POSTGRES_PASSWORD is only used on initial DB creation
Existing volumes require password changes via:
ALTER USER postgres WITH PASSWORD 'newpassword';
Authentication failures can be misleading when the app receives an empty password
Debugging Checklist
If authentication fails:
Confirm secret is not interpolated (${VAR})
Confirm variable name matches what the app expects
Check inside container:
env | grep PASSWORD
Check Postgres logs for auth method (scram-sha-256)
TL;DR
.env = defaults & structure
Dockerhand variables = safe overrides
Dockerhand secrets = runtime injection only
Never use ${VAR} for secrets
Declare env var names and let Dockerhand fill them
Final Rule to Remember
If it’s marked as a secret in Dockerhand,
Compose must never try to expand it.