/** * Docker context - Docker client and operations */ const Docker = require('dockerode'); const { DOCKER } = require('../utilities/constants'); const docker = new Docker(); /** * Pull a Docker image with timeout protection */ function dockerPull(imageName, timeoutMs = DOCKER.TIMEOUT) { return new Promise((resolve, reject) => { const timer = setTimeout( () => reject(new Error(`Docker pull timed out after ${timeoutMs / 1000}s: ${imageName}`)), timeoutMs ); docker.pull(imageName, (err, stream) => { if (err) { clearTimeout(timer); return reject(err); } docker.modem.followProgress(stream, (err, output) => { clearTimeout(timer); if (err) return reject(err); resolve(output); }); }); }); } /** * Find a running Docker container by name substring */ async function findContainerByName(name, opts = { all: false }) { const containers = await docker.listContainers(opts); const match = containers.find(c => c.Names.some(n => n.toLowerCase().includes(name.toLowerCase())) ); return match || null; } /** * Get all host ports currently in use by Docker containers */ async function getUsedPorts() { const containers = await docker.listContainers({ all: false }); const ports = new Set(); for (const c of containers) { for (const p of (c.Ports || [])) { if (p.PublicPort) ports.add(p.PublicPort); } } return ports; } function createDockerContext(dockerSecurity) { return { client: docker, pull: dockerPull, findContainer: findContainerByName, getUsedPorts, security: dockerSecurity, }; } module.exports = { createDockerContext };