Features
Accessories
Run databases, caches, and other services alongside your application.
Overview
Accessories are long-running services that support your application:
- Databases (PostgreSQL, MySQL, MongoDB)
- Caches (Redis, Memcached)
- Message queues (RabbitMQ)
- Search engines (Elasticsearch)
Odysseus manages these as Docker containers with independent lifecycles.
Configuration
Define accessories in your deploy.yml:
accessories:
db:
image: postgres:16
hosts:
- db.example.com
volumes:
- /var/lib/odysseus/myapp/postgres:/var/lib/postgresql/data
env:
clear:
POSTGRES_USER: myapp
POSTGRES_PASSWORD: secretpassword
POSTGRES_DB: myapp_production
healthcheck:
cmd: pg_isready -U myapp
interval: 10
timeout: 5
redis:
image: redis:7-alpine
hosts:
- cache.example.com
volumes:
- /var/lib/odysseus/myapp/redis:/data
cmd: redis-server --appendonly yes
image
Docker image for the service.
hosts
The servers where this accessory should run. Required for each accessory.
hosts:
- db.example.com
- db-replica.example.com
volumes
Persistent storage mappings. Data persists across container restarts.
volumes:
- /host/path:/container/path
env
Environment variables for the service:
env:
clear:
POSTGRES_USER: myapp
POSTGRES_DB: myapp_production
cmd
Override the container's default command:
cmd: redis-server --appendonly yes --maxmemory 256mb
healthcheck
Container health check configuration:
healthcheck:
cmd: pg_isready -U myapp
interval: 10
timeout: 5
ports
Expose ports (optional, for external access):
ports:
- 5432:5432
Managing accessories
Accessory commands read target hosts from the accessory's hosts configuration, similar to how deploy works.
Boot all accessories
Start all accessories on their configured hosts:
odysseus accessory boot-all
Boot specific accessory
Start a single accessory on all its configured hosts:
odysseus accessory boot --name db
Check status
View running accessories across all hosts:
odysseus accessory status
Output:
Accessories:
NAME HOST IMAGE STATUS HEALTH
db db.example.com postgres:16 running (healthy)
redis cache.example.com redis:7 running (healthy)
View logs
Logs require a server argument since they operate on a specific host:
odysseus accessory logs your-server --name db
odysseus accessory logs your-server --name db -f # Follow
odysseus accessory logs your-server --name db -n 200 # Last 200 lines
Restart
odysseus accessory restart --name db
Upgrade
Pull new image and restart:
odysseus accessory upgrade --name db
Remove
Stop and remove:
odysseus accessory remove --name db
Execute commands
Run a command in the accessory container (requires server argument):
odysseus accessory exec your-server --name db --command "psql -U myapp myapp_production"
Interactive shell
odysseus accessory shell your-server --name db
Common configurations
PostgreSQL
accessories:
db:
image: postgres:16
hosts:
- db.example.com
volumes:
- /var/lib/odysseus/myapp/postgres:/var/lib/postgresql/data
env:
clear:
POSTGRES_USER: myapp
POSTGRES_PASSWORD: secretpassword
POSTGRES_DB: myapp_production
healthcheck:
cmd: pg_isready -U myapp
interval: 10
timeout: 5
MySQL
accessories:
db:
image: mysql:8
hosts:
- db.example.com
volumes:
- /var/lib/odysseus/myapp/mysql:/var/lib/mysql
env:
clear:
MYSQL_ROOT_PASSWORD: rootpassword
MYSQL_DATABASE: myapp_production
MYSQL_USER: myapp
MYSQL_PASSWORD: userpassword
healthcheck:
cmd: mysqladmin ping -h localhost
interval: 10
timeout: 5
Redis
accessories:
redis:
image: redis:7-alpine
hosts:
- cache.example.com
volumes:
- /var/lib/odysseus/myapp/redis:/data
cmd: redis-server --appendonly yes
healthcheck:
cmd: redis-cli ping
interval: 10
timeout: 5
Redis with password
accessories:
redis:
image: redis:7-alpine
hosts:
- cache.example.com
volumes:
- /var/lib/odysseus/myapp/redis:/data
cmd: redis-server --appendonly yes --requirepass mypassword
Elasticsearch
accessories:
elasticsearch:
image: elasticsearch:8.11.0
hosts:
- search.example.com
volumes:
- /var/lib/odysseus/myapp/elasticsearch:/usr/share/elasticsearch/data
env:
clear:
discovery.type: single-node
ES_JAVA_OPTS: "-Xms512m -Xmx512m"
xpack.security.enabled: "false"
MongoDB
accessories:
mongo:
image: mongo:7
hosts:
- db.example.com
volumes:
- /var/lib/odysseus/myapp/mongo:/data/db
env:
clear:
MONGO_INITDB_ROOT_USERNAME: admin
MONGO_INITDB_ROOT_PASSWORD: password
Connecting from your app
Accessories run on the same Docker network as your application. Connect using the accessory name as hostname.
Database URL
# secrets.yml
DATABASE_URL: postgres://myapp:secretpassword@db:5432/myapp_production
REDIS_URL: redis://redis:6379
In your app
# Rails database.yml
production:
url: <%= ENV['DATABASE_URL'] %>
// Node.js
const redis = require('redis')
const client = redis.createClient({ url: process.env.REDIS_URL })
Data persistence
Accessories use Docker volumes for data persistence:
volumes:
- /var/lib/odysseus/myapp/postgres:/var/lib/postgresql/data
Data is stored on the host at /var/lib/odysseus/myapp/postgres.
Backup
SSH to your server and backup the volume:
# PostgreSQL dump
docker exec myapp-db pg_dump -U myapp myapp_production > backup.sql
# Copy from volume
tar -czf postgres-backup.tar.gz /var/lib/odysseus/myapp/postgres
Restore
# PostgreSQL restore
cat backup.sql | docker exec -i myapp-db psql -U myapp myapp_production
Best practices
1. Use health checks
Always configure health checks:
healthcheck:
cmd: pg_isready -U myapp
interval: 10
timeout: 5
2. Persistent storage
Map volumes for data that must survive restarts:
volumes:
- /var/lib/odysseus/myapp/postgres:/var/lib/postgresql/data
3. Secure credentials
Use secrets for passwords:
accessories:
db:
env:
secret:
- POSTGRES_PASSWORD
4. Resource limits
Consider adding resource limits for production:
accessories:
db:
options:
memory: 4g
cpus: 2
5. Regular backups
Schedule regular backups of your data volumes.