import * as plugins from './mod.plugins.js'; import * as helpers from './helpers.js'; import { logger } from '../gitzone.logging.js'; export type ContainerStatus = 'running' | 'stopped' | 'not_exists'; export interface IDockerRunOptions { name: string; image: string; ports?: { [key: string]: string }; volumes?: { [key: string]: string }; environment?: { [key: string]: string }; restart?: string; command?: string; } export class DockerContainer { private smartshell: plugins.smartshell.Smartshell; constructor() { this.smartshell = new plugins.smartshell.Smartshell({ executor: 'bash', }); } /** * Check if Docker is installed and available */ public async checkDocker(): Promise { try { const result = await this.smartshell.exec('docker --version'); return result.exitCode === 0; } catch (error) { return false; } } /** * Get container status */ public async getStatus(containerName: string): Promise { try { // Check if running const runningResult = await this.smartshell.exec( `docker ps --format '{{.Names}}' | grep -q "^${containerName}$"` ); if (runningResult.exitCode === 0) { return 'running'; } // Check if exists but stopped const existsResult = await this.smartshell.exec( `docker ps -a --format '{{.Names}}' | grep -q "^${containerName}$"` ); if (existsResult.exitCode === 0) { return 'stopped'; } return 'not_exists'; } catch (error) { return 'not_exists'; } } /** * Start a container */ public async start(containerName: string): Promise { try { const result = await this.smartshell.exec(`docker start ${containerName}`); return result.exitCode === 0; } catch (error) { return false; } } /** * Stop a container */ public async stop(containerName: string): Promise { try { const result = await this.smartshell.exec(`docker stop ${containerName}`); return result.exitCode === 0; } catch (error) { return false; } } /** * Remove a container */ public async remove(containerName: string, force: boolean = false): Promise { try { const forceFlag = force ? '-f' : ''; const result = await this.smartshell.exec(`docker rm ${forceFlag} ${containerName}`); return result.exitCode === 0; } catch (error) { return false; } } /** * Run a new container */ public async run(options: IDockerRunOptions): Promise { let command = 'docker run -d'; // Add name command += ` --name ${options.name}`; // Add ports if (options.ports) { for (const [hostPort, containerPort] of Object.entries(options.ports)) { command += ` -p ${hostPort}:${containerPort}`; } } // Add volumes if (options.volumes) { for (const [hostPath, containerPath] of Object.entries(options.volumes)) { command += ` -v "${hostPath}:${containerPath}"`; } } // Add environment variables if (options.environment) { for (const [key, value] of Object.entries(options.environment)) { command += ` -e ${key}="${value}"`; } } // Add restart policy if (options.restart) { command += ` --restart ${options.restart}`; } // Add image command += ` ${options.image}`; // Add command if provided if (options.command) { command += ` ${options.command}`; } try { const result = await this.smartshell.exec(command); return result.exitCode === 0; } catch (error) { logger.log('error', `Failed to run container: ${error.message}`); return false; } } /** * Execute a command in a running container */ public async exec(containerName: string, command: string): Promise { try { const result = await this.smartshell.exec(`docker exec ${containerName} ${command}`); if (result.exitCode === 0) { return result.stdout; } return ''; } catch (error) { return ''; } } /** * Get container logs */ public async logs(containerName: string, lines?: number): Promise { try { const tailFlag = lines ? `--tail ${lines}` : ''; const result = await this.smartshell.exec(`docker logs ${tailFlag} ${containerName}`); return result.stdout; } catch (error) { return `Error getting logs: ${error.message}`; } } /** * Check if a container exists */ public async exists(containerName: string): Promise { const status = await this.getStatus(containerName); return status !== 'not_exists'; } /** * Check if a container is running */ public async isRunning(containerName: string): Promise { const status = await this.getStatus(containerName); return status === 'running'; } /** * Wait for a container to be ready */ public async waitForReady(containerName: string, maxAttempts: number = 30): Promise { for (let i = 0; i < maxAttempts; i++) { if (await this.isRunning(containerName)) { return true; } await plugins.smartdelay.delayFor(1000); } return false; } /** * Get container information */ public async inspect(containerName: string): Promise { try { const result = await this.smartshell.exec(`docker inspect ${containerName}`); if (result.exitCode === 0) { return JSON.parse(result.stdout); } return null; } catch (error) { return null; } } }