Initial
This commit is contained in:
commit
3f60b72c3b
48 changed files with 6599 additions and 0 deletions
377
README.md
Normal file
377
README.md
Normal file
|
|
@ -0,0 +1,377 @@
|
|||
# Docker Compose Updater
|
||||
|
||||
A robust, production-ready Rust service that automatically updates Docker Compose image versions whilst preserving comments, formatting, and maintaining operational stability. The service operates on a configurable schedule and uses intelligent update strategies to ensure safe, conservative updates.
|
||||
|
||||
## Key Features
|
||||
|
||||
- 🔄 **Intelligent Updates**: Automatically updates Docker Compose files using configurable update strategies
|
||||
- 📝 **Format Preservation**: Maintains all comments, whitespace, and YAML formatting perfectly
|
||||
- 🎯 **Conservative Strategies**: Defaults to stable, tested versions rather than bleeding edge
|
||||
- 🏥 **Health Monitoring**: Built-in health endpoints for monitoring and observability
|
||||
- 🔐 **Multi-Registry Support**: Works with Docker Hub, GitHub Container Registry, GitLab, and custom registries
|
||||
- 🔍 **Flexible Filtering**: Configurable patterns to ignore specific images or registries
|
||||
- 🛡️ **Robust Error Handling**: Comprehensive error management with no silent failures
|
||||
- 📋 **Prefix/Suffix Support**: Handles complex versioning schemes like `v1.2.3-alpine`, `release-1.0.0-slim`
|
||||
- 🚀 **Container-Ready**: Designed for containerised environments with proper security
|
||||
- 📊 **Comprehensive Testing**: Extensively tested with 44+ test cases covering edge cases
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Using Docker Compose (Recommended)
|
||||
|
||||
1. **Create a configuration file** (`config.yaml`):
|
||||
```yaml
|
||||
# Paths to scan for Docker Compose files
|
||||
compose_paths:
|
||||
- "./compose-files"
|
||||
- "./docker-compose.yml"
|
||||
- "./services"
|
||||
|
||||
# Cron expression for update schedule
|
||||
schedule: "0 0 2 * * *" # Daily at 2 AM UTC
|
||||
|
||||
# Update strategy (conservative by default)
|
||||
update_strategy: "LatestPatchOfPreviousMinor"
|
||||
|
||||
# Runtime behaviour
|
||||
dry_run: false # Set to true for testing
|
||||
|
||||
# Images to ignore during updates (substring matching)
|
||||
ignore_images:
|
||||
- "localhost"
|
||||
- "127.0.0.1"
|
||||
- "internal.company.com"
|
||||
|
||||
# Registry configurations
|
||||
registries:
|
||||
"docker.io":
|
||||
url: "https://registry-1.docker.io"
|
||||
|
||||
"ghcr.io":
|
||||
url: "https://ghcr.io"
|
||||
auth_token: "${GITHUB_TOKEN}"
|
||||
```
|
||||
|
||||
2. **Deploy with Docker Compose**:
|
||||
```yaml
|
||||
version: '3.8'
|
||||
services:
|
||||
docker-compose-updater:
|
||||
image: ghcr.io/your-username/docker-compose-updater:latest
|
||||
container_name: docker-compose-updater
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- GITHUB_TOKEN=${GITHUB_TOKEN}
|
||||
- RUST_LOG=info
|
||||
volumes:
|
||||
# Mount Docker socket (read-only for security)
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
# Mount compose files directory
|
||||
- ./compose-files:/app/compose-files:rw
|
||||
# Mount configuration
|
||||
- ./config.yaml:/app/config/config.yaml:ro
|
||||
ports:
|
||||
- "8080:8080" # Health monitoring port
|
||||
user: "1000:1000" # Run as non-root user
|
||||
```
|
||||
|
||||
3. **Start the service**:
|
||||
```bash
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
### Command Line Usage
|
||||
|
||||
```bash
|
||||
# Install or build the binary
|
||||
cargo build --release
|
||||
|
||||
# Run a one-time update
|
||||
./target/release/docker-compose-updater --config ./config.yaml update
|
||||
|
||||
# Start the scheduled service with health monitoring
|
||||
./target/release/docker-compose-updater --config ./config.yaml start
|
||||
```
|
||||
|
||||
## Update Strategies
|
||||
|
||||
The service supports three intelligent update strategies, defaulting to the most conservative:
|
||||
|
||||
|
||||
### `LatestPatchOfPreviousMinor`
|
||||
- **Predictable**: Always updates to the latest patch of the previous minor version
|
||||
- **Consistent Behaviour**: Never updates to the current latest minor
|
||||
- **Example**: `1.5.3` → `1.4.8`
|
||||
|
||||
### `Latest`
|
||||
- **Aggressive**: Updates to the absolute latest available version
|
||||
- **Cutting Edge**: Useful for development environments
|
||||
- **Example**: `1.5.3` → `2.1.0`
|
||||
|
||||
## Advanced Version Handling
|
||||
|
||||
The service handles complex versioning schemes intelligently:
|
||||
|
||||
### Supported Version Formats
|
||||
- **Standard Semantic Versions**: `1.2.3`, `2.0.1`
|
||||
- **Prefixed Versions**: `v1.2.3`, `release-1.0.0`, `build123-2.1.0`
|
||||
- **Suffixed Versions**: `1.2.3-alpine`, `2.0.1-slim`, `1.5.0-ubuntu20.04`
|
||||
- **Combined**: `v1.2.3-alpine-slim`, `release-2.0.1-final`
|
||||
|
||||
### Version Matching Logic
|
||||
The service ensures that prefix and suffix combinations remain consistent:
|
||||
- `v1.2.3-alpine` will only be updated to other `v*.*.*-alpine` versions
|
||||
- `release-1.0.0` will only be updated to other `release-*.*.*` versions
|
||||
- This prevents incompatible image variants from being selected
|
||||
|
||||
## Comprehensive Registry Support
|
||||
|
||||
### Supported Registries
|
||||
- **Docker Hub**: `docker.io` (default registry)
|
||||
- **GitHub Container Registry**: `ghcr.io`
|
||||
- **GitLab Container Registry**: `registry.gitlab.com`
|
||||
- **Google Container Registry**: `gcr.io`
|
||||
- **Amazon ECR**: `*.dkr.ecr.*.amazonaws.com`
|
||||
- **Azure Container Registry**: `*.azurecr.io`
|
||||
- **Custom/Private Registries**: Any registry following Docker Registry API v2
|
||||
|
||||
### Registry Configuration
|
||||
```yaml
|
||||
registries:
|
||||
"docker.io":
|
||||
url: "https://registry-1.docker.io"
|
||||
# Docker Hub typically doesn't require auth for public images
|
||||
|
||||
"ghcr.io":
|
||||
url: "https://ghcr.io"
|
||||
auth_token: "${GITHUB_TOKEN}"
|
||||
|
||||
"registry.gitlab.com":
|
||||
url: "https://registry.gitlab.com"
|
||||
auth_token: "${GITLAB_TOKEN}"
|
||||
|
||||
"your-registry.company.com":
|
||||
url: "https://your-registry.company.com"
|
||||
auth_token: "${COMPANY_REGISTRY_TOKEN}"
|
||||
```
|
||||
|
||||
## Supported Image Formats
|
||||
|
||||
The updater handles various image naming conventions:
|
||||
|
||||
```yaml
|
||||
# Standard Docker Hub images
|
||||
nginx:1.21.0 → nginx:1.20.6
|
||||
ubuntu:20.04 → ubuntu:18.04
|
||||
|
||||
# Namespaced images
|
||||
bitnami/nginx:1.21.0 → bitnami/nginx:1.20.6
|
||||
library/postgres:13.7 → library/postgres:12.11
|
||||
|
||||
# Custom registries
|
||||
ghcr.io/user/app:v1.0.0 → ghcr.io/user/app:v0.9.5
|
||||
registry.example.com/team/service:2.1.3 → registry.example.com/team/service:2.0.9
|
||||
|
||||
# Complex versioning
|
||||
nginx:1.21.0-alpine → nginx:1.20.6-alpine
|
||||
postgres:13.7-bullseye → postgres:12.11-bullseye
|
||||
redis:v7.0.0-alpine3.16 → redis:v6.2.7-alpine3.16
|
||||
|
||||
# Local development (typically ignored)
|
||||
localhost:5000/myapp:latest → [ignored by default]
|
||||
127.0.0.1:8080/service:dev → [ignored by default]
|
||||
```
|
||||
|
||||
## Health Monitoring & Observability
|
||||
|
||||
The service provides comprehensive monitoring capabilities:
|
||||
|
||||
### Health Endpoints
|
||||
- **`GET /`**: Basic health check
|
||||
- Returns `{"status":"healthy"}` when operational
|
||||
- Returns `{"status":"unhealthy"}` during failures
|
||||
- Includes basic service information
|
||||
|
||||
### Logging
|
||||
```bash
|
||||
# Configure logging level via environment variable
|
||||
RUST_LOG=debug # For detailed debugging
|
||||
RUST_LOG=info # For operational information (default)
|
||||
RUST_LOG=warn # For warnings and errors only
|
||||
RUST_LOG=error # For errors only
|
||||
```
|
||||
|
||||
### Service Monitoring
|
||||
The service reports:
|
||||
- Successful update cycles with file counts
|
||||
- Failed updates with detailed error information
|
||||
- Registry connectivity status
|
||||
- Configuration validation results
|
||||
|
||||
## Security Features
|
||||
|
||||
- **Non-Root Execution**: Designed to run as non-root user in containers
|
||||
- **Minimal Attack Surface**: Alpine Linux base image with minimal packages
|
||||
- **Read-Only Docker Socket**: Only requires read access to Docker socket
|
||||
- **Secret Management**: All tokens provided via environment variables
|
||||
- **Input Validation**: Comprehensive validation of all configuration inputs
|
||||
- **Error Sanitisation**: No sensitive information leaked in error messages
|
||||
|
||||
## Development
|
||||
|
||||
### Building from Source
|
||||
|
||||
```bash
|
||||
# Clone the repository
|
||||
git clone https://github.com/your-username/docker-compose-updater.git
|
||||
cd docker-compose-updater
|
||||
|
||||
# Build in release mode
|
||||
cargo build --release
|
||||
|
||||
# Run comprehensive test suite
|
||||
cargo test
|
||||
|
||||
# Run with custom configuration
|
||||
./target/release/docker-compose-updater --config ./config.example.yaml start
|
||||
```
|
||||
|
||||
### Testing
|
||||
|
||||
The project includes extensive testing:
|
||||
|
||||
```bash
|
||||
# Run all tests (44+ test cases)
|
||||
cargo test
|
||||
|
||||
# Run specific test suites
|
||||
cargo test --test integration_tests # Integration tests
|
||||
cargo test --test test_error_handling # Error handling tests
|
||||
cargo test --test test_config_validation # Configuration tests
|
||||
cargo test --test test_compose_operations # Compose file operations
|
||||
|
||||
# Run with output for debugging
|
||||
cargo test -- --nocapture
|
||||
|
||||
# Generate coverage report (requires cargo-llvm-cov)
|
||||
cargo llvm-cov --html
|
||||
```
|
||||
|
||||
### Test Coverage
|
||||
- **Error Handling**: Invalid configurations, malformed files, network failures
|
||||
- **Config Validation**: All configuration formats, edge cases, defaults
|
||||
- **Compose Operations**: Complex file formats, image parsing, version handling
|
||||
- **Registry Integration**: Multiple registry types, authentication, failures
|
||||
- **Version Logic**: All update strategies, complex versioning schemes
|
||||
|
||||
## Configuration Reference
|
||||
|
||||
### Complete Configuration Example
|
||||
```yaml
|
||||
# File/directory paths to scan for Docker Compose files
|
||||
compose_paths:
|
||||
- "/app/compose-files" # Directory to scan recursively
|
||||
- "./docker-compose.yml" # Specific file
|
||||
- "./services/" # Another directory
|
||||
|
||||
# Cron expression for update schedule (UTC timezone)
|
||||
schedule: "0 0 2 * * *" # Daily at 2 AM
|
||||
|
||||
# Update strategy selection
|
||||
update_strategy: "LatestPatchOfPreviousMinor"
|
||||
|
||||
# Prevent actual file modifications (for testing)
|
||||
dry_run: false
|
||||
|
||||
# Images to ignore during updates (substring matching)
|
||||
ignore_images:
|
||||
- "localhost" # Local development images
|
||||
- "127.0.0.1" # Local registry
|
||||
- "internal.company.com" # Private internal registry
|
||||
- "snapshot" # Snapshot versions
|
||||
|
||||
# Registry configurations
|
||||
registries:
|
||||
"docker.io":
|
||||
url: "https://registry-1.docker.io"
|
||||
# auth_token not typically needed for public images
|
||||
|
||||
"ghcr.io":
|
||||
url: "https://ghcr.io"
|
||||
auth_token: "${GITHUB_TOKEN}"
|
||||
|
||||
"registry.gitlab.com":
|
||||
url: "https://registry.gitlab.com"
|
||||
auth_token: "${GITLAB_TOKEN}"
|
||||
```
|
||||
|
||||
### Environment Variables
|
||||
- **`GITHUB_TOKEN`**: Personal access token for GitHub Container Registry
|
||||
- **`GITLAB_TOKEN`**: Access token for GitLab Container Registry
|
||||
- **`RUST_LOG`**: Logging level (`debug`, `info`, `warn`, `error`)
|
||||
- **Registry-specific tokens**: For private registries
|
||||
|
||||
## Operational Considerations
|
||||
|
||||
### Backup Strategy
|
||||
- Always backup your Docker Compose files before running updates
|
||||
- Use version control (Git) to track changes
|
||||
- Test with `dry_run: true` before enabling actual updates
|
||||
|
||||
### Monitoring
|
||||
- Monitor the health endpoint for service availability
|
||||
- Set up alerts for failed update cycles
|
||||
- Review logs regularly for registry connectivity issues
|
||||
|
||||
### Resource Requirements
|
||||
- **Memory**: ~10-50MB during operation
|
||||
- **CPU**: Minimal during dormant periods, brief spikes during updates
|
||||
- **Network**: Requires outbound HTTPS access to configured registries
|
||||
- **Storage**: Minimal, only for configuration and temporary files
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
**Service fails to start**
|
||||
- Check configuration file syntax with `yamllint`
|
||||
- Verify file paths exist and are accessible
|
||||
- Ensure cron expression is valid
|
||||
|
||||
**Registry authentication failures**
|
||||
- Verify environment variables are set correctly
|
||||
- Check token permissions for the target registry
|
||||
- Test registry connectivity manually
|
||||
|
||||
**Updates not applied**
|
||||
- Check if `dry_run` is enabled
|
||||
- Verify images are not in the ignore list
|
||||
- Ensure semantic versioning is used in image tags
|
||||
|
||||
## Contributing
|
||||
|
||||
1. Fork the repository
|
||||
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
|
||||
3. Write tests for your changes
|
||||
4. Ensure all tests pass (`cargo test`)
|
||||
5. Commit your changes (`git commit -m 'Add amazing feature'`)
|
||||
6. Push to the branch (`git push origin feature/amazing-feature`)
|
||||
7. Open a Pull Request
|
||||
|
||||
## Licence
|
||||
|
||||
This project is licensed under the MIT Licence - see the [LICENSE](LICENSE) file for details.
|
||||
|
||||
## Changelog
|
||||
|
||||
### v0.1.0
|
||||
- Initial release with comprehensive functionality
|
||||
- Multi-registry support (Docker Hub, GHCR, GitLab, custom)
|
||||
- Intelligent update strategies with conservative defaults
|
||||
- Comment and formatting preservation
|
||||
- Comprehensive error handling (no silent failures)
|
||||
- Health monitoring and observability
|
||||
- Extensive test coverage (44+ test cases)
|
||||
- Prefix/suffix version handling
|
||||
- Robust configuration validation
|
||||
- Production-ready security features
|
||||
Loading…
Add table
Add a link
Reference in a new issue