Сайт

Докер

sdk.docker управляет Docker-контейнерами на машине пользователя через CLI docker. Обычно им пользуются окестраторы, поднимающие локальный бэкенд. Разрешение не требуется, работает только в десктопном приложении: в веб-приложении проверки доступности возвращают false, а остальные вызовы завершаются ошибкой.

Проверка доступности

isDockerInstalled(): Promise<DockerVersionInfo | false>
isComposeInstalled(): Promise<ComposeVersionInfo | false>

Оба метода возвращают информацию о версии, если она доступна, и false в противном случае.

  • isDockerInstalled возвращает version, apiVersion, os и arch клиента Docker. Возвращает false, если CLI нет или docker version завершается с ошибкой — например, когда Docker daemon не запущен.
  • isComposeInstalled проверяет docker compose (Compose v2) и возвращает его version. Отдельный бинарник docker-compose не определяется.

Запуск контейнеров

dockerUp(request: SdkDockerUpRequest): Promise<SdkDockerUpResponse>

Выполняет docker compose up для проекта, затем при необходимости инспектирует один контейнер.

| Поле | Тип | Описание | | --- | --- | --- | | project | string \| ComposeProject | Собственный compose-проект. Строка — это путь к compose-файлу: имя проекта — имя его папки, команды выполняются в этой папке. Приоритетнее preset. | | preset | 'orchestrator-local' \| 'orchestrator-go-local' | Встроенный в приложение compose-конфиг локальных бэкендов окестраторов Fragmenta. Оба запускаются как проект orchestrator. | | options | ComposeUpOptions | Флаги для compose up (ниже). | | containerId | string | Идентификатор или имя контейнера для инспекции после up. Без него ответ — {}. | | waitForHealthy | boolean | Вместе с containerId — дождаться healthy-состояния (см. waitForHealthy в разделе «Инспекция»), а не инспектировать сразу. | | healthCheck | HealthCheckOptions | Опции опроса для waitForHealthy. |

Передайте project или preset, если не передано ни то, ни другое, вызов отклоняется. Он также отклоняется, если compose up завершился неудачно или контейнер не удалось проинспектировать либо он не стал healthy. Вывод compose появляется в терминале Docker · <project name>, который открывается, если пользователь не установил terminal.commandOutput в off.

| ComposeUpOptions | По умолчанию | Эффект | | --- | --- | --- | | detached | true | Добавляет -d. false запускает в attached-режиме — вызов тогда ждёт остановки контейнеров. | | build | false | Добавляет --build. | | forceRecreate | false | Добавляет --force-recreate. | | removeOrphans | false | Добавляет --remove-orphans. | | timeout | — | Добавляет --timeout <seconds>. |

Ответ — { container?: SdkDockerContainerInfo }; container заполнен, только если передан containerId.

SdkDockerUpRequest · SdkDockerUpResponse
interface SdkDockerUpRequest {
  preset?: 'orchestrator-local' | 'orchestrator-go-local'
  project?: string | ComposeProject   // строка: путь к compose-файлу
  options?: ComposeUpOptions
  containerId?: string
  waitForHealthy?: boolean
  healthCheck?: HealthCheckOptions
}

interface SdkDockerUpResponse {
  container?: SdkDockerContainerInfo  // только если передан containerId
}
ComposeProject · ComposeUpOptions
interface ComposeProject {
  readonly name: string        // имя compose-проекта (-p)
  readonly configPath: string  // compose-файл (-f)
  readonly workingDir: string  // где выполняется compose
}

interface ComposeUpOptions {
  readonly detached?: boolean
  readonly build?: boolean
  readonly forceRecreate?: boolean
  readonly removeOrphans?: boolean
  readonly timeout?: number    // секунды
}

Инспекция

getContainerInfo(containerId: string): Promise<SdkDockerContainerInfo>
waitForHealthy(containerId: string, options?: HealthCheckOptions): Promise<SdkDockerContainerInfo>

getContainerInfo принимает id или имя контейнера и отклоняется, если контейнера нет.

SdkDockerContainerInfo:

| Поле | Тип | Описание | | --- | --- | --- | | id | string | Полный id контейнера. | | name | string | Имя контейнера без ведущего /. | | image | string | Образ, из которого создан контейнер. | | state | 'created' \| 'restarting' \| 'running' \| 'removing' \| 'paused' \| 'exited' \| 'dead' | Состояние контейнера; нераспознанное состояние отдаётся как 'dead'. | | health | 'healthy' \| 'unhealthy' \| 'starting' \| 'none' | Статус health check; 'none', если у контейнера нет health check. | | createdAt | string | Время создания, ISO 8601. | | ports | { containerPort, hostPort, protocol }[] | Опубликованные порты; protocol — 'tcp' или 'udp'. | | labels | Record<string, string> | Labels контейнера. | | url | string \| null | http://localhost:<hostPort> для первого опубликованного TCP-порта или null. |

waitForHealthy опрашивает контейнер каждые interval мс (по умолчанию 1000) в течение timeout мс (по умолчанию 60000):

  • разрешается, когда health — 'healthy', или когда у контейнера нет проверки здоровья ('none') и он находится в состоянии 'running';
  • немедленно отклоняется, когда health становится 'unhealthy' или state — 'exited' или 'dead';
  • отклоняется, когда истекает timeout.
SdkDockerContainerInfo · HealthCheckOptions
interface SdkDockerContainerInfo {
  readonly id: string
  readonly name: string
  readonly image: string
  readonly state: 'created' | 'restarting' | 'running' | 'removing' | 'paused' | 'exited' | 'dead'
  readonly health: 'healthy' | 'unhealthy' | 'starting' | 'none'
  createdAt: string           // ISO 8601
  readonly ports: readonly {
    readonly containerPort: number
    readonly hostPort: number
    readonly protocol: 'tcp' | 'udp'
  }[]
  readonly labels: Readonly<Record<string, string>>
  readonly url: string | null
}

interface HealthCheckOptions {
  readonly timeout?: number   // мс, по умолчанию 60000
  readonly interval?: number  // мс, по умолчанию 1000
  readonly retries?: number   // сейчас ни на что не влияет
}
DockerVersionInfo · ComposeVersionInfo
interface DockerVersionInfo {
  readonly version: string
  readonly apiVersion: string
  readonly os: string
  readonly arch: string
}

interface ComposeVersionInfo {
  readonly version: string
}

Порты

isPortAvailable(port: number, host?: string): Promise<PortCheckResult>
findAvailablePort(options?: FindPortOptions): Promise<number>

isPortAvailable проверяет, занят ли TCP-порт port на этой машине (lsof на macOS и Linux, PowerShell на Windows). Возвращает { port, available, process? }, где process — id процесса, занимающего порт, в виде текста (несколько id разделены переводами строк).

findAvailablePort проверяет порты по очереди от startPort (по умолчанию 3000) до endPort (по умолчанию 4000) включительно и возвращает первый свободный. Если свободных нет, отклоняется.

PortCheckResult · FindPortOptions
interface PortCheckResult {
  readonly port: number
  readonly available: boolean
  readonly process?: string   // id процесса(ов), занимающего порт
}

interface FindPortOptions {
  readonly startPort?: number // по умолчанию 3000
  readonly endPort?: number   // по умолчанию 4000
  readonly host?: string      // сейчас ни на что не влияет
}
import type { ExtensionContext } from '@fragmenta/extension'

export async function activate(context: ExtensionContext) {
  if (!(await sdk.docker.isDockerInstalled())) {
    await sdk.window.showErrorMessage('Нужен Docker')
    return
  }

  const { available } = await sdk.docker.isPortAvailable(8080)
  if (!available) {
    await sdk.window.showErrorMessage('Порт 8080 уже занят')
    return
  }

  const { container } = await sdk.docker.dockerUp({
    project: context.asAbsolutePath('docker/compose.yml'),
    containerId: 'my-backend', // container_name из compose.yml
    waitForHealthy: true,
  })
  await sdk.window.showInfoMessage('Бэкенд запущен', container?.url ?? undefined)
}