mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-08 00:19:42 +02:00
feat(docker): export/import (move a container to another machine) + boot reaper
- src/docker-export.ts: full-image export (pause-consistent commit + save|stream + workspace tar + manifest -> one .codeman-container.tgz) and workspace-only; import validates manifest + per-member sha256, traversal-guards the workspace tar, docker load + quarantine re-tag (never overwrites a local tag). Bounded by runWithConversionLimit; free-space precheck; docker rmi in finally; sealed containers refuse full-image export. - routes: POST /api/docker-cases/:name/export (background + SSE), GET/DELETE /api/docker-exports, GET download, POST /api/docker-cases/import (-> new host+case) - instance-scoped boot reaper (docker-hosts.reapOrphanedDockerContainers) wired after restoreMuxSessions; never touches another instance's containers - SSE docker:exportComplete/exportFailed/importComplete (both registries) - fix: stream pipeline in saveImageToTar so the bundle isn't truncated VERIFIED end-to-end on real docker: full export -> 326MB valid bundle -> delete case -> import -> new container runs from the quarantined image with the workspace file AND the in-image change both restored. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -465,6 +465,26 @@ export const DockerCaseLinkSchema = z.object({
|
||||
.optional(),
|
||||
});
|
||||
|
||||
export const DockerExportSchema = z.object({
|
||||
mode: z.enum(['full', 'workspace']).optional(),
|
||||
});
|
||||
|
||||
export const DockerImportSchema = z.object({
|
||||
// A bare filename resolved WITHIN the exports dir (never an arbitrary path).
|
||||
bundle: z
|
||||
.string()
|
||||
.min(1)
|
||||
.max(300)
|
||||
.regex(/^[a-zA-Z0-9._-]+\.tgz$/, 'Invalid bundle filename'),
|
||||
newCaseName: z.string().regex(/^[a-zA-Z0-9_-]+$/, 'Invalid case name format'),
|
||||
destWorkspacePath: z
|
||||
.string()
|
||||
.min(1)
|
||||
.max(2000)
|
||||
.regex(/^\//, 'Destination path must be absolute')
|
||||
.regex(NO_SHELL_META, 'Invalid characters in destination path'),
|
||||
});
|
||||
|
||||
// ========== Quick Start ==========
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user