No description
  • Rust 99.4%
  • Dockerfile 0.6%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Andras Schmelczer 30c1cd4a38
Some checks failed
Build and Publish Docker Image / test (pull_request) Successful in 1m41s
Build and Publish Docker Image / build-and-push (pull_request) Failing after 32s
Update Rust crate cron to 0.17
2026-09-27 15:01:14 +00:00
.forgejo/workflows Remove scan 2026-06-06 20:55:36 +01:00
compose Initial 2026-03-23 07:44:26 +00:00
src Longer retries 2026-09-27 15:02:27 +01:00
tests Longer retries 2026-09-27 15:02:27 +01:00
.dockerignore Initial 2026-03-23 07:44:26 +00:00
.gitignore Initial 2026-03-23 07:44:26 +00:00
Cargo.lock Update Rust crate cron to 0.17 2026-09-27 15:01:14 +00:00
Cargo.toml Update Rust crate cron to 0.17 2026-09-27 15:01:14 +00:00
CLAUDE.md Initial 2026-03-23 07:44:26 +00:00
config.example.yaml Longer retries 2026-09-27 15:02:27 +01:00
demo-config.yaml Initial 2026-03-23 07:44:26 +00:00
docker-compose.yml Clean up 2026-06-06 19:41:55 +01:00
Dockerfile Clean up 2026-06-06 19:41:55 +01:00
README.md Longer retries 2026-09-27 15:02:27 +01:00
renovate.json Add renovate.json 2026-09-19 10:38:59 +00:00

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

  1. Create a configuration file (config.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}"
  1. Deploy with Docker Compose:
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
  1. Start the service:
docker-compose up -d

Command Line Usage

# 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

Registry rate limits

Version checks list all image tags, so repositories with thousands of build and architecture tags require many requests even when checking only one service. The updater spaces requests to each registry backend one second apart by default. LinuxServer's lscr.io gateway shares the ghcr.io request budget.

Set registry_request_interval_ms: 2000 in config.yaml to slow requests further if other tools share the registry quota. The setting applies to tag pages, authentication and retries; 0 disables pacing. An HTTP 429 pauses requests to that backend using Retry-After, or exponential waits of 5, 10, 20, 40 and 80 seconds when the header is absent or invalid. Cooldowns also apply to subsequent images if retries are exhausted. Warnings include the image and backend.

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

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:

# 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

# 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

# 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:

# 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

# 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 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