Major improvements: flexible install dir, configurable compose file name for git, enhanced webhook notifications, cross-platform lock, robust rollback, and updated docs.\n\n- Install dir is now user-confirmable and dynamic\n- Added COMPOSE_FILENAME for git stacks\n- Webhook payloads now include git context and rollback events\n- Lock file age check is cross-platform\n- Rollback notifications for success/failure\n- Updated TOML example and documentation\n- Many robustness and UX improvements

This commit is contained in:
robojerk 2025-06-25 15:15:40 -07:00
parent f0dba7cc0a
commit 70486907aa
18 changed files with 3788 additions and 1767 deletions

View file

@ -1,263 +1,404 @@
# Watchtower Integration
This guide covers how to use ComposeSync alongside Watchtower and how to configure them to work together effectively.
This guide explains how ComposeSync works with Watchtower and provides recommendations for using both tools together.
## Understanding the Tools
## Overview
### Watchtower
- Monitors running Docker images and updates them when new versions are available in the registry
- Focuses on updating container images, not compose file configurations
- Works at the container level
ComposeSync and Watchtower are complementary tools that serve different purposes:
### ComposeSync
- Monitors remote sources for changes to `docker-compose.yml` files and applies those changes
- Focuses on updating compose file configurations, not just images
- Works at the compose file level
- **ComposeSync**: Updates Docker Compose configuration files
- **Watchtower**: Updates Docker container images
## Recommended Configuration
## Key Differences
For stacks managed by ComposeSync, it's recommended to disable Watchtower to prevent conflicts and race conditions.
| Feature | ComposeSync | Watchtower |
|---------|-------------|------------|
| **Purpose** | Updates compose files | Updates container images |
| **Scope** | Configuration changes | Image updates |
| **Method** | Downloads new compose files | Pulls new images |
| **Safety** | Preserves overrides, rollback on failure | Automatic image updates |
| **Control** | Version-controlled updates | Real-time updates |
### Disabling Watchtower for ComposeSync Stacks
## When to Use Each Tool
Add the following to your `docker-compose.override.yml`:
### Use ComposeSync When:
- You want to update application configurations
- You need to preserve custom overrides
- You want version-controlled updates
- You're managing complex multi-service stacks
- You need rollback capabilities
```yaml
services:
your-service:
labels:
- "com.centurylinklabs.watchtower.enable=false"
### Use Watchtower When:
- You want automatic image updates
- You're running simple containers
- You don't need configuration changes
- You want real-time updates
- You're using `latest` tags
## Integration Strategies
### Strategy 1: ComposeSync Only (Recommended)
Use ComposeSync for both configuration and image updates:
```toml
# Global settings
[global]
UPDATE_INTERVAL_SECONDS = 3600
KEEP_VERSIONS = 10
DRY_RUN = false
# Stack with specific image versions
[immich]
URL = "https://github.com/immich-app/immich/releases/latest/download/docker-compose.yml"
PATH = "/opt/composesync/stacks/immich"
TOOL = "wget"
```
### Example Configuration
**Benefits:**
- Full control over updates
- Configuration and images updated together
- Automatic rollback on failures
- Preserves your customizations
### Strategy 2: Watchtower Only
Use Watchtower for automatic image updates:
```yaml
# docker-compose.override.yml for a ComposeSync-managed stack
# docker-compose.yml
version: '3.8'
services:
immich-server:
labels:
- "com.centurylinklabs.watchtower.enable=false"
immich-microservices:
labels:
- "com.centurylinklabs.watchtower.enable=false"
immich-machine-learning:
labels:
- "com.centurylinklabs.watchtower.enable=false"
watchtower:
image: containrrr/watchtower
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
- WATCHTOWER_POLL_INTERVAL=3600
- WATCHTOWER_CLEANUP=true
restart: unless-stopped
```
**Benefits:**
- Real-time image updates
- Simple setup
- Automatic cleanup
### Strategy 3: Hybrid Approach
Use both tools for different purposes:
```toml
# ComposeSync for configuration updates
[global]
UPDATE_INTERVAL_SECONDS = 86400 # Daily config updates
KEEP_VERSIONS = 10
DRY_RUN = false
[immich]
URL = "https://github.com/immich-app/immich/releases/latest/download/docker-compose.yml"
PATH = "/opt/composesync/stacks/immich"
TOOL = "wget"
```
```yaml
# Watchtower for image updates
version: '3.8'
services:
watchtower:
image: containrrr/watchtower
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
- WATCHTOWER_POLL_INTERVAL=3600 # Hourly image updates
- WATCHTOWER_CLEANUP=true
- WATCHTOWER_LABEL_ENABLE=true
restart: unless-stopped
```
## Best Practices
### 1. Use ComposeSync for:
- Applications where the `docker-compose.yml` configuration evolves
- Complex stacks with multiple services
- Applications that require specific version management
- Stacks with custom configurations and overrides
### 1. Avoid Conflicts
### 2. Use Watchtower for:
- Simple, self-contained applications
- Stacks with static `docker-compose.yml` files
- Applications where only image updates are needed
- Stacks without complex configurations
**Don't use both tools on the same services** - this can cause conflicts and unexpected behavior.
### 3. Notification Integration:
- Configure both tools to send notifications to the same webhook
- This provides a unified view of all Docker updates
- Helps track what's being updated and when
### 2. Use Specific Image Tags
## Configuration Examples
### ComposeSync-Managed Stack (Immich)
When using ComposeSync, prefer specific image tags over `latest`:
```yaml
# docker-compose.override.yml
# Good: Specific version
services:
immich-server:
labels:
- "com.centurylinklabs.watchtower.enable=false"
environment:
- IMMICH_SERVER_URL=http://immich-server:2283
networks:
- npm_network
- immich-backend
image: ghcr.io/immich-app/immich-server:v1.75.0
redis:
labels:
- "com.centurylinklabs.watchtower.enable=false"
networks:
- immich-backend
database:
labels:
- "com.centurylinklabs.watchtower.enable=false"
networks:
- immich-backend
networks:
npm_network:
external: true
immich-backend:
name: immich-backend
# Avoid: Latest tag
services:
immich-server:
image: ghcr.io/immich-app/immich-server:latest
```
### Watchtower-Managed Stack (Simple App)
### 3. Configure Update Intervals
Set appropriate intervals for each tool:
```toml
# ComposeSync: Less frequent config updates
[global]
UPDATE_INTERVAL_SECONDS = 86400 # Daily
[immich]
URL = "https://github.com/immich-app/immich/releases/latest/download/docker-compose.yml"
PATH = "/opt/composesync/stacks/immich"
TOOL = "wget"
```
```yaml
# Watchtower: More frequent image updates
services:
watchtower:
environment:
- WATCHTOWER_POLL_INTERVAL=3600 # Hourly
```
### 4. Use Labels for Control
When using Watchtower, use labels to control which containers are updated:
```yaml
# docker-compose.yml
version: '3.8'
services:
simple-app:
image: nginx:latest
ports:
- "8080:80"
immich-server:
image: ghcr.io/immich-app/immich-server:v1.75.0
labels:
- "com.centurylinklabs.watchtower.enable=true"
restart: unless-stopped
database:
image: postgres:15
labels:
- "com.centurylinklabs.watchtower.enable=false" # Don't auto-update
restart: unless-stopped
```
## Potential Conflicts
### Race Conditions
- Both tools might try to update the same stack simultaneously
- Can lead to inconsistent states
- May cause service interruptions
### Configuration Conflicts
- Watchtower might update images while ComposeSync is updating compose files
- Can result in version mismatches
- May break service dependencies
### Resource Contention
- Both tools competing for Docker resources
- Can slow down update processes
- May cause timeouts or failures
## Monitoring Both Tools
### Unified Logging
Monitor both services together:
```bash
# Watch ComposeSync logs
sudo journalctl -u composesync -f
# Watch Watchtower logs (if running as container)
docker logs -f watchtower
# Or if running as systemd service
sudo journalctl -u watchtower -f
```
### Webhook Integration
Configure both tools to use the same webhook:
```env
# ComposeSync webhook
NOTIFICATION_WEBHOOK_URL=https://your-webhook-url.com/endpoint
# Watchtower webhook (in docker-compose.yml)
environment:
- WATCHTOWER_NOTIFICATIONS=webhook
- WATCHTOWER_NOTIFICATION_WEBHOOK_URL=https://your-webhook-url.com/endpoint
```
## Migration Strategy
## Migration Scenarios
### From Watchtower to ComposeSync
1. **Identify stacks to migrate**
- Choose stacks with evolving configurations
- Select stacks that need custom overrides
If you're currently using Watchtower and want to switch to ComposeSync:
2. **Configure ComposeSync**
- Add stack configuration to `.env`
- Set up override files
- Test with dry-run mode
1. **Stop Watchtower:**
```bash
docker compose down watchtower
```
3. **Disable Watchtower**
- Add labels to disable Watchtower for migrated stacks
- Keep Watchtower for simple stacks
2. **Configure ComposeSync:**
```toml
[global]
UPDATE_INTERVAL_SECONDS = 3600
KEEP_VERSIONS = 10
DRY_RUN = false
4. **Monitor and verify**
- Check that updates work correctly
- Verify no conflicts occur
[your-stack]
URL = "https://your-source.com/docker-compose.yml"
PATH = "/opt/composesync/stacks/your-stack"
TOOL = "wget"
```
3. **Create override file:**
```bash
sudo nano /opt/composesync/stacks/your-stack/docker-compose.override.yml
```
4. **Start ComposeSync:**
```bash
sudo systemctl start composesync
```
### From ComposeSync to Watchtower
1. **Identify simple stacks**
- Choose stacks with static configurations
- Select stacks that only need image updates
If you want to switch from ComposeSync to Watchtower:
2. **Remove from ComposeSync**
- Remove stack configuration from `.env`
- Clean up stack directories
1. **Stop ComposeSync:**
```bash
sudo systemctl stop composesync
sudo systemctl disable composesync
```
3. **Enable Watchtower**
- Remove Watchtower disable labels
- Configure Watchtower for the stack
2. **Deploy Watchtower:**
```yaml
version: '3.8'
services:
watchtower:
image: containrrr/watchtower
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
- WATCHTOWER_POLL_INTERVAL=3600
- WATCHTOWER_CLEANUP=true
restart: unless-stopped
```
3. **Update your compose files to use `latest` tags:**
```yaml
services:
your-app:
image: your-app:latest
```
## Troubleshooting
### Update Conflicts
### Conflicts Between Tools
If you see conflicts between the tools:
1. Check which tool is managing each stack
2. Ensure proper labels are set
3. Monitor logs for race conditions
4. Consider separating responsibilities more clearly
If you experience conflicts:
### Service Failures
```bash
# Check which tool is managing your containers
docker ps --format "table {{.Names}}\t{{.Image}}\t{{.Status}}"
If services fail after updates:
1. Check which tool performed the update
2. Verify the update was applied correctly
3. Check for configuration conflicts
4. Review logs for error messages
# Check ComposeSync logs
sudo journalctl -u composesync -f
# Check Watchtower logs
docker logs watchtower
```
### Unexpected Updates
If containers are updating unexpectedly:
```bash
# Check ComposeSync configuration
cat /opt/composesync/config.toml
# Check Watchtower configuration
docker inspect watchtower | grep -A 10 "Env"
# Check container labels
docker inspect your-container | grep -A 5 "Labels"
```
### Performance Issues
If updates are slow or failing:
1. Check resource usage during updates
2. Verify network connectivity
3. Consider staggering update intervals
4. Monitor for resource contention
If you experience performance issues:
## Advanced Configuration
```bash
# Check update frequency
grep "UPDATE_INTERVAL_SECONDS" /opt/composesync/config.toml
### Selective Updates
# Check Watchtower interval
docker inspect watchtower | grep "WATCHTOWER_POLL_INTERVAL"
You can configure both tools to update different aspects:
# Monitor resource usage
docker stats
```
## Recommendations
### For Production Environments
**Use ComposeSync** for production environments because:
- Better control over updates
- Automatic rollback on failures
- Preserves your customizations
- Version-controlled updates
- Better monitoring and logging
### For Development Environments
**Use Watchtower** for development environments because:
- Faster iteration
- Real-time updates
- Simpler setup
- Less configuration overhead
### For Mixed Environments
**Use the hybrid approach** with:
- ComposeSync for critical production stacks
- Watchtower for development and testing stacks
- Clear separation of responsibilities
## Example Configurations
### Production Setup (ComposeSync Only)
```toml
# /opt/composesync/config.toml
[global]
UPDATE_INTERVAL_SECONDS = 86400 # Daily updates
KEEP_VERSIONS = 15
DRY_RUN = false
NOTIFICATION_WEBHOOK_URL = "https://your-webhook.com/endpoint"
[immich]
URL = "https://github.com/immich-app/immich/releases/latest/download/docker-compose.yml"
PATH = "/opt/composesync/stacks/immich"
TOOL = "wget"
[portainer]
URL = "https://github.com/portainer/portainer-compose.git"
PATH = "/opt/composesync/stacks/portainer"
TOOL = "git"
GIT_SUBPATH = "compose/docker-compose.yml"
GIT_REF = "main"
```
### Development Setup (Watchtower Only)
```yaml
# ComposeSync handles compose file updates
# Watchtower handles image updates for specific services
# docker-compose.yml
version: '3.8'
services:
app:
watchtower:
image: containrrr/watchtower
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
- WATCHTOWER_POLL_INTERVAL=1800 # 30 minutes
- WATCHTOWER_CLEANUP=true
- WATCHTOWER_LABEL_ENABLE=true
restart: unless-stopped
dev-app:
image: your-dev-app:latest
labels:
- "com.centurylinklabs.watchtower.enable=true"
- "com.centurylinklabs.watchtower.scope=app"
database:
restart: unless-stopped
```
### Hybrid Setup
```toml
# ComposeSync for production stacks
[global]
UPDATE_INTERVAL_SECONDS = 86400
KEEP_VERSIONS = 10
[production-app]
URL = "https://github.com/user/production-app.git"
PATH = "/opt/composesync/stacks/production"
TOOL = "git"
GIT_REF = "main"
```
```yaml
# Watchtower for development stacks
services:
watchtower:
image: containrrr/watchtower
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
- WATCHTOWER_POLL_INTERVAL=3600
- WATCHTOWER_CLEANUP=true
- WATCHTOWER_LABEL_ENABLE=true
restart: unless-stopped
dev-app:
image: your-dev-app:latest
labels:
- "com.centurylinklabs.watchtower.enable=false"
```
### Update Scheduling
Coordinate update schedules to avoid conflicts:
```env
# ComposeSync: Check every 6 hours
UPDATE_INTERVAL_SECONDS=21600
# Watchtower: Check every 12 hours (different schedule)
# Configure in Watchtower settings
```
### Notification Filtering
Use different webhook endpoints for different tools:
```env
# ComposeSync notifications
NOTIFICATION_WEBHOOK_URL=https://webhook.com/composesync
# Watchtower notifications (separate endpoint)
# Configure in Watchtower settings
```
This allows you to handle notifications differently based on the source.
- "com.centurylinklabs.watchtower.enable=true"
restart: unless-stopped
```