Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 61 additions & 16 deletions alchemy-web/src/content/docs/providers/cloudflare/container.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ description: Deploy Docker containers on Cloudflare's global network

A Container is a running Docker image running in Cloudflare's global network, managed by a Cloudflare Durable Object.

> [!CAUTION]
> Cloudflare Containers is still in [Beta](https://blog.cloudflare.com/containers-are-available-in-public-beta-for-simple-global-and-programmable/).
:::caution
Cloudflare Containers is still in [Beta](https://blog.cloudflare.com/containers-are-available-in-public-beta-for-simple-global-and-programmable/).
:::

You'll need:

Expand Down Expand Up @@ -68,20 +69,64 @@ const container = await Container<MyContainer>("my-container", {

This will build your Dockerfile and prepare it for publishing to Cloudflare's Image Registry.

> [!TIP]
> The default behavior is effectively `docker build . -t my-container` but you can customize the configuration:
>
> ```ts
> const container = await Container<MyContainer>("my-container", {
> className: "MyContainer",
> name: "your-container",
> tag: "some-tag",
> build: {
> context: import.meta.dir,
> dockerfile: "Dockerfile.dev",
> },
> });
> ```
:::tip
The default behavior is effectively `docker build . -t my-container` but you can customize the configuration:

```ts
const container = await Container<MyContainer>("my-container", {
className: "MyContainer",
name: "your-container",
tag: "some-tag",
build: {
context: import.meta.dir,
dockerfile: "Dockerfile.dev",
},
});
```
:::

## Pre-built Images

You can use a pre-built image by passing an image reference to the `image` property:

### Pull an Image by reference

```ts
const container = await Container<MyContainer>("my-container", {
className: "MyContainer",
image: "alpine:latest",
});
```

### Build an Image first

```ts
const image = await Image("my-image", {
name: "my-image",
tag: "latest",
build: {
context: path.join(import.meta.dirname, "container"),
},
});

const container = await Container<MyContainer>("my-container", {
className: "MyContainer",
image,
});
```

### Pull a RemoteImage explcictly

```ts
const remoteImage = await RemoteImage("alpine", {
image: "alpine:latest"
});

const container = await Container<MyContainer>("my-container", {
className: "MyContainer",
image: remoteImage,
});
```

## Adopting Existing Containers

Expand Down
17 changes: 10 additions & 7 deletions alchemy/src/cloudflare/container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,10 +218,10 @@ export async function Container<T>(
const isDev = scope.local && !props.dev?.remote;
if (isDev) {
const image = await Image(id, {
...props,
name: `cloudflare-dev/${name}`, // prefix used by Miniflare
tag,
build: props.build,
});
} as ImageProps);

return {
...output,
Expand All @@ -235,16 +235,19 @@ export async function Container<T>(
const image = await Image(id, {
name: `${api.accountId}/${name}`,
tag,
build: {
platform: props.build?.platform ?? "linux/amd64",
...props.build,
},
build: props.build
? {
platform: props.build?.platform ?? "linux/amd64",
...props.build,
}
: undefined,
image: props.image,
registry: {
server: "registry.cloudflare.com",
username: credentials.username || credentials.user!,
password: secret(credentials.password),
},
});
} as ImageProps);

return {
...output,
Expand Down
7 changes: 7 additions & 0 deletions alchemy/src/docker/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,13 @@ export class DockerApi {
return this.exec(["pull", image]);
}

async tagImage(
source: string,
target: string,
): Promise<{ stdout: string; stderr: string }> {
return this.exec(["tag", source, target]);
}

/**
* Build Docker image
*
Expand Down
Loading
Loading