Skip to content

Dockhand Stack Management

This guide covers how to properly manage Docker Compose stacks with Dockhand to ensure all containers are tracked and manageable through the Dockhand interface.

Table of Contents


Overview

Key Principle: All stack compose files should be located in /home/jeff/docker/[stack-name]/ for Dockhand to properly manage them.

Dockhand has two types of stacks:

  • Internal Stacks: Fully managed by Dockhand with known compose file locations
  • Untracked Stacks: Running stacks that Dockhand detects but doesn't know where the compose files are located

Our goal is to have all stacks as Internal stacks for full management capabilities.

Note on Container Updates: This documentation reflects that Internal stacks should be safe to update via the Containers tab because Dockhand knows the compose file location and can reference the full configuration. This is based on experience with similar tools (Portainer, Dockge) and the difference between Internal vs. Untracked stacks. The guidance will be validated through real-world testing and updated if needed.


Prerequisites

Dockhand Configuration

Ensure Dockhand has access to your docker directory. Your Dockhand compose.yml should include:

services:
  dockhand:
    image: fnsys/dockhand:latest
    container_name: dockhand
    restart: unless-stopped
    ports:
      - 3003:3000
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - ./dockhand_data:/app/data
      - /home/jeff/docker:/home/jeff/docker  # Critical mount

Never adopt Dockhand's own stack into Dockhand. Manage Dockhand via Dockge or CLI only.


Adopting Existing Stacks into Dockhand

Scenario 1: Stack Already in /home/jeff/docker

If your stack is already located in /home/jeff/docker/[stack-name]/:

  1. Stop the running stack (important - prevents conflicts):
cd /home/jeff/docker/[stack-name]
docker compose down
  1. Adopt in Dockhand:
  2. Navigate to Stacks → Adopt
  3. Browse to /home/jeff/docker/[stack-name]
  4. Click on the docker-compose.yaml (or compose.yaml) file
  5. Click Adopt
  6. Dockhand will automatically deploy the stack
  7. Verify Success:
  8. Stack should show as Internal in the Source column
  9. Location should show: /home/jeff/docker/[stack-name]/docker-compose.yaml
  10. Status should be running

Scenario 2: Stack Located Elsewhere (e.g., /opt/[stack-name])

If your stack is outside /home/jeff/docker:

  1. Stop the running stack:
cd /opt/[stack-name]  # or wherever it's located
docker compose down
  1. Move the stack to the standard location:
sudo mv /opt/[stack-name] /home/jeff/docker/
sudo chown -R jeff:jeff /home/jeff/docker/[stack-name]
  1. Adopt in Dockhand (follow Scenario 1 steps above)

Scenario 3: Standalone Containers (Not Compose)

If containers were created with docker run commands (showing as Untracked):

  1. Document the current configuration:
docker inspect [container-name] > /tmp/[container-name]-config.json
  1. Create a compose file:
mkdir -p /home/jeff/docker/[stack-name]
cd /home/jeff/docker/[stack-name]
nano docker-compose.yaml
  1. Recreate as compose using the inspect output for reference
  2. Stop the old container:
docker stop [container-name]
docker rm [container-name]
  1. Adopt the new compose file (follow Scenario 1)

Creating New Stacks

Never create stacks directly in Dockhand's UI. This creates them in Dockhand's internal directory structure, making them harder to manage outside of Dockhand.

  1. Create the directory structure:
mkdir -p /home/jeff/docker/[new-stack-name]
cd /home/jeff/docker/[new-stack-name]
  1. Create the docker-compose.yaml file:
nano docker-compose.yaml

Example structure:

services:
  app:
    image: someapp:latest
    container_name: [stack-name]
    ports:
      - "8080:80"
    volumes:
      - ./data:/data
    environment:
      - VARIABLE=value
    restart: unless-stopped
  1. Create .env file for sensitive data (optional but recommended):
nano .env

Example:

# Application Configuration
DATABASE_PASSWORD=your-secure-password
API_KEY=your-api-key
  1. Do NOT start the stack yet:
# DO NOT RUN: docker compose up -d
  1. Adopt into Dockhand:
  2. Navigate to Stacks → Adopt
  3. Browse to /home/jeff/docker/[new-stack-name]
  4. Click on docker-compose.yaml
  5. Click Adopt
  6. Dockhand will deploy the stack automatically
  7. Verify:
  8. Check that stack shows as Internal
  9. Verify containers are running
  10. Test the application

Alternative: Edit After Adopting

If you prefer to use Dockhand's editor:

  1. Create the directory and minimal compose file as above
  2. Adopt into Dockhand (it will fail to start due to incomplete config)
  3. Click on the stack → Edit
  4. Complete the configuration in Dockhand's editor
  5. Click Save & redeploy

Updating Stacks

Understanding Update Safety

The safety of updating from the Containers tab depends on whether your stack is Internal or Untracked:

Stack Type Containers Tab Update Why
Internal ✅ Likely Safe Dockhand knows the compose file location and can reference the full configuration
Untracked ❌ Not Safe Dockhand doesn't know where the compose file is and can only use Docker's stored config

Update Methods

Method 1: Containers Tab (For Internal Stacks)

Once your stacks are adopted as "Internal", updating from the Containers tab should preserve all configuration:

  1. Navigate to Containers tab
  2. Click Check for updates
  3. Update individual containers or Update all

What gets preserved:

  • Environment variables (from compose file and .env)
  • Volume mounts
  • Network configurations
  • Port mappings
  • Dependencies

Important: This method is ONLY recommended for stacks showing as "Internal" in the Stacks tab. Never use this for "Untracked" stacks.

Method 2: CLI Update (Always Safe)

This method works for both Internal and Untracked stacks:

cd /home/jeff/docker/[stack-name]
docker compose pull
docker compose up -d

Benefits:

  • Guaranteed to use compose file configuration
  • Works regardless of Internal/Untracked status
  • Full control over the update process

Method 3: Edit and Redeploy in Dockhand

For Internal stacks in Dockhand:

  1. Stacks → Click on stack → Edit
  2. Modify if needed (or just trigger a redeploy)
  3. Click Save & redeploy

Note: This method requires a change in the compose file to trigger an image pull. Simply clicking "Save & redeploy" without changes may not pull new images.

Configure automatic updates at the stack level:

  1. Stacks → Click on stack
  2. Look for Settings or Auto-update tab
  3. Enable Auto-update
  4. Configure schedule (daily/weekly/custom cron)
  5. Set vulnerability criteria if using scanning
  6. Save

Verification After Updates

After updating any stack (especially the first few times using Containers tab), verify configuration is intact:

# Check environment variables
docker inspect [container-name] | grep -A 30 "Env"

# Check volume mounts
docker inspect [container-name] | grep -A 10 "Mounts"

# Check networks
docker inspect [container-name] | grep -A 5 "Networks"

# Test the application
# Access the web UI or API to ensure it works correctly

Critical Rules for Updates

✅ SAFE Methods:

For Internal Stacks:

  • Containers tab updates (Check for updates → Update)
  • CLI: docker compose pull && docker compose up -d
  • Stacks tab: Edit → Save & redeploy
  • Enable auto-updates at stack level

For Untracked Stacks:

  • CLI: docker compose pull && docker compose up -d (ONLY safe method)
  • Adopt the stack first, then use any method above

❌ UNSAFE Methods:

Never do this for Untracked stacks:

  • Containers → Check for updates → Update
  • Containers → Update all

Why Untracked Updates Fail: When a stack is Untracked, Dockhand cannot reference the compose file. Updates use only Docker's stored container configuration, which may be incomplete and can lose:

  • Environment variables from .env files
  • Custom network configurations
  • Dependency relationships
  • Volume mount details

Example of what can go wrong: Updating an Untracked n8n stack lost the N8N_ENCRYPTION_KEY environment variable, breaking MFA and requiring database repairs.

Update Workflow Recommendation

First-time setup (for each stack):

  1. Ensure stack is adopted as "Internal"
  2. Perform first update using CLI method
  3. Verify all configuration is preserved
  4. Once confirmed working, you can use Containers tab for future updates

Ongoing updates:

  • Use Containers tab for routine updates (after verifying it works for your setup)
  • Use CLI for critical stacks or when you want absolute certainty
  • Consider enabling auto-updates for non-critical stacks

Important Rules

✅ DO:

  • Create all stack compose files in /home/jeff/docker/[stack-name]/
  • Adopt stacks into Dockhand before starting them
  • Verify stacks show as "Internal" in the Stacks tab
  • Update Internal stacks via Containers tab OR CLI (both should work)
  • Update Untracked stacks ONLY via CLI
  • Use .env files for sensitive configuration
  • Keep compose files version-controlled (git)

❌ DON'T:

  • Create stacks directly in Dockhand's UI (creates them in internal directories)
  • Update Untracked stacks from the Containers tab
  • Adopt Dockhand's own stack into Dockhand
  • Edit running containers directly without updating the compose file
  • Use docker run for new containers (use compose instead)

Update Safety by Stack Type

Stack Status Containers Tab CLI Stacks Tab Auto-Update
Internal ✅ Safe* ✅ Safe ✅ Safe ✅ Safe
Untracked ❌ Unsafe ✅ Safe ❌ N/A ❌ N/A

*After verifying it works correctly for your environment. Test carefully the first few times.

Stack Naming Conventions

  • Use lowercase with hyphens: my-app-name
  • Be descriptive: jellyfin not media
  • Match the directory name to stack name for clarity

Directory Structure Example

/home/jeff/docker/
├── dockhand/
│   ├── compose.yml
│   └── dockhand_data/
├── n8n/
│   ├── docker-compose.yaml
│   └── .env
├── jellyfin/
│   ├── docker-compose.yaml
│   └── config/
├── seafile/
│   ├── docker-compose.yaml
│   ├── .env
│   ├── seafile-data/
│   └── mysql/
└── [new-stack]/
    ├── docker-compose.yaml
    └── .env

Troubleshooting

Stack Shows as "Untracked"

Problem: Stack is running but shows as "Untracked" in Dockhand

Solution:

  1. Stop the stack: docker compose down
  2. Adopt the compose file via Stacks → Adopt
  3. Dockhand will deploy and track it

"Stack directory not found" Error During Adoption

Problem: Adoption fails with directory error

Solutions:

  • Verify the compose file exists at the path
  • Check Dockhand has the volume mount: /home/jeff/docker:/home/jeff/docker
  • Restart Dockhand: docker restart dockhand
  • Check directory permissions: ls -la /home/jeff/docker/[stack-name]

Can't See /home/jeff/docker in Adopt Browser

Problem: Adopt browser doesn't show your docker directory

Solution: Check Dockhand's compose file includes the volume mount:

volumes:
  - /home/jeff/docker:/home/jeff/docker

Restart Dockhand if you just added it:

cd /home/jeff/docker/dockhand
docker compose down
docker compose up -d

Encryption Key Mismatch (n8n, etc.)

Problem: After updating, apps like n8n show encryption key errors or MFA failures

Cause: Updated an Untracked stack via Containers tab instead of adopting it first

Prevention:

  1. Adopt all stacks as "Internal" before updating
  2. For Internal stacks, Containers tab updates should preserve configuration
  3. For critical stacks with encryption keys, consider using CLI updates for extra safety

Recovery:

  1. Fix the compose file to include correct environment variables
  2. Redeploy from Stacks tab or CLI
  3. May need to disable/reset features like MFA (database recovery may be required)

Lost Configuration After Update

Problem: Container lost environment variables, volumes, or settings after update

Cause: Updated an Untracked stack via Containers tab

Solution:

  1. Adopt the stack as Internal first
  2. Check the compose file has all configuration
  3. Redeploy via Stacks → Edit → Save & redeploy or CLI

Prevention: Only update from Containers tab after stack is adopted as "Internal"


Quick Reference Commands

# Create new stack structure
mkdir -p /home/jeff/docker/[stack-name]
cd /home/jeff/docker/[stack-name]
nano docker-compose.yaml
# Then adopt via Dockhand UI

# Move existing stack to standard location
sudo mv /path/to/stack /home/jeff/docker/[stack-name]
sudo chown -R jeff:jeff /home/jeff/docker/[stack-name]
cd /home/jeff/docker/[stack-name]
docker compose down
# Then adopt via Dockhand UI

# Update stack via CLI (always safe)
cd /home/jeff/docker/[stack-name]
docker compose pull
docker compose up -d

# Update via Containers tab (for Internal stacks)
# Navigate to Containers → Check for updates → Update
# Verify afterwards with commands below

# Verify configuration after update
docker inspect [container-name] | grep -A 30 "Env"
docker inspect [container-name] | grep -A 10 "Mounts"
docker inspect [container-name] | grep -A 5 "Networks"

# Check stack status
docker compose ps
docker compose logs -f

# View all stacks
ls -la /home/jeff/docker/

# Restart Dockhand
cd /home/jeff/docker/dockhand
docker compose restart

Additional Resources

  • Dockhand Documentation: https://dockhand.pro/manual/
  • Docker Compose Reference: https://docs.docker.com/compose/
  • Your Dockhand Instance: http://your-server:3003

Last Updated: February 14, 2026