UNPKG

@wocker/ws

Version:

Docker workspace for web projects

247 lines (246 loc) 8.71 kB
"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.DockerService = void 0; const core_1 = require("@wocker/core"); const ContainerService_1 = require("./ContainerService"); const ModemService_1 = require("./ModemService"); const ImageService_1 = require("./ImageService"); let DockerService = class DockerService extends core_1.DockerService { constructor(modemService, containerService, imageService, logService) { super(); this.modemService = modemService; this.containerService = containerService; this.imageService = imageService; this.logService = logService; } get docker() { return this.modemService.docker; } async createVolume(name) { return await this.docker.createVolume({ Name: name, Driver: "local" }); } async hasVolume(name) { const volume = await this.getVolume(name); try { await volume.inspect(); return true; } catch (err) { return false; } } async getVolume(name) { return this.docker.getVolume(name); } async rmVolume(name) { const volume = await this.getVolume(name); await volume.remove(); } async createContainer(params) { const { name, user, entrypoint, tty, image, projectId, restart, memory, memorySwap, ulimits, extraHosts, networkMode = "bridge", links = [], env = {}, volumes = [], ports = [], cmd = [], network: networkName = "workspace", aliases } = params; const network = this.docker.getNetwork(networkName); try { await network.inspect(); } catch (err) { if (err.statusCode === 404) { await this.docker.createNetwork({ Name: networkName }); } } await this.pullImage(image); return this.docker.createContainer({ name, User: user, Image: image, Hostname: name, Domainname: name, Labels: { ...projectId ? { projectId } : {} }, AttachStdin: true, AttachStdout: true, AttachStderr: true, OpenStdin: true, StdinOnce: false, Entrypoint: entrypoint, Tty: true, Cmd: cmd, Env: Object.keys(env).map((key) => { const value = env[key]; return `${key}=${value}`; }), ExposedPorts: ports.reduce((res, value) => { const [, , containerPort, type = "tcp"] = /(\d+):(\d+)(?:\/(\w+))?/.exec(value) || []; if (containerPort) { res[`${containerPort}/${type}`] = {}; } return res; }, {}), HostConfig: { Memory: memory, MemorySwap: memorySwap, NetworkMode: networkMode, ExtraHosts: extraHosts, Ulimits: ulimits ? Object.keys(ulimits).reduce((res, name) => { return [ ...res, { Name: name, Hard: ulimits[name].hard, Soft: ulimits[name].soft } ]; }, []) : [], ...restart ? { RestartPolicy: { Name: restart } } : {}, Binds: volumes, PortBindings: ports.reduce((res, value) => { const [, hostPort, containerPort, type = "tcp"] = /(\d+):(\d+)(?:\/(\w+))?/.exec(value) || []; if (hostPort && containerPort) { res[`${containerPort}/${type}`] = [ { HostPort: hostPort } ]; } else { this.logService.warn(`Invalid port format for container "${name}": "${value}". Expected format: hostPort:containerPort[/protocol]`); } return res; }, {}) }, NetworkingConfig: { EndpointsConfig: networkMode === "host" ? {} : { [networkName]: { Links: links, Aliases: aliases || (env.VIRTUAL_HOST ? env.VIRTUAL_HOST.split(",") : undefined) } } } }); } async getContainer(name) { return this.containerService.get(name); } async removeContainer(name) { await this.containerService.rm(name); } async buildImage(params) { await this.imageService.build(params); } async imageExists(tag) { return this.imageService.exists(tag); } async imageRm(tag, force = false) { await this.imageService.rm(tag, force); } async imageLs(options) { const { tag, reference, labels } = options || {}; const filters = {}; if (reference) { filters.reference = [ ...filters.reference || [], ...reference ]; } if (tag) { filters.reference = [ ...filters.reference || [], tag ]; } if (labels) { filters.label = []; for (const i in labels) { filters.label.push(`${i}=${labels[i]}`); } } return this.docker.listImages({ filters: JSON.stringify(filters) }); } async pullImage(tag) { await this.imageService.pull(tag); } async attach(containerOrName) { let container = typeof containerOrName === "string" ? await this.getContainer(containerOrName) : containerOrName; if (!container) { return; } const stream = await container.attach({ stream: true, hijack: true, stdin: true, stdout: true, stderr: true, logs: true, detachKeys: "ctrl-d" }); await this.attachStream(stream); const handleResize = () => { const [width, height] = process.stdout.getWindowSize(); container.resize({ w: width, h: height }); }; process.stdout.on("resize", handleResize); handleResize(); return stream; } async attachStream(stream) { return this.modemService.attachStream(stream); } async exec(nameOrContainer, options, _tty) { return await this.containerService.exec(nameOrContainer, options, _tty); } async logs(containerOrName) { const container = typeof containerOrName === "string" ? await this.getContainer(containerOrName) : containerOrName; if (!container) { return; } const stream = await container.logs({ stdout: true, stderr: true, follow: true, tail: 4 }); stream.on("data", (data) => { process.stdout.write(data); }); stream.on("error", (data) => { process.stderr.write(data); }); return stream; } async followProgress(stream) { await this.modemService.followProgress(stream); } }; exports.DockerService = DockerService; exports.DockerService = DockerService = __decorate([ (0, core_1.Injectable)("DOCKER_SERVICE"), __metadata("design:paramtypes", [ModemService_1.ModemService, ContainerService_1.ContainerService, ImageService_1.ImageService, core_1.LogService]) ], DockerService);