shubhjn commited on
Commit
ea4bb9b
·
1 Parent(s): 7cdbd2a

fix boot error

Browse files
Files changed (3) hide show
  1. Dockerfile +3 -1
  2. lib/docker/manager.ts +79 -1
  3. test-fallback.ts +26 -0
Dockerfile CHANGED
@@ -33,7 +33,9 @@ FROM base AS runner
33
  WORKDIR /app
34
 
35
  # Add libc6-compat and other runtimes for native modules (node-pty)
36
- RUN apk add --no-cache libc6-compat python3 make g++ git
 
 
37
 
38
  ENV NODE_ENV production
39
  ENV NEXT_TELEMETRY_DISABLED 1
 
33
  WORKDIR /app
34
 
35
  # Add libc6-compat and other runtimes for native modules (node-pty)
36
+ # Also add code-server for Native Isolation Mode (when Docker is missing)
37
+ RUN apk add --no-cache libc6-compat python3 make g++ git \
38
+ && npm install -g code-server --unsafe-perm
39
 
40
  ENV NODE_ENV production
41
  ENV NEXT_TELEMETRY_DISABLED 1
lib/docker/manager.ts CHANGED
@@ -1,10 +1,23 @@
1
  import Docker from 'dockerode';
2
  import path from 'path';
 
 
3
 
4
  // Connect to the local Docker daemon
5
- // This assumes Docker Desktop or Docker Engine is running locally and accessible
6
  const docker = new Docker({ socketPath: process.platform === 'win32' ? '//./pipe/docker_engine' : '/var/run/docker.sock' });
7
 
 
 
 
 
 
 
 
 
 
 
 
 
8
  export interface WorkspaceConfig {
9
  id: string;
10
  userId: string;
@@ -14,12 +27,69 @@ export interface WorkspaceConfig {
14
  onLog?: (msg: string) => void;
15
  }
16
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  /**
18
  * Initializes and starts a Dockerized VS Code Code-Server instance for the given workspace ID.
19
  * Optionally spins up a sidecar Android emulator container.
20
  */
21
  export async function startWorkspaceContainer(config: WorkspaceConfig) {
22
  const { id, userId, projectName, withAndroidEmulator = false, onLog = console.log } = config;
 
 
 
 
 
 
23
  const containerName = `codeverse-workspace-${id}`;
24
  const androidContainerName = `codeverse-android-${id}`;
25
 
@@ -191,6 +261,14 @@ export async function startWorkspaceContainer(config: WorkspaceConfig) {
191
  * Stops and optionally removes a workspace container and its sidecars.
192
  */
193
  export async function stopWorkspaceContainer(id: string, remove = false) {
 
 
 
 
 
 
 
 
194
  const containerName = `codeverse-workspace-${id}`;
195
  const androidContainerName = `codeverse-android-${id}`;
196
 
 
1
  import Docker from 'dockerode';
2
  import path from 'path';
3
+ import { spawn, ChildProcess } from 'child_process';
4
+ import { existsSync } from 'fs';
5
 
6
  // Connect to the local Docker daemon
 
7
  const docker = new Docker({ socketPath: process.platform === 'win32' ? '//./pipe/docker_engine' : '/var/run/docker.sock' });
8
 
9
+ // Native process registry to manage non-docker workspaces (HF Fallback)
10
+ const nativeProcesses = new Map<string, { process: ChildProcess, port: number }>();
11
+
12
+ async function isDockerAvailable(): Promise<boolean> {
13
+ try {
14
+ await docker.ping();
15
+ return true;
16
+ } catch {
17
+ return false;
18
+ }
19
+ }
20
+
21
  export interface WorkspaceConfig {
22
  id: string;
23
  userId: string;
 
27
  onLog?: (msg: string) => void;
28
  }
29
 
30
+ /**
31
+ * Native Mode Fallback: Starts code-server as a child process if Docker is missing.
32
+ */
33
+ async function startNativeWorkspace(config: WorkspaceConfig) {
34
+ const { id, userId, projectName, onLog = console.log } = config;
35
+
36
+ if (nativeProcesses.has(id)) {
37
+ const existing = nativeProcesses.get(id)!;
38
+ return { success: true, containerId: `native-${id}`, port: String(existing.port) };
39
+ }
40
+
41
+ onLog("[SYSTEM] Docker not detected. Entering Native Isolation Mode...");
42
+
43
+ // HF standard: use /app/workspaces or the resolved mount
44
+ const safeName = projectName.replace(/[^a-zA-Z0-9-_]/g, "-").slice(0, 60);
45
+ const dataPath = path.resolve(process.cwd(), 'workspaces', userId, safeName);
46
+
47
+ // Simple port allocation (multi-workspace on HF isn't common but we handle it)
48
+ const port = 8080 + nativeProcesses.size;
49
+
50
+ onLog(`[NATIVE] Booting code-server for ${projectName} on port ${port}...`);
51
+
52
+ const child = spawn('code-server', [
53
+ '--auth', 'none',
54
+ '--port', String(port),
55
+ '--disable-telemetry',
56
+ '--bind-addr', `0.0.0.0:${port}`,
57
+ dataPath
58
+ ], {
59
+ env: { ...process.env, HOME: dataPath },
60
+ shell: true
61
+ });
62
+
63
+ child.stdout.on('data', (data) => onLog(`[NATIVE-STDOUT] ${data}`));
64
+ child.stderr.on('data', (data) => onLog(`[NATIVE-STDERR] ${data}`));
65
+
66
+ nativeProcesses.set(id, { process: child, port });
67
+
68
+ // Give it a moment to bind
69
+ await new Promise(resolve => setTimeout(resolve, 2000));
70
+
71
+ return {
72
+ success: true,
73
+ containerId: `native-${id}`,
74
+ port: String(port),
75
+ androidContainerId: null,
76
+ androidPort: null,
77
+ appetizeUrl: null
78
+ };
79
+ }
80
+
81
  /**
82
  * Initializes and starts a Dockerized VS Code Code-Server instance for the given workspace ID.
83
  * Optionally spins up a sidecar Android emulator container.
84
  */
85
  export async function startWorkspaceContainer(config: WorkspaceConfig) {
86
  const { id, userId, projectName, withAndroidEmulator = false, onLog = console.log } = config;
87
+
88
+ // Check availability first
89
+ if (!await isDockerAvailable()) {
90
+ return startNativeWorkspace(config);
91
+ }
92
+
93
  const containerName = `codeverse-workspace-${id}`;
94
  const androidContainerName = `codeverse-android-${id}`;
95
 
 
261
  * Stops and optionally removes a workspace container and its sidecars.
262
  */
263
  export async function stopWorkspaceContainer(id: string, remove = false) {
264
+ // Check Native Mode first
265
+ if (nativeProcesses.has(id)) {
266
+ const { process: child } = nativeProcesses.get(id)!;
267
+ child.kill();
268
+ nativeProcesses.delete(id);
269
+ return { success: true };
270
+ }
271
+
272
  const containerName = `codeverse-workspace-${id}`;
273
  const androidContainerName = `codeverse-android-${id}`;
274
 
test-fallback.ts ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { startWorkspaceContainer } from './lib/docker/manager';
2
+
3
+ async function testNativeFallback() {
4
+ console.log("--- NATIVE FALLBACK TEST ---");
5
+ try {
6
+ const result = await startWorkspaceContainer({
7
+ id: 'test-id',
8
+ userId: 'test-user',
9
+ projectName: 'test-project',
10
+ onLog: (msg) => console.log(`[TEST-LOG] ${msg}`)
11
+ });
12
+
13
+ console.log("Test Result:", JSON.stringify(result, null, 2));
14
+
15
+ if (result.containerId.startsWith('native-')) {
16
+ console.log("SUCCESS: Fallback to Native Mode detected.");
17
+ } else {
18
+ console.log("INFO: Docker was available, running in Docker mode.");
19
+ }
20
+
21
+ } catch (error) {
22
+ console.error("TEST FAILED:", error);
23
+ }
24
+ }
25
+
26
+ testNativeFallback();