Skip to content

Commit ea14f17

Browse files
committed
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
1 parent 81320b1 commit ea14f17

File tree

3 files changed

+74
-18
lines changed

3 files changed

+74
-18
lines changed

README.md

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,22 @@ For development purposes or running directly from source, see the **[DEVELOPMENT
465465

466466
## 🔄 Updating Pulse
467467

468+
### Web-Based Updates (Non-Docker)
469+
470+
For non-Docker installations, Pulse includes a built-in update mechanism:
471+
472+
1. Open the Settings modal (gear icon in the top right)
473+
2. Scroll to the "Software Updates" section
474+
3. Click "Check for Updates"
475+
4. If an update is available, review the release notes
476+
5. Click "Apply Update" to install it automatically
477+
478+
The update process:
479+
- Backs up your configuration files
480+
- Downloads and applies the update
481+
- Preserves your settings
482+
- Automatically restarts the application
483+
468484
### Community Scripts LXC Installation
469485

470486
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.
477493

478494
### Docker Compose Installation
479495

480-
To update a Docker Compose installation:
496+
Docker deployments must be updated by pulling the new image:
481497

482498
```bash
483499
cd /path/to/your/pulse-config
@@ -487,6 +503,8 @@ docker compose up -d
487503

488504
This pulls the latest image and recreates the container with the new version.
489505

506+
**Note:** The web-based update feature will detect Docker deployments and provide these instructions instead of attempting an in-place update.
507+
490508
### Manual LXC Installation
491509

492510
If you used the manual installation script, update by re-running it:

server/updateManager.js

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ class UpdateManager {
3939
currentVersion: this.currentVersion,
4040
latestVersion,
4141
updateAvailable,
42+
isDocker: this.isDockerEnvironment(),
4243
releaseNotes: response.data.body || 'No release notes available',
4344
releaseUrl: response.data.html_url,
4445
publishedAt: response.data.published_at,
@@ -49,7 +50,7 @@ class UpdateManager {
4950
}))
5051
};
5152

52-
console.log(`[UpdateManager] Current version: ${this.currentVersion}, Latest version: ${latestVersion}`);
53+
console.log(`[UpdateManager] Current version: ${this.currentVersion}, Latest version: ${latestVersion}, Docker: ${updateInfo.isDocker}`);
5354
return updateInfo;
5455

5556
} catch (error) {
@@ -104,6 +105,15 @@ class UpdateManager {
104105
}
105106
}
106107

108+
/**
109+
* Check if running in Docker
110+
*/
111+
isDockerEnvironment() {
112+
return process.env.DOCKER_DEPLOYMENT === 'true' ||
113+
require('fs').existsSync('/.dockerenv') ||
114+
(process.env.container === 'docker');
115+
}
116+
107117
/**
108118
* Apply update
109119
*/
@@ -112,6 +122,16 @@ class UpdateManager {
112122
throw new Error('Update already in progress');
113123
}
114124

125+
// Check if running in Docker
126+
if (this.isDockerEnvironment()) {
127+
throw new Error(
128+
'Automatic updates are not supported in Docker deployments. ' +
129+
'Please update your Docker image by pulling the latest version:\n' +
130+
'docker pull rcourtman/pulse:latest\n' +
131+
'or update your docker-compose.yml to use the new version tag.'
132+
);
133+
}
134+
115135
this.updateInProgress = true;
116136

117137
try {
@@ -166,8 +186,6 @@ class UpdateManager {
166186
progressCallback({ phase: 'extract', progress: 100 });
167187
}
168188

169-
// Detect deployment type
170-
const isDocker = process.env.DOCKER_DEPLOYMENT === 'true' || require('fs').existsSync('/.dockerenv');
171189
const pulseDir = path.join(__dirname, '..');
172190

173191
if (progressCallback) {
@@ -207,20 +225,14 @@ class UpdateManager {
207225
// Schedule restart
208226
console.log('[UpdateManager] Scheduling restart...');
209227
setTimeout(() => {
210-
if (isDocker) {
211-
// In Docker, just exit - container will be restarted
212-
console.log('[UpdateManager] Exiting for Docker restart...');
228+
// For systemd/manual deployments, try to restart
229+
console.log('[UpdateManager] Attempting restart...');
230+
231+
// Try systemctl first
232+
execAsync('sudo systemctl restart pulse').catch(() => {
233+
// If systemctl fails, just exit
213234
process.exit(0);
214-
} else {
215-
// For systemd/manual deployments, try to restart
216-
console.log('[UpdateManager] Attempting restart...');
217-
218-
// Try systemctl first
219-
execAsync('sudo systemctl restart pulse').catch(() => {
220-
// If systemctl fails, just exit
221-
process.exit(0);
222-
});
223-
}
235+
});
224236
}, 2000);
225237

226238
// Cleanup

src/public/js/ui/settings.js

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -878,7 +878,33 @@ PulseApp.ui.settings = (() => {
878878
.replace(/^/, '<p class="mb-2">')
879879
.replace(/$/, '</p>');
880880

881-
latestVersionInfo.innerHTML = `<span class="text-green-600 dark:text-green-400">Update available!</span>`;
881+
// Handle Docker deployments differently
882+
if (updateInfo.isDocker) {
883+
latestVersionInfo.innerHTML = `<span class="text-green-600 dark:text-green-400">Update available! (Docker deployment detected)</span>`;
884+
885+
// Replace the apply button with Docker instructions
886+
const applyButton = document.getElementById('apply-update-button');
887+
const buttonContainer = applyButton.parentElement;
888+
889+
buttonContainer.innerHTML = `
890+
<div class="bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-lg p-3">
891+
<p class="text-sm font-medium text-blue-800 dark:text-blue-200 mb-2">Docker Update Instructions:</p>
892+
<ol class="text-sm text-gray-700 dark:text-gray-300 list-decimal list-inside space-y-1">
893+
<li>Pull the latest image: <code class="bg-gray-100 dark:bg-gray-800 px-1 rounded">docker pull rcourtman/pulse:latest</code></li>
894+
<li>Recreate your container with the new image</li>
895+
<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>
896+
</ol>
897+
<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">
898+
View release on GitHub
899+
<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
900+
<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" />
901+
</svg>
902+
</a>
903+
</div>
904+
`;
905+
} else {
906+
latestVersionInfo.innerHTML = `<span class="text-green-600 dark:text-green-400">Update available!</span>`;
907+
}
882908
} else {
883909
updateDetails.classList.add('hidden');
884910
latestVersionInfo.innerHTML = `<span class="text-gray-600 dark:text-gray-400">You are running the latest version</span>`;

0 commit comments

Comments
 (0)