Generic Procedures to update Docker Compose installed applications on Ubuntu server VMs
There is an older, shorter version of this process on Pontifex.site but the process keeps getting refined as I acquire more information about best practices,and improved documentation methods, and this post documents the most up to date version of that process.
Note: If you have multiple Docker Compose applications running in a single VM, it is recommended that you use DockPeek for easier management and updates. The installation and usage guide can be found here: How to install DockPeek on an Ubuntu VM with many Docker containers running
Generic Docker Compose Service Update Procedure
NOTE: to see if new docker containers exist for your project, so you can update them, run these commands inside the directory containing the docker-compose.yml file:
1
docker compose pull
Or to be extra careful, specify the specific docker container name - which you can get by running docker ps.
1
docker compose -p speedtest-tracker pull
TL;DR
1
docker compose pull
1
docker compose up -d
1
docker ps
1
docker system prune
Overview
This document provides a standardized procedure for updating Docker services running with docker-compose.yml files on Ubuntu VMs in Proxmox.
Applicable Services
This procedure applies to any Docker Compose-based service including:
- Homepage
- Immich
- LibreNMS
- Jellyfin
- Ghostfolio
- Mealie
- Paperless-ngx
- Any other containerized service
Pre-Update Checklist
- Identify current version of the service
- Check release notes for breaking changes
- Verify backup status
- Schedule maintenance window (if applicable)
- Have SSH access to the VM
- Know the location of docker-compose.yml file
Update Procedure
Step 1: Review Release Notes
Before updating, always review the change log:
1
2
3
# Most projects have releases on GitHub
# Example format:
https://github.com/[organization]/[project]/releases
Look for:
- Breaking changes
- Required migration steps
- New environment variables
- Configuration changes
- Known issues
Common sources:
- GitHub releases page
- Project documentation
- Docker Hub change log
- Project website/blog
Step 2: Create Proxmox VM Snapshot
This is mandatory - snapshots provide instant rollback capability.
Via Proxmox Web Interface:
- Select the VM in Proxmox
- Navigate to Snapshots tab
- Click Take Snapshot
- Name format:
before-[service]-[version]-[date]- Example:
before-immich-2.0.1-20241214
- Example:
- Add description noting current version
- Wait for completion (usually 10-30 seconds)
Via Proxmox CLI:
1
2
# On Proxmox host
qm snapshot [VMID] before-[service]-update --description "Before updating [service] to [version]"
Step 3: Connect to the VM
1
ssh [VM-IP-ADDRESS]
Example:
1
ssh 192.168.1.108
Step 4: Document Current Configuration
Locate docker-compose.yml:
1
2
3
4
# Common locations:
ls -la /home/*/docker/*/docker-compose.yml
ls -la /opt/docker/*/docker-compose.yml
ls -la ~/docker-compose.yml
Inspect running container:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# List running containers
docker ps
# Get detailed configuration
docker inspect [container-name]
# View mounts
docker inspect [container-name] --format='' | jq
# View environment variables
docker inspect [container-name] --format='' | jq
# View restart policy
docker inspect [container-name] --format=''
Save current configuration:
1
2
# Optional: Backup docker-compose.yml
cp docker-compose.yml docker-compose.yml.backup-$(date +%Y%m%d)
Step 5: Navigate to Service Directory
1
cd /path/to/service/docker-compose-directory/
Examples:
1
2
3
cd /home/mark/docker/homepage/
cd /opt/docker/immich/
cd ~/jellyfin/
Step 6: Review docker-compose.yml
1
cat docker-compose.yml
Check image tag:
latest- Always pulls the newest versionv1.2.3- Pinned to specific versionstable- Follows stable channel2- Follows major version
Note the current tag before updating.
Step 7: Pull New Image(s)
For single service:
1
docker compose pull
For specific service in multi-container setup:
1
docker compose pull [service-name]
Manually pull specific version (if needed):
1
docker pull [image]:[tag]
Expected output:
1
2
[+] Running 1/1
✔ [service] Pulled
Step 8: Check for Migration Requirements
Some services require database migrations or configuration updates:
1
2
3
4
5
6
# Check service documentation for migration steps
# Examples:
# Immich often requires migrations between major versions
# Paperless-ngx may need to run migrations
# LibreNMS requires database updates
Common migration patterns:
1
2
3
4
5
# Run one-time migration command
docker compose run --rm [service] migrate
# Or via docker exec
docker exec [container] /app/migrate.sh
Step 9: Update the Service
Standard update (recreates containers):
1
docker compose up -d
What this does:
- Stops existing container(s)
- Removes old container(s)
- Creates new container(s) with updated image
- Preserves volumes and networks
- Starts container(s) in detached mode
Force recreate (if compose doesn’t detect changes):
1
docker compose up -d --force-recreate
For specific service only:
1
docker compose up -d [service-name]
Step 10: Verify Service Health
Check container status:
1
docker ps | grep [service-name]
Look for:
- Status: “Up” (not “Restarting”)
- Health: “healthy” (if health checks configured)
View real-time logs:
1
docker compose logs -f
Or specific service:
1
docker compose logs -f [service-name]
Press Ctrl+C to exit log view.
Check last 50 log lines:
1
docker compose logs --tail 50
Look for errors:
1
2
3
docker compose logs | grep -i error
docker compose logs | grep -i fail
docker compose logs | grep -i fatal
Step 11: Test Service Functionality
Web-based services:
1
2
# Access via browser
http://[VM-IP]:[PORT]
Verify:
- Service loads without errors
- Login works (if applicable)
- Main features function correctly
- Data is intact and accessible
- API endpoints respond (if applicable)
- Background jobs running (if applicable)
CLI-based verification:
1
2
3
4
5
# Example: Test API endpoint
curl http://localhost:[PORT]/api/health
# Example: Check database connection
docker compose exec [service] /check-db.sh
Step 12: Clean Up Old Images (Optional)
After successful update, remove old images to free space:
1
2
3
4
5
6
7
8
# List all images
docker images
# Remove specific old image
docker rmi [image]:[old-tag]
# Or clean up all unused images
docker image prune -a
Warning: Only do this after confirming the update works!
Rollback Procedures
Option 1: Proxmox Snapshot Rollback (Fastest)
Use when:
- Service won’t start
- Data corruption detected
- Critical functionality broken
Steps:
- Stop the VM from Proxmox interface
- Navigate to VM → Snapshots tab
- Select the pre-update snapshot
- Click Rollback
- Confirm the rollback
- Start the VM
Result: Complete system state restored to pre-update.
Option 2: Docker Image Downgrade (Targeted)
Use when:
- Only the service needs rollback
- VM configuration changes should be kept
- Faster than full VM rollback
Steps:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# Navigate to service directory
cd /path/to/service/
# Edit docker-compose.yml
nano docker-compose.yml
# Change image tag back to previous version
# From: image: service:latest
# To: image: service:v1.2.3
# Stop and remove containers
docker compose down
# Pull the old version
docker compose pull
# Start with old version
docker compose up -d
# Verify
docker compose logs -f
Option 3: Emergency Recovery
If service is completely broken:
1
2
3
4
5
6
7
8
9
# Stop everything
docker compose down
# Remove volumes (WARNING: DATA LOSS)
docker compose down -v
# Restore from backup (if available)
# Then recreate fresh
docker compose up -d
Best Practices
Timing
- Update during low-usage periods
- Avoid updating multiple services simultaneously
- Test updates in development/staging first (if available)
Documentation
- Keep a change log of updates in
/home/[user]/update-log.txt - Note version numbers before and after
- Document any issues encountered
Backup Verification
- Test backup restoration periodically
- Verify automated backups are running
- Keep multiple snapshot/backup generations
Version Pinning
Consider pinning to specific versions instead of latest:
1
2
3
4
5
# Instead of:
image: immich:latest
# Use:
image: immich:v2.0.1
Advantages:
- Predictable updates
- Easier rollback
- Better change control
Disadvantages:
- Manual version tracking required
- May miss security patches
Service-Specific Notes
Immich
- Check for database migrations between major versions
- Review migration guide
- May require PostgreSQL updates
LibreNMS
- Often requires database schema updates
- Run:
docker exec librenms /opt/librenms/daily.sh - Verify poller is running
Jellyfin
- Usually straightforward updates
- May need to rebuild library metadata
- Check plugin compatibility
Paperless-ngx
- May require document re-indexing
- Check for OCR engine updates
- Verify consumption folder permissions
Ghostfolio
- Database migrations may be required
- Check portfolio calculation accuracy post-update
Troubleshooting
Container Won’t Start
1
2
3
4
5
6
7
8
9
10
11
# Check detailed logs
docker compose logs [service]
# Verify image was pulled
docker images | grep [service]
# Check resource usage
docker stats
# Verify port availability
sudo netstat -tulpn | grep [PORT]
Permission Errors
1
2
3
4
5
6
7
8
# Check volume permissions
ls -la /path/to/volume/
# Fix permissions (adjust user:group as needed)
sudo chown -R 1000:1000 /path/to/volume/
# Check SELinux (if applicable)
getenforce
Database Connection Issues
1
2
3
4
5
6
7
8
9
# Check database container
docker compose ps
# Verify database is ready
docker compose logs [db-service] | grep ready
# Test database connection
docker compose exec [db-service] pg_isready # PostgreSQL
docker compose exec [db-service] mysqladmin ping # MySQL
Network Issues
1
2
3
4
5
6
7
8
9
# List networks
docker network ls
# Inspect network
docker network inspect [network-name]
# Recreate network (be cautious)
docker network rm [network-name]
docker network create [network-name]
Out of Disk Space
1
2
3
4
5
6
7
8
9
10
# Check disk usage
df -h
# Clean Docker system
docker system df
docker system prune -a
# Remove old volumes (careful!)
docker volume ls
docker volume prune
Automation Considerations
Update Notification Tools
- Diun - Docker Image Update Notifier
- Watchtower - Automated updates (use with caution)
- Portainer - GUI for Docker management
Monitoring
- Set up health checks in docker-compose.yml
- Use Uptime Kuma or similar for service monitoring
- Configure alerting for service downtime
Emergency Contacts
- Service documentation: Check GitHub/official site
- Docker logs location:
/var/lib/docker/containers/[container-id]/[container-id]-json.log - Proxmox backups:
/var/lib/vz/dump/(on Proxmox host)
Standard Update Command Summary
1
2
3
4
5
# Quick reference for standard update
cd /path/to/service/
docker compose pull
docker compose up -d
docker compose logs -f
Checklist Template
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
## Update Checklist - [Service Name] - [Date]
- [ ] Current version documented: ______
- [ ] Release notes reviewed
- [ ] Breaking changes identified: Yes / No
- [ ] Proxmox snapshot created: [Snapshot Name]
- [ ] docker-compose.yml location: ______
- [ ] Configuration backed up
- [ ] Image pulled successfully
- [ ] Migration steps completed (if any)
- [ ] Service updated
- [ ] Logs checked for errors
- [ ] Functionality verified
- [ ] Old images cleaned up
- [ ] Update logged in documentation
- [ ] Snapshot deleted (after 7 days)
## Issues Encountered
[None / List any issues]
## New version: ______
Save this checklist for each update to maintain an audit trail.