Skip to content

Commit

A deployment is a site or a Worker whenever it can be, and a container only as the fallback. With Build as on Auto, a Wrangler config or a framework's Cloudflare adapter is a Workers project; a framework's site, a build script's or an index.html is that site even beside a Dockerfile, and the log says "Built as a Vite site; Dockerfile is not used (a container is only the fallback; choose **Build as**: Container to use it)", where a Dockerfile that ran a server used to win; a Node.js server with no Dockerfile (Express, Koa, Hono, Polka, Restify, hapi, node:http) runs as a Worker; any other server g1t recognises, a Node.js server with its own Dockerfile, a framework set up to need a server, or a Dockerfile with nothing else to serve is a container.

A Node.js server runs as a Worker through httpServerHandler from cloudflare:node with nodejs_compat (developers.cloudflare.com/workers/runtime-apis/nodejs/http: from the compatibility date 2025-09-01 nodejs_compat turns on the HTTP server modules, and g1t's date is 2026-09-26). deploy/node_worker.rs finds the file that starts it (what its start script runs with node, tsx or ts-node, else main, else server.js and the like), and the build installs and builds it, writes a prelude that keeps every server the app creates or listens on and lets listen take any port and address, and an entry that imports the app and answers with httpServerHandler, or with the app's default export's fetch when it has one (a Hono app, whose Response @hono/node-server replaces is turned back into the runtime's). wrangler deploy --dry-run bundles it, and wrangler dev starts it once with the project's variables and asks it for /: a module that cannot load, a top-level await that never settles, or a server that never listens fails there, not in production. A folder served with app.use(express.static("public")) is uploaded as the Worker's static files. What cannot run as a Worker is found before anything is built, and the app is a container from the Dockerfile g1t writes, the log saying "Could not run as a Worker: <reason>; deploying as a container.": a native addon (better-sqlite3, bcrypt, sharp and others), Fastify, NestJS, Sails, remix-serve or react-router-serve, a WebSocket server (socket.io, express-ws, WebSocketServer, an upgrade handler), child_process, cluster or worker_threads, files read or written while it runs, files served from disk under a path, or a start script g1t cannot read. A Worker that does not bundle or start falls back the same way. Build as Workers runs a Node.js server as one whatever is found, and Build as Container (shown as Container now, still `docker` as stored) runs its container. g1t-runner detect and g1t/detect print entry for such a Worker.

Checked:
cargo test -p g1t-runner (the precedence table: Vite with a Dockerfile is a site, Express without one a Worker, Express with better-sqlite3 a container, a Go server with its Dockerfile a container, a Wrangler config with a Dockerfile Workers, index.html with an nginx Dockerfile a site), and on Linux the ignored end-to-end tests in tests/deploy_cli.rs, which install Express, bundle and start its Worker and deploy it to a fake API with public/ as its assets, and fall back to a container when the bundle fails or a top-level await never settles. Express, Hono on @hono/node-server and Fastify were run by hand with wrangler dev: Express and Hono answered, and Fastify, which boots on timers, did not, so it is a container. The deployments service's tests and typecheck, the web typecheck, and the docs build pass. The Deployments guide has the rule, Node.js servers as Workers, and how to force a container; the architecture page, the Build as hint and g1t/detect's outputs follow it.
syntaqxcommitted Parenta6a6f43Browse files
2 files+9−50/2 viewed
+4−3
2424 | `root-dir` | The checkout | Where the project is in the checkout. |
2525 | `build-command` | None | A build command of your own, as `g1t/deploy` takes it. |
2626 | `output-dir` | None | An output folder of your own, as `g1t/deploy` takes it. |
27−| `build-as` | `auto` | What it is built as: `auto`, `static`, `workers` or `docker`, as `g1t/deploy` takes it. |
27+| `build-as` | `auto` | What it is built as: `auto`, `static`, `workers` or `docker` (Container), as `g1t/deploy` takes it. |
2828 | `dockerfile` | None | A Dockerfile's path of your own, as `g1t/deploy` takes it. |
2929
3030 ## Outputs
3131
3232 | Output | |
3333 | --- | --- |
34−| `kind` | `workers` (a `wrangler.jsonc`, `wrangler.json` or `wrangler.toml`, or a framework's Cloudflare adapter), `static` (a site a build writes), `html` (the files as they are), `container` (a `Dockerfile`, a framework set up to need a server, or a server g1t writes a Dockerfile for) or `none` (nothing to serve). |
35−| `framework` | The framework it is built with, from the table below; for a container without one, `dockerfile`, or the server g1t writes a Dockerfile for (`node`, `django`, `flask`, `fastapi`, `python`, `go`, `rails`, `rack`, `laravel`, `php`). Empty when there is none. |
34+| `kind` | `workers` (a `wrangler.jsonc`, `wrangler.json` or `wrangler.toml`, a framework's Cloudflare adapter, or a Node.js server run as a Worker), `static` (a site a build writes), `html` (the files as they are), `container` (a server that is not run as a Worker, a framework set up to need a server, or a `Dockerfile` with nothing else to serve) or `none` (nothing to serve). |
35+| `framework` | The framework it is built with, from the table below; `node` for a Node.js server run as a Worker; for a container without one, `dockerfile`, or the server g1t writes a Dockerfile for (`node`, `django`, `flask`, `fastapi`, `python`, `go`, `rails`, `rack`, `laravel`, `php`). Empty when there is none. |
3636 | `dockerfile` | A container's own Dockerfile, relative to the project. Empty when g1t writes one, and for anything that is not a container. |
3737 | `port` | The port a container listens on: its Dockerfile's `EXPOSE`, else `8080`. |
38+| `entry` | For a Node.js server run as a Worker, the file that starts it, relative to the project. Empty for anything else. |
3839 | `install` | How dependencies are installed, from the lockfile: `npm ci`, `pnpm install --frozen-lockfile`, and so on, and `bundle install` for Jekyll. Empty when there is nothing to install. |
3940 | `build` | What builds it: your command, the package's `build` script (`npm run build`), the framework's own command, or `wrangler deploy --dry-run` for Workers. Empty when nothing does. |
4041 | `output-dir` | The folder served, relative to the project (`.` for the project itself): yours, a Workers project's assets directory, the folder the framework writes, or the first of `dist`, `build`, `out`, `public`, `_site`, `.output/public` that exists. Empty when a build has yet to write it, as for a Cloudflare adapter's Worker. |
+5−2
2626
2727 outputs:
2828 kind:
29− description: workers (a Wrangler config, or a framework's Cloudflare adapter), static (a site a build writes), html (the files as they are), container (a Dockerfile, a framework set up to need a server, or a server g1t writes a Dockerfile for) or none (nothing to serve).
29+ description: workers (a Wrangler config, a framework's Cloudflare adapter, or a Node.js server run as a Worker), static (a site a build writes), html (the files as they are), container (a server that is not run as a Worker, a framework set up to need a server, or a Dockerfile with nothing else to serve) or none (nothing to serve).
3030 value: ${{ steps.detect.outputs.kind }}
3131 install:
3232 description: How its dependencies are installed, such as npm ci. Empty without a package.json.
3838 description: The folder that is served, relative to the project (. for the project itself). Empty when a build has yet to write it.
3939 value: ${{ steps.detect.outputs.output-dir }}
4040 framework:
41− description: The framework it is built with, such as vite, astro, nextjs, sveltekit or hugo; for a container without one, dockerfile or the server g1t writes a Dockerfile for (node, flask, rails…). Empty when there is none.
41+ description: The framework it is built with, such as vite, astro, nextjs, sveltekit or hugo; node for a Node.js server run as a Worker; for a container without one, dockerfile or the server g1t writes a Dockerfile for (node, flask, rails…). Empty when there is none.
4242 value: ${{ steps.detect.outputs.framework }}
4343 dockerfile:
4444 description: A container's own Dockerfile, relative to the project. Empty when g1t writes one, or for anything else.
4646 port:
4747 description: The port a container listens on, its Dockerfile's EXPOSE or 8080. Empty for anything else.
4848 value: ${{ steps.detect.outputs.port }}
49+ entry:
50+ description: For a Node.js server run as a Worker, the file that starts it, relative to the project. Empty for anything else.
51+ value: ${{ steps.detect.outputs.entry }}
4952
5053 runs:
5154 using: composite