← Cloudflare Durable Objects / durable-objects / api
Durable Object Container
Описание
Каждый контейнер управляется Durable Object. Container класс от @cloudflare/containers расширяет DurableObject и берёт на себя управление жизненным циклом, готовность портов и тайм-ауты перехода в спящий режим. Durable Object управляет маршрутизацией, постоянным состоянием и хуками жизненного цикла, а процесс контейнера запускает ваш образ внутри Linux VM.
Низкоуровневый API, описанный на этой странице, доступен в this.ctx.container внутри любого класса Durable Object, у которого есть привязка container. Используйте его, если вам нужен непосредственный контроль над процессом контейнера или вы не можете использовать Container в качестве класса.
Поскольку Container класс расширяет DurableObject, у вас также есть доступ к Хранилище SQLite через this.ctx.storage, alarms, и всех остальных API Durable Objects.
export class MyDurableObject extends DurableObject {
constructor(ctx, env) {
super(ctx, env);
// boot the container when starting the DO
this.ctx.blockConcurrencyWhile(async () => {
this.ctx.container.start();
});
}
}export class MyDurableObject extends DurableObject {
constructor(ctx: DurableObjectState, env: Env) {
super(ctx, env);
// boot the container when starting the DO
this.ctx.blockConcurrencyWhile(async () => {
this.ctx.container.start();
});
}
}Атрибуты
running
running возвращает true, если контейнер в данный момент запущен. Это не гарантирует, что контейнер полностью запустился и готов принимать запросы.
this.ctx.container.running;Методы
start
start запускает контейнер. Этот метод не блокируется до полного запуска контейнера.
Перед использованием контейнера рекомендуется убедиться, что он готов принимать запросы.
this.ctx.container.start({
env: {
FOO: "bar",
},
enableInternet: false,
entrypoint: ["node", "server.js"],
});Параметры
options(необязательно): объект со следующими свойствами:env: объект с переменными окружения, передаваемыми в контейнер. Это удобно для передачи в контейнер значений конфигурации или секретов.entrypoint: массив строк, представляющих команду для запуска в контейнере.enableInternet: логическое значение, указывающее, включён ли доступ к интернету для контейнера.
Возвращаемые значения
- Нет.
exec
exec запускает ещё один процесс внутри уже работающего Container. Он не запускает остановленный Container.
В следующем примере вызывается this.ctx.container.exec() внутри класса, расширяющего Container от @cloudflare/containers. В RPC-методах проверяйте this.ctx.container.running и вызвать await this.start() при необходимости. Также можно использовать onStart()-хук для выполнения любой последовательности команд при каждом запуске Container.
exec(
cmd: string[],
options?: ContainerExecOptions,
): Promise<ExecProcess> exec операция запускает исполняемый файл напрямую с переданными аргументами. Она не запускает оболочку и не интерпретирует конвейеры, перенаправления, подстановки и другой синтаксис оболочки. Чтобы явно вызвать Bash, используйте ["bash", "-lc", "<COMMAND>"] когда в образе есть Bash. Используйте ["sh", "-c", "<COMMAND>"] для образов, в которых есть только POSIX-совместимая оболочка (Portable Operating System Interface).
Следующий метод RPC запускает Container перед выполнением команды:
import { Container } from "@cloudflare/containers";
export class MyContainer extends Container {
async runCommand() {
if (!this.ctx.container.running) {
await this.start();
}
const process = await this.ctx.container.exec(["node", "--version"]);
const output = await process.output();
return {
pid: process.pid,
exitCode: output.exitCode,
stdout: new TextDecoder().decode(output.stdout),
};
}
}import { Container } from "@cloudflare/containers";
export class MyContainer extends Container {
async runCommand() {
if (!this.ctx.container.running) {
await this.start();
}
const process = await this.ctx.container.exec(["node", "--version"]);
const output = await process.output();
return {
pid: process.pid,
exitCode: output.exitCode,
stdout: new TextDecoder().decode(output.stdout),
};
}
}Параметры
cmd(string[]) : исполняемый файл и его аргументы.options(ContainerExecOptions, необязательный), конфигурация процесса:stdin(ReadableStream | "pipe") : источник для стандартного ввода. Используйте"pipe"для записи через возвращённыйstdinпоток. Если он не указан, стандартный ввод закрывается и отправляет признак конца файла (EOF).stdout("pipe" | "ignore", по умолчанию"pipe") : записывает или отбрасывает стандартный вывод.stderr("pipe" | "ignore" | "combined", по умолчанию"pipe") : записывает, отбрасывает или объединяет стандартный поток ошибок со стандартным выводом."combined"значение требуетstdout: "pipe". Объединённый вывод не гарантирует порядок между исходными потоками.cwd(string) : рабочий каталог процесса.env(Record<string, string>) : добавления и переопределения переменных окружения. Процесс наследует существующие переменные Container. Для совпадающих ключей используется значение, заданное при выполнении.user(string) : пользователь образа для процесса.
Возвращаемые значения
Возвращает Promise<ExecProcess>.
Одна ExecProcess содержит следующие поля и методы:
stdin(WritableStream | null) : поток для записи стандартного ввода, когдаstdinэто"pipe".stdout(ReadableStream | null) : поток для чтения стандартного вывода при перенаправлении.stderr(ReadableStream | null) : поток для чтения стандартного потока ошибок при отдельном перенаправлении.pid(number) : идентификатор процесса.exitCode(Promise<number>) : выполняется, когда процесс завершается. Ненулевые коды завершения также приводят к успешному выполнению, а не к отклонению.output()(Promise<ExecOutput>) : считывает буферизованный вывод один раз.ExecOutputсодержитstdout(ArrayBuffer),stderr(ArrayBuffer), иexitCode(number). Игнорируемые потоки создают пустые буферы. ИспользуйтеTextDecoderдля декодирования текста.kill(signal?: number)(void) : помещает сигнал в очередь для процесса. По умолчанию используетсяSIGTERM, сигнал15. Сигнал должен поступать от1через64.
С stderr: "combined", stderr это null на ExecProcess и пустой ArrayBuffer на ExecOutput. Считывайте оба канала вывода из stdout.
output() выбрасывает TypeError при вызове более одного раза или после того, как один из потоков чтения уже начал считываться. Для больших объёмов данных считывайте оба потока чтения параллельно, вместо буферизации их с помощью output().
exec не имеет встроенного тайм-аута. Используйте kill() чтобы запросить завершение работы, а затем отслеживать его через exitCode. Процесс может обработать сигнал или проигнорировать его, поэтому это не гарантирует жёсткий дедлайн. Не делайте выводов о конкретном коде завершения на основании сигнала.
Исключения
exec()вызывает исключение, если Container не запущен.exec()выбрасываетTypeErrorкогдаcmdпуст, параметр mode недопустим илиstderr: "combined"используется вместе сstdout: "ignore".exec()отклоняется, если среде выполнения не удаётся создать или запустить процесс.- Имена переменных окружения не могут содержать
=или null-символы. Значения переменных окружения,cwd, а такжеuserне может содержать null-символы. kill()выбрасываетRangeErrorкогда сигнал выходит за пределы поддерживаемого диапазона.
Примеры для конкретных задач см. в Выполнять команды.
destroy
destroy останавливает контейнер и, при необходимости, возвращает пользовательское сообщение об ошибке в monitor() колбэк ошибки.
this.ctx.container.destroy("Manually Destroyed");Параметры
error(необязательно): строка, которая будет передана обработчику ошибокmonitorметод. Это полезно для логирования и отладки.
Возвращаемые значения
- Promise, который возвращается после уничтожения контейнера.
signal
signal отправляет контейнеру IPC-сигнал, например SIGKILL или SIGTERM. Это удобно для корректной или принудительной остановки контейнера.
const SIGTERM = 15;
this.ctx.container.signal(SIGTERM);Параметры
signal: число, обозначающее сигнал для отправки в контейнер. Обычно это номер сигнала POSIX, например SIGTERM (15) или SIGKILL (9).
Возвращаемые значения
- Нет.
getTcpPort
getTcpPort возвращает порт TCP контейнера. Его можно использовать для взаимодействия с контейнером по TCP и HTTP.
const port = this.ctx.container.getTcpPort(8080);
const res = await port.fetch("http://container/set-state", {
body: initialState,
method: "POST",
});const conn = this.ctx.container.getTcpPort(8080).connect("10.0.0.1:8080");
await conn.opened;
try {
if (request.body) {
await request.body.pipeTo(conn.writable);
}
return new Response(conn.readable);
} catch (err) {
console.error("Request body piping failed:", err);
return new Response("Failed to proxy request body", { status: 502 });
}Параметры
port(number): номер TCP-порта, используемый для связи с контейнером.
Возвращаемые значения
TcpPort:TcpPortобъект, представляющий TCP-порт. Этот объект можно использовать для отправки запросов в контейнер по TCP и HTTP.
monitor
monitor возвращает промис, который разрешается при завершении работы контейнера и отклоняется при возникновении ошибки контейнера. Это удобно для настройки
колбэков, обрабатывающих изменения статуса контейнера в коде Workers.
class MyContainer extends DurableObject {
constructor(ctx, env) {
super(ctx, env);
function onContainerExit() {
console.log("Container exited");
}
// the "err" value can be customized by the destroy() method
async function onContainerError(err) {
console.log("Container errored", err);
}
this.ctx.container.start();
this.ctx.container.monitor().then(onContainerExit).catch(onContainerError);
}
}Параметры
- None
Возвращаемые значения
- Promise, который разрешается при завершении работы контейнера.
interceptOutboundHttp
interceptOutboundHttp перенаправляет исходящие HTTP-запросы, соответствующие имени хоста, шаблону имени хоста, IP-адресу, комбинации IP:port или диапазону CIDR, через WorkerEntrypoint. Можно вызывать как до, так и после запуска контейнера. Открытые соединения подхватывают новый обработчик без разрыва.
const worker = this.ctx.exports.MyWorker({ props: { message: "hello" } });
// Match a specific hostname
this.ctx.container.interceptOutboundHttp("api.example.com", worker);
// Match a hostname glob pattern
this.ctx.container.interceptOutboundHttp("*.example.com", worker);
// Match an IP:port
await this.ctx.container.interceptOutboundHttp("15.0.0.1:80", worker);
// Match a CIDR range (IPv4 and IPv6)
await this.ctx.container.interceptOutboundHttp("123.123.123.123/23", worker);Параметры
target(string): имя хоста, шаблон-глоб имени хоста (например,*.example.com), IP-адрес, IP:порт или диапазон CIDR для сопоставления.worker(WorkerEntrypoint):WorkerEntrypointэкземпляр для обработки соответствующих запросов.
Возвращаемые значения
- Нет.
interceptAllOutboundHttp
interceptAllOutboundHttp перенаправляет все исходящие HTTP-запросы контейнера через WorkerEntrypoint, независимо от назначения.
await this.ctx.container.interceptAllOutboundHttp(worker);Параметры
worker(WorkerEntrypoint):WorkerEntrypointэкземпляр для обработки всех исходящих HTTP-запросов.
Возвращаемые значения
- Promise, который разрешается после установки правила перехвата.
interceptOutboundHttps
interceptOutboundHttps перенаправляет исходящие HTTPS-запросы, соответствующие имени хоста или шаблону имени хоста, через WorkerEntrypoint. Работает так же, как interceptOutboundHttp но для трафика HTTPS. Контейнер должен доверять сертификату CA по адресу /etc/cloudflare/certs/cloudflare-containers-ca.crt чтобы перехват HTTPS работал.
Поддерживает шаблоны glob, где * соответствует любой последовательности символов.
const worker = this.ctx.exports.MyWorker({ props: {} });
// Match a specific hostname
this.ctx.container.interceptOutboundHttps("api.example.com", worker);
// Match a hostname glob pattern
this.ctx.container.interceptOutboundHttps("*.example.com", worker);
// Intercept all HTTPS traffic
this.ctx.container.interceptOutboundHttps("*", worker);Параметры
target(string): имя хоста или шаблон-глоб имени хоста для сопоставления. Используйте*чтобы перехватывать весь HTTPS-трафик.worker(WorkerEntrypoint):WorkerEntrypointэкземпляр для обработки соответствующих запросов.
Возвращаемые значения
- Нет.
Дополнительные материалы
- Справочник по классу Container : рекомендуемый высокоуровневый API, построенный на основе этого интерфейса
- Обзор Containers
- Начало работы с Containers
- API хранилища SQLite : сохраняет состояние между перезапусками контейнера
- Durable Objects : базовая платформа, на которой работают Containers