UNPKG

alwaysai

Version:

The alwaysAI command-line interface (CLI)

220 lines (205 loc) 5.39 kB
import { CliTerseError } from '@alwaysai/alwayscli'; import * as winston from 'winston'; import { TargetHardware } from '../../core/app'; import { ALWAYSAI_SYSTEM_ID } from '../../environment'; import { logger } from '../logger'; import { Spawner } from '../spawner'; import { stringifyError } from '../stringify-error'; export async function buildDockerImage(props: { targetHostSpawner: Spawner; targetHardware?: string; dockerImageTag?: string; dockerfilePath?: string; pullBaseImage?: boolean; runInForeground?: boolean; logger?: winston.Logger; }) { const { targetHostSpawner, targetHardware, dockerImageTag, dockerfilePath, pullBaseImage, runInForeground, logger } = props; let args = ['build', '--network=host']; if (targetHardware) { args = args.concat(['--build-arg', `ALWAYSAI_HW=${targetHardware}`]); } if (dockerImageTag) { args = args.concat(['-t', dockerImageTag]); } if (dockerfilePath) { args = args.concat(['-f', dockerfilePath]); } if (pullBaseImage) { args = args.concat(['--pull']); } // first run to see build logs if (runInForeground) { // On Windows, stream to stdout to prevent garbled log output if (process.platform === 'win32') { const dockerLogs = await targetHostSpawner.runStreaming({ exe: 'docker', args: args.concat(['.']), cwd: '.' }); dockerLogs.pipe(process.stdout); } else { targetHostSpawner.runForegroundSync({ exe: 'docker', args: args.concat(['.']), cwd: '.' }); } } else { // NOTE: Seeing errors with streaming logs to readable stream so sending all-at-once for now. // See: // * https://github.com/winstonjs/winston/issues/1339 // * https://github.com/sponja23/winston-stream-wrapper/blob/main/src/index.ts const dockerLogs = await targetHostSpawner.run({ exe: 'docker', args: args.concat(['.']), cwd: '.' }); logger?.debug(dockerLogs); } // second run returns an output - docker does not rebuild it but it returns the success message const output = await targetHostSpawner.run({ exe: 'docker', args: args.concat(['--quiet', '.']), cwd: '.' }); const dockerImageId = output.trim(); logger?.info(`Built ${dockerImageId}`); return dockerImageId; } export async function pullDockerImage(props: { targetHostSpawner: Spawner; dockerImageId: string; }) { const { targetHostSpawner, dockerImageId } = props; const dockerArgs: string[] = ['pull', dockerImageId]; try { await targetHostSpawner.run({ exe: 'docker', args: dockerArgs, cwd: '.' }); } catch (err) { logger.error(stringifyError(err)); throw new CliTerseError( `Pull access denied for ${dockerImageId}, repository does not exist or may require 'docker login'.` ); } } export type DockerRunCmd = { dockerImageId: string; pullImage?: boolean; remove?: boolean; interactive?: boolean; tty?: boolean; volumes?: string[]; env_vars?: string[]; user?: string; ports?: string[]; targetHardware?: TargetHardware; workdir?: string; detach?: boolean; restart?: string; exe?: string; exeArgs?: string[]; }; export function getDockerRunCmd(cmd: DockerRunCmd) { const args: string[] = ['run', '--privileged']; if (ALWAYSAI_SYSTEM_ID) { args.push('--env', `ALWAYSAI_SYSTEM_ID=${ALWAYSAI_SYSTEM_ID}`); } if (cmd.remove) { args.push('--rm'); } if (cmd.pullImage) { args.push('--pull', 'always'); } if (cmd.interactive) { args.push('--interactive'); } if (cmd.tty) { args.push('--tty'); } if (cmd.volumes) { for (const v of cmd.volumes) { args.push('--volume', v); } } if (cmd.env_vars) { for (const e of cmd.env_vars) { args.push('--env', e); } } if (cmd.user) { args.push('--user', cmd.user); } if (cmd.ports) { for (const p of cmd.ports) { args.push('--publish', `127.0.0.1:${p}:${p}/tcp`); } } else { args.push('--network=host'); } if ( cmd.targetHardware?.includes('jetson') || cmd.targetHardware?.includes('x86-trt') ) { args.push('--runtime=nvidia'); } if (cmd.targetHardware?.includes('jetson')) { args.push('--ipc=host'); args.push('--volume'); args.push('/tmp/argus_socket:/tmp/argus_socket'); } if (cmd.workdir) { args.push('--workdir', cmd.workdir); } if (cmd.detach) { args.push('--detach'); } if (cmd.restart) { args.push('--restart', cmd.restart); } args.push(cmd.dockerImageId); if (cmd.exe) { args.push(cmd.exe); if (cmd.exeArgs) { args.push(...cmd.exeArgs); } } return args; } export async function runDockerContainer(props: { targetHostSpawner: Spawner; cmd: DockerRunCmd; }) { const { targetHostSpawner, cmd } = props; const dockerArgs = getDockerRunCmd(cmd); const output = await targetHostSpawner.run({ exe: 'docker', args: dockerArgs, cwd: '.' }); const containerId = output.trim(); return containerId; } export async function runDockerContainerForeground(props: { targetHostSpawner: Spawner; cmd: DockerRunCmd; }) { const { targetHostSpawner, cmd } = props; const dockerArgs = getDockerRunCmd(cmd); await targetHostSpawner.runForeground({ exe: 'docker', args: dockerArgs, cwd: '.' }); }