Skip to main content
Glama
docker.ts5.09 kB
import { Logger } from "winston"; import { Docker } from "docker-cli-js"; import { z } from "zod"; import { promises as fsPromises } from "fs"; import * as path from "path"; import * as os from "os"; import * as util from "util"; import { exec } from "child_process"; import { generateDockerFile, parseDockerArgs } from "./docker-helpers.js"; const execPromise = util.promisify(exec); const CA_CERT_FILENAME = "mitm_proxy.crt"; export class DockerService { private docker: Docker; private logger: Logger; private certPath: string; constructor(certPath: string, logger: Logger) { const echo = logger.level === "verbose" || logger.level === "silly"; this.docker = new Docker({ echo }); this.certPath = certPath; this.logger = logger.child({ component: "DockerService" }); } public async createImageWithCa(args: string[]): Promise<string[]> { if (!this.certPath) { return Promise.reject( `CA certificate path is not set. Please provide a valid path.`, ); } await fsPromises.access(this.certPath).catch((accessError) => { return Promise.reject( `CA certificate at '${this.certPath}' is not accessible. Error: ${accessError}`, ); }); const dockerArgs = parseDockerArgs(args); if (!dockerArgs.image) { return Promise.reject(`Failed to parse Docker command.`); } this.logger.debug( `Starting to modify lunar.dev Intercepted Docker image from ${dockerArgs.originalImage}`, ); const detectedOsRaw = await this.detectImageOs(dockerArgs.originalImage); const detectedOs = z .enum(["debian", "ubuntu", "alpine", "centos", "rhel", "fedora"]) .safeParse(detectedOsRaw || ""); if (!detectedOs.success) { return Promise.reject( `Failed to detect OS for image ${dockerArgs.originalImage}.`, ); } const tempDir = await fsPromises .mkdtemp(path.join(os.tmpdir(), "docker-ca-build-")) .catch((mkdtempError) => { return Promise.reject( `Failed to create temporary directory for Docker build: ${mkdtempError}`, ); }); const dockerfilePath = path.join(tempDir, "Dockerfile"); const caCertTempPath = path.join(tempDir, CA_CERT_FILENAME); await fsPromises .copyFile(this.certPath, caCertTempPath) .catch((copyError) => { return Promise.reject( `Failed to copy CA certificate to ${caCertTempPath}: ${copyError}`, ); }); let originalUser = "root"; await this.docker .command(`pull ${dockerArgs.originalImage}`) .catch((pullError) => { return Promise.reject( `Failed to pull original image ${dockerArgs.originalImage}. Error: ${pullError}`, ); }); const inspectOutput = await this.docker.command( `inspect ${dockerArgs.originalImage}`, ); const inspectData = JSON.parse(inspectOutput.raw); if ( inspectData && inspectData.length > 0 && inspectData[0].Config && inspectData[0].Config.User ) { if (inspectData[0].Config.User !== "") { originalUser = inspectData[0].Config.User; } } const dockerFileContent = generateDockerFile(detectedOs.data)({ originalImageName: dockerArgs.originalImage, originalUser, caCertFilename: CA_CERT_FILENAME, }); await fsPromises .writeFile(dockerfilePath, dockerFileContent, "utf8") .catch((writeError) => { return Promise.reject( `Failed to write Dockerfile at ${dockerfilePath}. Error: ${writeError}`, ); }); this.logger.debug( `Building lunar.dev modified Docker image from ${dockerArgs.originalImage}`, ); const buildCommand = `docker build -q -t ${dockerArgs.image} .`; const { stderr } = await execPromise(buildCommand, { cwd: tempDir }).catch( (error) => { return Promise.reject( `Failed to build Docker image ${dockerArgs.image}: ${error}`, ); }, ); if (stderr) { return Promise.reject( `Failed to build Docker image ${dockerArgs.image}.`, ); } this.logger.debug(`Successfully built Docker image ${dockerArgs.image}.`); fsPromises .rm(tempDir, { recursive: true, force: true }) .catch((cleanupError) => { this.logger.error( `Error cleaning up temporary directory ${tempDir}:`, cleanupError, ); }); return dockerArgs.args; } private async detectImageOs(imageName: string): Promise<string> { await this.docker.command(`pull ${imageName}`).catch((pullError) => { return Promise.reject( `Failed to pull image ${imageName}. Error: ${pullError}`, ); }); const commandToRun = `run --rm --entrypoint "" ${imageName} sh -c 'grep -E "^ID=" /etc/os-release | cut -d= -f2'`; const { raw } = await this.docker.command(commandToRun).catch((error) => { return Promise.reject( `Failed to run command to detect OS for image ${imageName}. Error: ${error}`, ); }); return raw.trim(); } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/TheLunarCompany/lunar'

If you have feedback or need assistance with the MCP directory API, please join our Discord server