fix: make update system Docker-aware and prevent container modifications

- Added Docker environment detection to prevent in-place updates
- Show Docker-specific update instructions in UI instead of update button
- Provide proper docker pull commands for Docker users
- Updated README with web-based update documentation
- Ensure Docker container immutability is maintained
This commit is contained in:
courtmanr@gmail.com
2025-05-30 16:35:24 +01:00
parent afa1aef98f
commit 3381981bb8
3 changed files with 74 additions and 18 deletions
+19 -1
View File
@@ -465,6 +465,22 @@ For development purposes or running directly from source, see the **[DEVELOPMENT
## 🔄 Updating Pulse
### Web-Based Updates (Non-Docker)
For non-Docker installations, Pulse includes a built-in update mechanism:
1. Open the Settings modal (gear icon in the top right)
2. Scroll to the "Software Updates" section
3. Click "Check for Updates"
4. If an update is available, review the release notes
5. Click "Apply Update" to install it automatically
The update process:
- Backs up your configuration files
- Downloads and applies the update
- Preserves your settings
- Automatically restarts the application
### Community Scripts LXC Installation
If you installed using the Community Scripts method, simply re-run the original installation command:
@@ -477,7 +493,7 @@ The script will detect the existing installation and update it automatically.
### Docker Compose Installation
To update a Docker Compose installation:
Docker deployments must be updated by pulling the new image:
```bash
cd /path/to/your/pulse-config
@@ -487,6 +503,8 @@ docker compose up -d
This pulls the latest image and recreates the container with the new version.
**Note:** The web-based update feature will detect Docker deployments and provide these instructions instead of attempting an in-place update.
### Manual LXC Installation
If you used the manual installation script, update by re-running it:
+28 -16
View File
@@ -39,6 +39,7 @@ class UpdateManager {
currentVersion: this.currentVersion,
latestVersion,
updateAvailable,
isDocker: this.isDockerEnvironment(),
releaseNotes: response.data.body || 'No release notes available',
releaseUrl: response.data.html_url,
publishedAt: response.data.published_at,
@@ -49,7 +50,7 @@ class UpdateManager {
}))
};
console.log(`[UpdateManager] Current version: ${this.currentVersion}, Latest version: ${latestVersion}`);
console.log(`[UpdateManager] Current version: ${this.currentVersion}, Latest version: ${latestVersion}, Docker: ${updateInfo.isDocker}`);
return updateInfo;
} catch (error) {
@@ -104,6 +105,15 @@ class UpdateManager {
}
}
/**
* Check if running in Docker
*/
isDockerEnvironment() {
return process.env.DOCKER_DEPLOYMENT === 'true' ||
require('fs').existsSync('/.dockerenv') ||
(process.env.container === 'docker');
}
/**
* Apply update
*/
@@ -112,6 +122,16 @@ class UpdateManager {
throw new Error('Update already in progress');
}
// Check if running in Docker
if (this.isDockerEnvironment()) {
throw new Error(
'Automatic updates are not supported in Docker deployments. ' +
'Please update your Docker image by pulling the latest version:\n' +
'docker pull rcourtman/pulse:latest\n' +
'or update your docker-compose.yml to use the new version tag.'
);
}
this.updateInProgress = true;
try {
@@ -166,8 +186,6 @@ class UpdateManager {
progressCallback({ phase: 'extract', progress: 100 });
}
// Detect deployment type
const isDocker = process.env.DOCKER_DEPLOYMENT === 'true' || require('fs').existsSync('/.dockerenv');
const pulseDir = path.join(__dirname, '..');
if (progressCallback) {
@@ -207,20 +225,14 @@ class UpdateManager {
// Schedule restart
console.log('[UpdateManager] Scheduling restart...');
setTimeout(() => {
if (isDocker) {
// In Docker, just exit - container will be restarted
console.log('[UpdateManager] Exiting for Docker restart...');
// For systemd/manual deployments, try to restart
console.log('[UpdateManager] Attempting restart...');
// Try systemctl first
execAsync('sudo systemctl restart pulse').catch(() => {
// If systemctl fails, just exit
process.exit(0);
} else {
// For systemd/manual deployments, try to restart
console.log('[UpdateManager] Attempting restart...');
// Try systemctl first
execAsync('sudo systemctl restart pulse').catch(() => {
// If systemctl fails, just exit
process.exit(0);
});
}
});
}, 2000);
// Cleanup
+27 -1
View File
@@ -878,7 +878,33 @@ PulseApp.ui.settings = (() => {
.replace(/^/, '<p class="mb-2">')
.replace(/$/, '</p>');
latestVersionInfo.innerHTML = `<span class="text-green-600 dark:text-green-400">Update available!</span>`;
// Handle Docker deployments differently
if (updateInfo.isDocker) {
latestVersionInfo.innerHTML = `<span class="text-green-600 dark:text-green-400">Update available! (Docker deployment detected)</span>`;
// Replace the apply button with Docker instructions
const applyButton = document.getElementById('apply-update-button');
const buttonContainer = applyButton.parentElement;
buttonContainer.innerHTML = `
<div class="bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-lg p-3">
<p class="text-sm font-medium text-blue-800 dark:text-blue-200 mb-2">Docker Update Instructions:</p>
<ol class="text-sm text-gray-700 dark:text-gray-300 list-decimal list-inside space-y-1">
<li>Pull the latest image: <code class="bg-gray-100 dark:bg-gray-800 px-1 rounded">docker pull rcourtman/pulse:latest</code></li>
<li>Recreate your container with the new image</li>
<li>Or update your docker-compose.yml to version <code class="bg-gray-100 dark:bg-gray-800 px-1 rounded">${updateInfo.latestVersion}</code></li>
</ol>
<a href="${updateInfo.releaseUrl}" target="_blank" class="inline-flex items-center gap-1 mt-2 text-sm text-blue-600 dark:text-blue-400 hover:underline">
View release on GitHub
<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" />
</svg>
</a>
</div>
`;
} else {
latestVersionInfo.innerHTML = `<span class="text-green-600 dark:text-green-400">Update available!</span>`;
}
} else {
updateDetails.classList.add('hidden');
latestVersionInfo.innerHTML = `<span class="text-gray-600 dark:text-gray-400">You are running the latest version</span>`;