Skip to main content

Docker Folder Structure & Naming Conventions

What this is

A standardised way to organise all Docker services, folders, and naming across my homelab.

This ensures consistency, easier troubleshooting, and simpler backups.


Why I needed this

Without structure:

  • Files end up scattered
  • Hard to find configs
  • Inconsistent naming between services
  • Backups become messy
  • Harder to migrate to another host

With structure:

  • Everything is predictable
  • Faster troubleshooting
  • Easier to rebuild or migrate
  • Cleaner integration with NAS storage

My Setup

Base directory:

/opt/docker/

Each service gets its own folder:

/opt/docker/
├── jellyfin/
├── homeassistant/
├── paperless/
├── dozzle/
├── diun/

Inside each service:

docker-compose.yml
.env
data/
config/
logs/


Key Concepts / Options

Flat vs Nested Structure

Approach Example Verdict
Flat /opt/docker/jellyfin ✅ Simple
Nested by type /opt/docker/media/jellyfin ⚠️ Can get messy

Named Volumes vs Bind Mounts

Type Example Use Case
Bind mount ./data ✅ Preferred
Named volume portainer_data Limited use

Recommendation

👉 Use a flat structure with bind mounts

Why:

  • Easier backups (rsync, NAS sync)
  • Full visibility of files
  • No hidden Docker volumes
  • Cleaner disaster recovery

Setup

1. Create Base Directory

sudo mkdir -p /opt/docker
sudo chown -R $USER:$USER /opt/docker


2. Create Service Folder

Example:

cd /opt/docker
mkdir jellyfin
cd jellyfin


3. Standard Folder Layout

mkdir -p data config logs


4. Example docker-compose.yml

version: "3.9"

services:
jellyfin:
image: jellyfin/jellyfin:latest
container_name: jellyfin
restart: unless-stopped

ports:
- "8096:8096"

volumes:
- ./config:/config
- ./data:/data
- /mnt/sjb2/media:/media

environment:
- TZ=Europe/London
- PUID=1000
- PGID=1000


Configuration

Naming Conventions

Container Names

  • Use same as folder:
jellyfin
homeassistant
paperless


Folder Names

  • Lowercase
  • No spaces
  • Match service name

Compose Files

Always:

docker-compose.yml


Environment Files

Optional:

.env


Port Conventions (Recommended)

Type Range
Web UIs 8000–8999
Admin tools 9000–9999
Custom apps 7000–7999

Permissions Notes

  • Always align container permissions:
id

Typical:

  • PUID=1000
  • PGID=1000

Fix issues:

sudo chown -R 1000:1000 /opt/docker/<service>


Verification

Check structure:

tree /opt/docker

Check running containers:

docker ps


Common Problems / Fixes

Config files missing

  • Cause: Wrong volume mapping
  • Fix:
  • Verify paths in docker-compose.yml

Data not persisting

  • Cause: Using container-only storage
  • Fix:
  • Use bind mounts (./config, ./data)

Permissions errors

  • Cause: Wrong ownership
  • Fix:
sudo chown -R 1000:1000 .


Inconsistent naming

  • Cause: Manual container creation
  • Fix:
  • Standardise folder + container names

Result

  • Clean, predictable folder structure
  • Easy backups to NAS
  • Faster troubleshooting
  • Consistent deployments across both hosts

Notes

  • Keep everything under /opt/docker
  • Avoid random folders elsewhere
  • Back up:
    • /opt/docker
    • /mnt/sjb2 (NAS data)
  • Stick to one pattern — consistency matters more than perfection
  • This structure scales easily as services grow