- Implement complete test suite with 63 examples (49 unit + 14 integration tests) - Add RSpec, FactoryBot, WebMock, and SimpleCov testing dependencies - Create mocked integration tests eliminating need for real Docker containers - Fix SQLite method signature to accept login/password parameters - Enhance container discovery to handle nil labels gracefully - Add test coverage reporting and JUnit XML output for CI - Update GitHub Actions workflow to run tests before Docker builds - Add Ruby 3.3 setup with gem caching for faster CI execution - Create CI test script and comprehensive testing documentation - Ensure Docker builds only proceed when all tests pass 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
5.9 KiB
5.9 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Project Overview
Baktainer is a Ruby-based Docker container database backup utility that automatically discovers and backs up databases using Docker labels. It supports MySQL, MariaDB, PostgreSQL, and SQLite databases.
Development Commands
Build and Run
# Build Docker image locally
docker build -t baktainer:local .
# Run with docker-compose
docker-compose up -d
# Run directly with Ruby (for development)
cd app && bundle install
bundle exec ruby app.rb
# Run backup immediately (bypasses cron schedule)
cd app && bundle exec ruby app.rb --now
Dependency Management
cd app
bundle install # Install dependencies
bundle update # Update dependencies
bundle exec <command> # Run commands with bundled gems
Testing Commands
cd app
# Quick unit tests
bin/test
bundle exec rspec spec/unit/
# All tests with coverage
bin/test --all --coverage
COVERAGE=true bundle exec rspec
# Integration tests (requires Docker)
bin/test --integration --setup --cleanup
bundle exec rspec spec/integration/
# Using Rake tasks
rake spec # Unit tests
rake integration # Integration tests
rake test_full # Full suite with setup/cleanup
rake coverage # Tests with coverage
rake coverage_report # Open coverage report
Docker Commands
# View logs
docker logs baktainer
# Restart container
docker restart baktainer
# Check running containers with baktainer labels
docker ps --filter "label=baktainer.backup=true"
Architecture Overview
Core Components
-
Runner (
app/lib/baktainer.rb
)- Main orchestrator class
Baktainer::Runner
- Manages Docker connection (socket/TCP/SSL)
- Implements cron-based scheduling using
cron_calc
gem - Uses thread pool for concurrent backups
- Main orchestrator class
-
Container Discovery (
app/lib/baktainer/container.rb
)Baktainer::Containers.find_all
discovers containers withbaktainer.backup=true
label- Parses Docker labels to extract database configuration
- Creates appropriate backup command objects
-
Database Backup Implementations
app/lib/baktainer/mysql.rb
- MySQL/MariaDB backups usingmysqldump
app/lib/baktainer/postgres.rb
- PostgreSQL backups usingpg_dump
app/lib/baktainer/sqlite.rb
- SQLite backups using file copy- Each implements a common interface with
#backup
method
-
Backup Command (
app/lib/baktainer/backup_command.rb
)- Abstract base class for database-specific backup implementations
- Handles file organization:
/backups/<date>/<name>-<timestamp>.sql
- Manages Docker exec operations
Threading Model
- Uses
concurrent-ruby
gem withFixedThreadPool
- Default 4 threads (configurable via
BT_THREADS
) - Each backup runs in separate thread
- Thread-safe logging via custom Logger wrapper
Docker Integration
- Connects via Docker socket (
/var/run/docker.sock
) or TCP - Supports SSL/TLS for remote Docker API
- Uses
docker-api
gem for container operations - Executes backup commands inside containers via
docker exec
Environment Variables
Required configuration through environment variables:
BT_DOCKER_URL
- Docker API endpoint (default:unix:///var/run/docker.sock
)BT_CRON
- Cron expression for backup schedule (default:0 0 * * *
)BT_THREADS
- Thread pool size (default: 4)BT_LOG_LEVEL
- Logging level: debug/info/warn/error (default: info)BT_BACKUP_DIR
- Backup storage directory (default:/backups
)BT_SSL
- Enable SSL for Docker API (default: false)BT_CA
- CA certificate for SSLBT_CERT
- Client certificate for SSLBT_KEY
- Client key for SSL
Docker Label Configuration
Containers must have these labels for backup:
labels:
- baktainer.backup=true # Required: Enable backup
- baktainer.db.engine=<engine> # Required: mysql/postgres/sqlite
- baktainer.db.name=<database> # Required: Database name
- baktainer.db.user=<username> # Required for MySQL/PostgreSQL
- baktainer.db.password=<pass> # Required for MySQL/PostgreSQL
- baktainer.name=<app_name> # Optional: Custom backup filename
File Organization
Backups are stored as:
/backups/
├── YYYY-MM-DD/
│ ├── <name>-<unix_timestamp>.sql
│ └── <name>-<unix_timestamp>.sql
Adding New Database Support
- Create new file in
app/lib/baktainer/<database>.rb
- Inherit from
Baktainer::BackupCommand
- Implement
#backup
method - Add engine mapping in
container.rb
- Update README.md with new engine documentation
Deployment
GitHub Actions automatically builds and pushes to Docker Hub on:
- Push to
main
branch →jamez001/baktainer:latest
- Tag push
v*.*.*
→jamez001/baktainer:<version>
Manual deployment:
docker build -t jamez001/baktainer:latest .
docker push jamez001/baktainer:latest
Common Development Tasks
Testing Database Backups
# Create test container with labels
docker run -d \
--name test-postgres \
-e POSTGRES_PASSWORD=testpass \
-l baktainer.backup=true \
-l baktainer.db.engine=postgres \
-l baktainer.db.name=testdb \
-l baktainer.db.user=postgres \
-l baktainer.db.password=testpass \
postgres:17
# Run backup immediately
cd app && bundle exec ruby app.rb --now
# Check backup file
ls -la backups/$(date +%Y-%m-%d)/
Debugging
- Set
BT_LOG_LEVEL=debug
for verbose logging - Check container logs:
docker logs baktainer
- Verify Docker socket permissions
- Test Docker connection:
docker ps
from inside container
Code Conventions
- Ruby 3.3 with frozen string literals
- Module namespacing under
Baktainer
- Logger instance available as
LOGGER
- Error handling with logged stack traces in debug mode
- No test framework currently implemented