Filesets
Filesets keep a local directory in sync with a path inside a Docker volume. They let you manage configuration files, static assets, or seed data declaratively, without baking files into images.
Filesets follow the same pattern as stacks: discover by convention, augment with explicit config.
-
Declarative sync Define the source and target; Dockform syncs diffs only.
-
Idempotent and incremental Only changed, added, or removed files are applied.
-
Auto-discovery Filesets are found in
<context>/<stack>/volumes/directories. -
Optional service restarts Configure services to restart after files are updated.
Automatic Discovery
Dockform discovers filesets from volumes/ directories inside each stack:
my-project/
├── dockform.yml
├── default/
│ └── web/
│ ├── compose.yaml
│ └── volumes/ # ← Filesets directory
│ ├── config/ # ← Fileset "config"
│ │ └── nginx.conf
│ └── static/ # ← Fileset "static"
│ ├── index.html
│ └── styles.css
Each subdirectory of volumes/ becomes a fileset. The directory name is used as:
- The fileset name
- The target volume name (created if it doesn't exist)
Discovery Defaults
For each discovered fileset:
| Property | Default Value |
|---|---|
source |
<stack>/volumes/<fileset>/ |
target_volume |
<fileset> (same as directory name) |
target_path |
/<fileset> (root path with fileset name) |
apply_mode |
hot |
Customizing Discovery
Change the volumes directory name:
identifier: myapp
discovery:
volumes_dir: data # Look for <stack>/data/ instead of <stack>/volumes/
contexts:
default: {}
Configuring Filesets in the Manifest
Use the filesets: block inside a stack definition to override discovered defaults or declare filesets explicitly. This follows the same discover-then-augment pattern used for stacks.
Overriding Discovered Filesets
When a fileset is discovered from volumes/, you can override any of its defaults:
identifier: myapp
contexts:
default: {}
stacks:
default/web:
filesets:
config: # ← Must match the directory name
target_volume: my-custom-volume # ← Override default volume name
target_path: /etc/nginx # ← Override default target path
ownership:
user: "1000"
group: "1000"
file_mode: "0644"
dir_mode: "0755"
exclude:
- "*.tmp"
- .DS_Store
Explicit values override discovered defaults. Fields you don't specify keep their discovered values.
Declaring Filesets Explicitly
You can also define filesets entirely in the manifest without a volumes/ directory. This is useful when the source files live outside the stack directory or when you need full control over the configuration:
identifier: myapp
contexts:
default: {}
stacks:
default/web:
filesets:
config:
source: ./shared/nginx-config # ← Source outside the stack directory
target_volume: nginx_config
target_path: /etc/nginx
exclude:
- "*.bak"
Fileset Fields
| Field | Type | Description |
|---|---|---|
source |
string | Local directory to sync from |
target_volume |
string | Docker volume to sync into |
target_path |
string | Path inside the volume (must be absolute, default: /) |
apply_mode |
string | hot (default) or cold |
exclude |
list | Gitignore-style patterns to exclude |
ownership |
object | Ownership and permission settings |
restart_services |
string or list | Services to restart after sync |
Using Filesets with Compose
Reference fileset volumes as external in your compose files:
The config volume is automatically created and synced with the contents of volumes/config/.
How Sync Works
Dockform builds a content index from the local source and compares it with a remote index inside the volume:
- Index storage:
.dockform-index.jsoninside the target path - On differences:
- Packs created/updated files in a tar archive
- Extracts them into the volume
- Deletes files present remotely but absent locally
- Writes the new index file
- No changes: If tree hashes match, the fileset is skipped
Apply Modes
Filesets support two apply modes that control how files are synchronized with running containers:
Hot Mode (Default)
With apply_mode: hot, Dockform syncs files while containers are running, then restarts configured services.
Hot mode workflow:
- Sync files to volume (containers keep running)
- Apply stack changes via
docker compose up - Restart services if configured
Cold Mode
With apply_mode: cold, Dockform stops services first, syncs files, then starts them again.
Use cold mode when:
- Files must not change while services are running
- Atomic updates across multiple files are required
- Database or critical system configurations are being updated
Ownership & Permissions
Filesets can enforce ownership and permission bits on synced files via the ownership block:
stacks:
default/web:
filesets:
config:
ownership:
user: "1000"
group: "1000"
file_mode: "0644"
dir_mode: "0755"
preserve_existing: false
| Field | Description |
|---|---|
user |
Numeric UID or POSIX username |
group |
Numeric GID or POSIX group name |
file_mode |
Octal permission for files (e.g., "0644") |
dir_mode |
Octal permission for directories (e.g., "0755") |
preserve_existing |
When true, only new/updated files get ownership applied |
Tip
Use numeric IDs for portability. Named users/groups must exist inside the helper container (alpine:3.22).
Preserve Existing
When preserve_existing: true, ownership and permissions are only applied to files that are newly created or updated during the current sync. Files that already exist in the volume and haven't changed keep their current ownership.
This is useful when:
- Multiple filesets or processes write to the same volume
- You want to avoid overwriting manually set permissions
- Initial deploy sets ownership, subsequent syncs only touch new files
Excluding Files
Use the exclude field with gitignore-style patterns:
Restarting Services
Configure services to restart after a fileset is synced using restart_services:
stacks:
default/web:
filesets:
config:
restart_services: attached # ← Restart services that mount the target volume
restart_services accepts:
| Value | Behavior |
|---|---|
attached |
Automatically discover and restart services that mount the fileset's target volume |
| List of strings | Restart the named services explicitly |
Lifecycle and Operations
| Step | Operation |
|---|---|
| plan | Shows file operations per fileset when Docker is available |
| apply | Ensures volume exists, computes diffs, syncs changes, writes index, queues restarts |
| destroy | Removes fileset-associated volumes along with other labeled resources |
Multi-Context Filesets
Filesets are discovered per context, allowing different configurations for different environments:
my-project/
├── dockform.yml
├── default/
│ └── nginx/
│ └── volumes/
│ └── config/
│ └── nginx.dev.conf
└── production/
└── nginx/
└── volumes/
└── config/
└── nginx.prod.conf
Examples
Basic: Static Site Assets
services:
nginx:
image: nginx:alpine
volumes:
- html:/usr/share/nginx/html
volumes:
html:
external: true
Traefik with Custom Target Path
Database Seeds with Ownership
identifier: myapp
contexts:
default: {}
stacks:
default/db:
filesets:
init:
target_path: /docker-entrypoint-initdb.d
apply_mode: cold
ownership:
user: "999"
group: "999"
file_mode: "0640"
services:
postgres:
image: postgres:16
volumes:
- init:/docker-entrypoint-initdb.d
volumes:
init:
external: true
Run dockform plan to preview fileset changes, then dockform apply to sync files and start services.