Accessories
Accessories are stateful services (databases, caches, message queues, etc.) that have a separate lifecycle from your main application. They are deployed once and remain untouched during regular app deployments.
Why Accessories?
Problem: If you put your database in the main docker-compose.yml, it gets restarted on every deployment. This can cause data corruption or downtime.
Solution: Accessories are deployed as a separate Docker Swarm stack. Your app can be deployed 100 times without touching the database.
myapp-production ā Main app (redeployed often)
myapp-production-accessories ā Databases, Redis, etc. (deployed once)Configuration
Create a file at .deployment/docker/accessories.yml using standard Docker Compose format:
version: "3.8"
services:
postgres:
image: postgres:16-alpine
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
environment:
POSTGRES_USER: app
POSTGRES_PASSWORD: "{{ db_password }}"
POSTGRES_DB: myapp
healthcheck:
test: ["CMD-SHELL", "pg_isready -U app"]
interval: 10s
timeout: 5s
retries: 5
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
- redis_data:/data
command: redis-server --appendonly yes
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
volumes:
postgres_data:
redis_data:Environment variables can be accessed using Jinja2 syntax: {{ variable_name }}
Automatic Swarm Configuration
Dockflow automatically injects a minimal Swarm configuration for each accessory service:
deploy:
replicas: 1
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 3This ensures:
- Single replica by default (appropriate for stateful services)
- Automatic restart on failure with backoff
- No rolling updates (you control when to update databases)
You can override any of these in your accessories.yml.
Deployment
Dockflow uses hash-based change detection for accessories. This means:
- First deployment ā accessories are automatically deployed
accessories.ymlchanged ā accessories are automatically redeployed- No changes ā accessories are skipped (fast)
Automatic Deployment (Default)
dockflow deploy production
# Deploys app
# Auto-checks accessories.yml hash
# Deploys accessories only if changed or first timeForce Redeploy Accessories
dockflow deploy production --accessories # Accessories only (forced)
dockflow deploy production --all # App + accessories (forced)Skip Accessories Check
dockflow deploy production --skip-accessories
# Deploys app only, completely ignores accessoriesThe hash is stored on the server at /var/lib/dockflow/accessories/{stack}/.hash. Delete this file to force a redeploy on next deployment.
Management Commands
All accessories commands use SSH to interact with the running services.
List Accessories
dockflow accessories list production
# or
dockflow acc ls productionShows all accessories services with their status and replicas.
View Logs
dockflow accessories logs production # All accessories
dockflow accessories logs production postgres # Specific service
dockflow accessories logs production postgres -f # FollowExecute Commands
dockflow accessories exec production postgres # Open shell
dockflow accessories exec production postgres psql # Run psqlRestart Services
dockflow accessories restart production # All
dockflow accessories restart production postgres # SpecificStop Services
dockflow accessories stop production # Scale all to 0
dockflow accessories stop production postgres # Scale specific to 0Stop scales services to 0 replicas but keeps the containers and volumes. Use restart to bring them back.
Remove Accessories
dockflow accessories remove production # Remove stack (keep volumes)
dockflow accessories remove production --volumes # Remove stack AND volumesThe --volumes flag permanently deletes all data. You will be prompted to type the environment name to confirm.
Best Practices
1. Always Use Named Volumes
volumes:
- postgres_data:/var/lib/postgresql/data # ā
Named volume
- ./data:/var/lib/postgresql/data # ā Bind mount (lost on redeploy)2. Pin Image Versions
image: postgres:16-alpine # ā
Specific version
image: postgres:latest # ā Unpredictable updates3. Configure Health Checks
healthcheck:
test: ["CMD-SHELL", "pg_isready -U app"]
interval: 10s
timeout: 5s
retries: 5
start_period: 30s # Give time for initial startup4. Constrain to Manager Node (Optional)
For single-node deployments, this ensures data stays on the same node:
deploy:
placement:
constraints:
- node.role == managerConnecting Your App
Your main application can connect to accessories using Dockerās internal DNS:
services:
app:
image: myapp:latest
environment:
DATABASE_URL: postgres://app:password@postgres:5432/myapp
REDIS_URL: redis://redis:6379
networks:
- default
- accessories
networks:
accessories:
external: true
name: myapp-production-accessories_defaultMake sure to reference the correct network name: {project}-{env}-accessories_default