Cloudflare Containers, durable objects
Describe the feature
I would like to be able to use Cloudflare Containers in a project with Nitro. Configuring wrangler from own file or nuxt.config.ts works fine. I can make use images and bindings.
The problem is that the export must be in the main bundle and not chunks, hence the error:
Your Worker depends on the following Durable Objects, which are not exported in your entrypoint file: MyContainer.
This is generally not a problem of Containers itself. Generally every durable_object binding returns an error after building because it is not in the main bundle.
There is also an issue here: https://github.com/nitrojs/nitro/issues/3378
In the cloudflare_durable preset there is something like this: https://github.com/nitrojs/nitro/blob/v3/src/presets/cloudflare/runtime/cloudflare-durable.ts#L60
and it exports 1 binding, durable object with name $DurableObject, and with containers it needs to export somewhere in the route something like below. And while there is no error during build, there is an error during deploy because this export is not in the main bundle.
import { Container, getContainer } from "@cloudflare/containers";
export class MyContainer extends Container {
defaultPort = 4000; // Port the container is listening on
sleepAfter = "10m"; // Stop the instance if requests not sent for 10 minutes
}
Additional information
- [ ] Would you be willing to help implement this feature?
Any update on this? Did anyone got it working somehow?
I found a solution 🎉
I created a custom preset that extends the cloudflare default.
nitro: {
preset: "./preset",
}
Preset:
// preset/nitro.config.ts
import type { NitroPreset } from "nitropack";
import { fileURLToPath } from "node:url";
export default <NitroPreset>{
extends: "cloudflare_module",
entry: fileURLToPath(new URL("./entry.ts", import.meta.url)),
};
// preset/entry.ts
import "#nitro-internal-pollyfills";
import { Container } from "@cloudflare/containers";
import cloudflareModule from "nitropack/presets/cloudflare/runtime/cloudflare-module";
// could be also a Durable Object
export class MyContainer extends Container {
defaultPort = 3000;
sleepAfter = '5m';
override onStart() {
console.log('Container successfully started');
}
override onStop() {
console.log('Container successfully shut down');
}
override onError(error: unknown) {
console.log('Container error:', error);
}
}
export default cloudflareModule
Then it will be inside the cloudflare context:
const container = event?.context?.cloudflare?.env?.MY_CONTAINER
Thanks @valtlfelipe! Looks like a very clean workaround, will be very useful. I wouldn't have thought of that solution.
@pi0 maybe it's worth adding to the documentation an example of extending the preset for such non-standard situations and new platform features that are not yet natively supported by the framework as in the example above?