Skip to content

Commit d78508f

Browse files
Create multi-platform Docker image and switch to Cloudflare official repo (#29)
* Add Docker multi-architecture build system - Replace manual arch-specific builds with buildx multi-arch - Add GitHub Actions workflow for automated Docker builds - Update documentation to use unified Docker image - Create test workflow to validate multi-arch builds * Fix bun installation * Fix container startup race condition - Add defaultPort = 3000 to Sandbox class for proper port readiness checks - Fix onStop() to only log shutdown when container is actually stopped - Add ping() method that checks container state without triggering containerFetch - Update /api/ping endpoint to use new ping() method instead of exec() This prevents the "Sandbox successfully shut down" message from appearing during initialization and fixes port exposure errors on first run. * Override containerFetch to handle failures * Handle 503s during startup * Revert HTTPClient * Use local docker image in local dev * Remove plan * Switch over to Cloudflare official repo * Document setEnvVars * Add changeset
1 parent 70dcdae commit d78508f

File tree

11 files changed

+112
-13
lines changed

11 files changed

+112
-13
lines changed

.changeset/icy-garlics-tan.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@cloudflare/sandbox": patch
3+
---
4+
5+
Create multi-platform Docker image and switch to Cloudflare official repo

.github/changeset-version.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { execSync } from "node:child_process";
2+
import * as fs from "node:fs";
23

34
// This script is used by the `release.yml` workflow to update the version of the packages being released.
45
// The standard step is only to run `changeset version` but this does not update the package-lock.json file.
@@ -11,3 +12,44 @@ execSync("npx changeset version", {
1112
execSync("npm install", {
1213
stdio: "inherit",
1314
});
15+
16+
// Update Dockerfile and README version references after changeset updates package.json
17+
try {
18+
const packageJson = JSON.parse(fs.readFileSync("./packages/sandbox/package.json", "utf-8"));
19+
const newVersion = packageJson.version;
20+
21+
const dockerfilePath = "./examples/basic/Dockerfile";
22+
let dockerfileContent = fs.readFileSync(dockerfilePath, "utf-8");
23+
24+
// Update the production image version in the comment
25+
dockerfileContent = dockerfileContent.replace(
26+
/# FROM docker\.io\/cloudflare\/sandbox:[\d.]+/,
27+
`# FROM docker.io/cloudflare/sandbox:${newVersion}`
28+
);
29+
30+
// Update the test image version
31+
dockerfileContent = dockerfileContent.replace(
32+
/FROM cloudflare\/sandbox-test:[\d.]+/,
33+
`FROM cloudflare/sandbox-test:${newVersion}`
34+
);
35+
36+
fs.writeFileSync(dockerfilePath, dockerfileContent);
37+
console.log(`✅ Updated Dockerfile versions to ${newVersion}`);
38+
39+
// Update README.md
40+
const readmePath = "./README.md";
41+
let readmeContent = fs.readFileSync(readmePath, "utf-8");
42+
43+
// Update the Docker image version in README
44+
readmeContent = readmeContent.replace(
45+
/FROM docker\.io\/cloudflare\/sandbox:[\d.]+/,
46+
`FROM docker.io/cloudflare/sandbox:${newVersion}`
47+
);
48+
49+
fs.writeFileSync(readmePath, readmeContent);
50+
console.log(`✅ Updated README.md version to ${newVersion}`);
51+
52+
} catch (error) {
53+
console.error("❌ Failed to update file versions:", error);
54+
// Don't fail the whole release for this
55+
}

.github/workflows/prerelease.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,18 @@ jobs:
3333
- run: npm run check
3434
- run: CI=true npm run test
3535

36+
- name: Set up Docker Buildx
37+
uses: docker/setup-buildx-action@v3
38+
39+
- name: Login to Docker Hub
40+
uses: docker/login-action@v3
41+
with:
42+
username: ${{ secrets.DOCKER_HUB_USERNAME }}
43+
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
44+
45+
- name: Build and push Docker image (beta)
46+
run: npm run docker:publish:beta --workspace=@cloudflare/sandbox
47+
3648
- run: npm publish --tag beta --access public
3749
env:
3850
NPM_PUBLISH_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }}

.github/workflows/release.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,18 @@ jobs:
2727
- run: npm install
2828
- run: npm run build
2929

30+
- name: Set up Docker Buildx
31+
uses: docker/setup-buildx-action@v3
32+
33+
- name: Login to Docker Hub
34+
uses: docker/login-action@v3
35+
with:
36+
username: ${{ secrets.DOCKER_HUB_USERNAME }}
37+
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
38+
39+
- name: Build and push Docker image
40+
run: npm run docker:publish --workspace=@cloudflare/sandbox
41+
3042
- id: changesets
3143
uses: changesets/action@v1
3244
with:

README.md

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,7 @@ npm install @cloudflare/sandbox
6464
1. **Create a Dockerfile** (temporary requirement, will be removed in future releases):
6565

6666
```dockerfile
67-
FROM docker.io/ghostwriternr/cloudflare-sandbox:0.0.9
68-
# If building your project on arm64, use:
69-
# FROM docker.io/ghostwriternr/cloudflare-sandbox-arm:0.0.9
67+
FROM docker.io/cloudflare/sandbox:0.0.9
7068

7169
EXPOSE 3000
7270

@@ -203,6 +201,28 @@ await sandbox.gitCheckout("https://github.com/user/repo", {
203201
});
204202
```
205203

204+
#### `setEnvVars(envVars)`
205+
206+
Set environment variables dynamically in the sandbox.
207+
208+
> **Important**: This method must be called immediately after `getSandbox()` and before any other operations. Once a sandbox instance starts up, environment variables cannot be changed
209+
for that instance.
210+
211+
```typescript
212+
const sandbox = getSandbox(env.Sandbox, "my-sandbox");
213+
214+
// Set environment variables FIRST, before any other operations
215+
await sandbox.setEnvVars({
216+
NODE_ENV: "production",
217+
API_KEY: "your-api-key",
218+
DATABASE_URL: "postgresql://localhost:5432/mydb"
219+
});
220+
221+
// Now you can run commands - environment variables are available
222+
const result = await sandbox.exec("echo $NODE_ENV");
223+
console.log(result.stdout); // "production"
224+
```
225+
206226
#### Process Management
207227

208228
- `listProcesses()` - List all running processes

examples/basic/Dockerfile

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
FROM docker.io/ghostwriternr/cloudflare-sandbox:0.0.9
1+
# This image is unique to this repo, and you'll never need it.
2+
# Whenever you're integrating with sandbox SDK in your own project,
3+
# you should use the official image instead:
4+
# FROM docker.io/cloudflare/sandbox:0.1.1
5+
FROM cloudflare/sandbox-test:0.1.1
26

37
EXPOSE 8080
48
EXPOSE 3001

examples/basic/wrangler.jsonc

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,5 +33,8 @@
3333
"new_sqlite_classes": ["Sandbox"],
3434
"tag": "v1"
3535
}
36-
]
36+
],
37+
"dev": {
38+
"container_engine": "unix:///Users/naresh/.colima/default/docker.sock"
39+
}
3740
}

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"scripts": {
66
"typecheck": "tsx scripts/typecheck.ts",
77
"check": "biome check && npm run typecheck",
8-
"build": "npm run build -w @cloudflare/sandbox",
8+
"build": "npm run build -w @cloudflare/sandbox && npm run docker:local -w @cloudflare/sandbox",
99
"test": "echo 'No tests'",
1010
"toc": "doctoc README.md --github --maxlevel 3 && node scripts/fix-toc-links.js"
1111
},

packages/sandbox/Dockerfile

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# Sandbox base image with development tools, Python, Node.js, and Bun
2+
FROM oven/bun:latest AS bun-source
23
FROM ubuntu:22.04
34

45
# Prevent interactive prompts during package installation
@@ -50,11 +51,9 @@ RUN apt-get update && apt-get install -y ca-certificates curl gnupg \
5051
&& apt-get install -y nodejs \
5152
&& rm -rf /var/lib/apt/lists/*
5253

53-
# Install Bun using the official installation script
54-
RUN curl -fsSL https://bun.sh/install | bash \
55-
&& mv /root/.bun/bin/bun /usr/local/bin/bun \
56-
&& mv /root/.bun/bin/bunx /usr/local/bin/bunx \
57-
&& rm -rf /root/.bun
54+
# Install Bun from official image (avoids architecture compatibility issues)
55+
COPY --from=bun-source /usr/local/bin/bun /usr/local/bin/bun
56+
COPY --from=bun-source /usr/local/bin/bunx /usr/local/bin/bunx
5857

5958
# Install global npm packages as root
6059
RUN npm install -g yarn pnpm

packages/sandbox/package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@
1818
],
1919
"scripts": {
2020
"build": "rm -rf dist && tsup src/*.ts --outDir dist --dts --sourcemap --format esm",
21-
"docker:build": "docker build -t ghostwriternr/cloudflare-sandbox:$npm_package_version .",
22-
"docker:publish": "docker push docker.io/ghostwriternr/cloudflare-sandbox:$npm_package_version"
21+
"docker:local": "docker build . -t cloudflare/sandbox-test:$npm_package_version",
22+
"docker:publish": "docker buildx build --platform linux/amd64,linux/arm64 -t cloudflare/sandbox:$npm_package_version --push .",
23+
"docker:publish:beta": "docker buildx build --platform linux/amd64,linux/arm64 -t cloudflare/sandbox:$npm_package_version-beta --push ."
2324
},
2425
"exports": {
2526
".": {

0 commit comments

Comments
 (0)