feat: add 7 new features — exec shell, SSE events, compose import, docker resources, resource limits, email notifications, auto-updates
- Container exec/shell via WebSocket + xterm.js (subtle >_ button on cards) - Live dashboard updates via SSE (resource alerts, health changes, update notices) - Docker Compose import with YAML parsing, preview, and dependency-ordered deploy - Volume & network management modal with disk usage overview - CPU/memory resource limits on deploy and live update - Email SMTP notifications (nodemailer) alongside Discord/Telegram/ntfy - Scheduled auto-update scheduler with maintenance windows (daily/weekly/monthly) New deps: ws, js-yaml, nodemailer Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -190,6 +190,36 @@ module.exports = function({ docker, log, asyncHandler }) {
|
||||
success(res, { logs: logs.toString() });
|
||||
}, 'container-logs'));
|
||||
|
||||
// Update resource limits on a running container
|
||||
router.put('/:id/resources', asyncHandler(async (req, res) => {
|
||||
const container = await getVerifiedContainer(req.params.id);
|
||||
const { memory, cpus } = req.body;
|
||||
const updateConfig = {};
|
||||
|
||||
if (memory !== undefined) {
|
||||
updateConfig.Memory = memory > 0 ? Math.round(memory * 1024 * 1024) : 0; // MB to bytes, 0 = unlimited
|
||||
updateConfig.MemoryReservation = memory > 0 ? Math.round(memory * 1024 * 1024 * 0.5) : 0;
|
||||
}
|
||||
if (cpus !== undefined) {
|
||||
updateConfig.NanoCpus = cpus > 0 ? Math.round(cpus * 1e9) : 0; // 0 = unlimited
|
||||
}
|
||||
|
||||
await container.update(updateConfig);
|
||||
success(res, { message: 'Resource limits updated' });
|
||||
}, 'container-resources'));
|
||||
|
||||
// Get resource limits for a container
|
||||
router.get('/:id/resources', asyncHandler(async (req, res) => {
|
||||
const container = await getVerifiedContainer(req.params.id);
|
||||
const info = await container.inspect();
|
||||
const hc = info.HostConfig;
|
||||
success(res, {
|
||||
memory: hc.Memory ? Math.round(hc.Memory / 1024 / 1024) : 0, // bytes to MB
|
||||
memoryReservation: hc.MemoryReservation ? Math.round(hc.MemoryReservation / 1024 / 1024) : 0,
|
||||
cpus: hc.NanoCpus ? hc.NanoCpus / 1e9 : 0,
|
||||
});
|
||||
}, 'container-resources-get'));
|
||||
|
||||
// Delete container
|
||||
router.delete('/:id', asyncHandler(async (req, res) => {
|
||||
const container = await getVerifiedContainer(req.params.id);
|
||||
|
||||
Reference in New Issue
Block a user