Skip to content

Where people and agents ship software together. The open-source git platform for the whole job: issues, agents, checks and deploys to the edge.

g1t.sh

Commit

Docker deployments are switched on for g1t.page: a project with a Dockerfile, or a server g1t recognises, deploys as a container with nothing to set. CONTAINERS stays, for a self-hosted g1t whose account has no Containers; the deployments guide documents how Auto chooses between a site and a container, the limitations page loses its section, and Deploy to Cloudflare's checklist becomes what to check on a new account.

syntaqxcommitted Parentdb19627Browse files
7 files+76−620/7 viewed
+0−16
365365
366366 ## Deployments
367367
368−### Containers are not switched on yet
369−
370−[Docker deployments](/guides/deployments/#docker-deployments) are built,
371−but off on g1t.page: a project that runs as a container fails to deploy,
372−saying so, and one with a site besides its `Dockerfile` is built as that
373−site.
374−
375−- **Why.** Cloudflare's container APIs (applications in a Workers for
376− Platforms namespace, registry logins) have to be checked against g1t's
377− own account first.
378−- **Instead.** Build a framework app as a static export or with its
379− Cloudflare adapter, as [Frameworks](/guides/deployments/#frameworks)
380− lists, or set **Build as** to Static site. Or deploy the server from a
381− workflow to wherever it runs today, with its credentials in
382− [secrets](/guides/secrets-and-variables/).
383−
384368 ### A container is one instance, and keeps nothing
385369
386370 A container app runs one instance at a time, sleeps after five minutes
+9−1
2525
2626 1. a Workers project, from `wrangler deploy --dry-run`;
2727 2. a framework it knows, such as Vite, Astro, Next.js or SvelteKit;
28−3. a container, which g1t.sh does not run yet (`CONTAINERS` is `off`);
28+3. a container: a `Dockerfile` that runs a server, even beside a site, or a
29+ server it recognises, for which it writes one
30+ ([Docker deployments](/guides/deployments/#docker-deployments));
2931 4. a static site.
3032
33+A container's image is pushed to Cloudflare's registry with a push-only
34+login `deployments` mints for the build, and runs on Cloudflare
35+Containers behind a Worker of g1t's own in the same namespace. A
36+self-hosted g1t whose account has no Containers sets `CONTAINERS` to
37+`off`.
38+
3139 The sandbox is given a key that can upload the app's static files and
3240 nothing else. `deployments` uploads the built Worker itself to the Workers
3341 for Platforms dispatch namespace `g1t-deployments`. A site with only static
+16−12
317317 ## Docker deployments
318318
319319 Container apps ([Docker deployments](/guides/deployments/#docker-deployments))
320−are off until `CONTAINERS` is `on` in `services/deployments/wrangler.jsonc`.
321−The code follows Cloudflare's documentation and Wrangler's own client for
322−these APIs, but none of them has been called against g1t's account yet.
323−Before turning it on, check each of these with a test project:
320+run when `CONTAINERS` is `on` in `services/deployments/wrangler.jsonc`, as
321+it is for g1t.sh. On an account without Containers, set it to `off`: a
322+container build then fails, saying so, and a project with a site beside
323+its `Dockerfile` is built as that site.
324+
325+The calls follow Cloudflare's API reference and Wrangler's own client.
326+On a new account, deploy a small server (an Express app with a
327+`Dockerfile`, or none) and check each of these:
324328
325329 1. **The token.** `CLOUDFLARE_API_TOKEN` of `services/deployments` has
326330 **Containers: Edit** (and the account has Containers, on Workers Paid).
340344 `exports: { "G1tApp": { "type": "durable-object", "storage": "sqlite" } }`
341345 and `containers: [{ "class_name": "G1tApp" }]` in its metadata is taken,
342346 and taken again on the next deploy with nothing changed about the class.
343−5. **Its Durable Object namespace.**
347+5. **Its Durable Object namespace.** The app's Worker's `APP` binding
348+ (`GET …/dispatch/namespaces/g1t-deployments/scripts/<app>/bindings`)
349+ names its `namespace_id`; failing that,
344350 `GET /accounts/{id}/workers/durable_objects/namespaces` lists it with
345− `class` `G1tApp`, `script` the app's name and `dispatch_namespace`
346− `g1t-deployments`.
351+ `class` `G1tApp` and `script` the app's name.
347352 6. **The Container application.** `POST /accounts/{id}/containers/applications`
348353 with `scheduling_policy` `default`, the image by digest, `instance_type`,
349354 `max_instances` 1 and `durable_objects.namespace_id` creates it; a
362367 9. **Pausing and taking down.** A workspace over its limit gets its
363368 container app's Worker put back paused, which stops the container, and
364369 taking an app down deletes its application before its Worker.
365−
366−Then set `CONTAINERS` to `on`, deploy `services/deployments`, and the
367−container build of a project with a `Dockerfile` goes live; the
368−[limitations page](/about/limitations/#containers-are-not-switched-on-yet)
369−and the caution in the deployments guide come out in the same change.
370+10. **Old images.** After a second deploy of the app, the registry's tag
371+ list for `<account>/g1t-<app>` has only the two newest builds' tags
372+ (`GET /v2/<account>/g1t-<app>/tags/list`), and none once the app is
373+ taken down. The account holds 50 GB of images in all.
370374
371375 ## Rolling back
372376
+41−25
9999 | `wrangler.jsonc`, `wrangler.json` or `wrangler.toml` | Builds it as a **Workers project**: installs dependencies, runs `wrangler deploy --dry-run` to bundle it (which runs the config's own `build` command), and deploys the bundle with the config's static assets, `compatibility_date`, `compatibility_flags` and `vars`. |
100100 | A framework from the table below | Installs dependencies, builds it with the framework's command, and serves the folder it writes as a **static site**, or deploys the Worker its Cloudflare adapter writes as a **Workers project**. |
101101 | A framework set up to need a server (Next.js without a static export, Astro's `@astrojs/node`, SvelteKit's `adapter-node`, a server-rendered React Router or Remix app) | Builds it as a **container**: from its `Dockerfile`, or one g1t writes for it. |
102−| A `Dockerfile` or `Containerfile`, and no framework above | Builds the image and runs it as a **container**. |
103−| A Node.js, Python, Go, Ruby or PHP server, with no `Dockerfile` | Writes a Dockerfile for it, shows it in the build's log, and runs it as a **container**. See [Docker deployments](#docker-deployments). |
102+| A `Dockerfile` or `Containerfile` that runs a server (`CMD`, `ENTRYPOINT` or `EXPOSE`), even beside a site or a framework above | Builds the image and runs it as a **container**. |
103+| A `Dockerfile` and nothing else to serve | Builds the image and runs it as a **container**. |
104+| A Node.js, Python, Go, Ruby, PHP or Rust server, with no `Dockerfile` | Writes a Dockerfile for it, shows it in the build's log, and runs it as a **container**. See [Docker deployments](#docker-deployments). |
104105 | A `build` script in `package.json` | Installs dependencies, runs `npm run build`, and serves the output as a **static site**. |
105106 | An `index.html` and nothing to build | Serves it as it is. |
106107 | Nothing g1t recognises | Fails, saying to add a `Dockerfile`. |
211212 behind the app's Worker, at the same addresses, custom domains and
212213 previews as any other app.
213214
214−:::caution[Not switched on yet]
215−Docker deployments are built but off on g1t.page until Cloudflare's
216−container APIs are checked against g1t's account. Until then a container
217−build fails with "Docker deployments are not switched on for g1t.page
218−yet", and a project that is a container only for having a `Dockerfile`,
219−beside a site g1t could serve, is built as that site, as before.
220−:::
221−
222−What a project is built as is decided in this order:
215+There is nothing to set: push a project with a `Dockerfile`, or a server
216+g1t recognises, and it deploys as a container. What a project is built as
217+is decided in this order:
223218
224219 1. **Build as**, under **Settings → Deployments**: **Static site**,
225220 **Workers** or **Docker** is what it is built as, whatever else it has.
226221 2. **Auto** (the default) finds it from its files:
227− 1. A Wrangler config is a Workers project.
228− 2. A framework that builds a static site or a Worker is that, even
229− beside a `Dockerfile`: it costs nothing while no one visits.
230− 3. A framework set up to need a server is a container, from its
222+ 1. A Wrangler config, or a framework's Cloudflare adapter, is a
223+ Workers project.
224+ 2. A site (a framework that builds one, a `build` script, or an
225+ `index.html`) beside a `Dockerfile` is a container when the
226+ Dockerfile runs a server: its last stage has `CMD` or `ENTRYPOINT`,
227+ or `EXPOSE` on an image that is not only a file server. A
228+ Dockerfile that only copies the site into `nginx`, `httpd`, `caddy`,
229+ `lighttpd`, `busybox` or another file server, or says none of those,
230+ leaves it a site, which g1t serves itself for nothing while no one
231+ visits.
232+ 3. A framework that builds a static site, with no such Dockerfile, is
233+ that site.
234+ 4. A framework set up to need a server is a container, from its
231235 `Dockerfile`, or one g1t writes for it.
232− 4. A project with no framework g1t knows is a container when it has a
236+ 5. A project with no framework g1t knows is a container when it has a
233237 `Dockerfile` (or `Containerfile`, or the path set as its
234238 **Dockerfile**), or is a server g1t recognises.
235− 5. Otherwise a static site or plain HTML, as above; with nothing to
239+ 6. Otherwise a static site or plain HTML, as above; with nothing to
236240 serve, the build fails, saying to add a `Dockerfile`.
237241
242+When a project could be either, the build's log says which it chose and
243+why, near its top: for example, "Building it as a container from
244+Dockerfile, not as the static site it also has: its Dockerfile starts a
245+server of its own (`CMD`). Set **Build as** to Static site to serve the
246+site instead."
247+
238248 g1t writes a Dockerfile for these, when there is none:
239249
240250 | The project has | Runs with |
241251 | --- | --- |
242252 | `package.json` with a `start` script, or a server package (`express`, `fastify`, `koa`, `@nestjs/core`, `@hono/node-server` and others) and a main file | `npm start`, or `node <main>`, on `node:22-slim` (or the major release in `.nvmrc` or `.node-version`), after `npm run build` when there is one |
243−| Next.js, Astro with `@astrojs/node`, SvelteKit with `adapter-node`, React Router or Remix | `next start`, `node ./dist/server/entry.mjs`, `node build`, `react-router-serve` or `remix-serve`, after the build |
253+| Next.js, Astro with `@astrojs/node`, SvelteKit with `adapter-node`, React Router or Remix | `next start` (or `node .next/standalone/server.js`, with its static files beside it, for `output: 'standalone'`), `node ./dist/server/entry.mjs`, `node build`, `react-router-serve` or `remix-serve`, after the build |
244254 | `requirements.txt`, `pyproject.toml` or `Pipfile`, and `manage.py` (Django) | `gunicorn <project>.wsgi` on `python:3.12-slim` |
245255 | The same, with Flask and an `app.py`, `main.py`, `server.py`, `wsgi.py` or `asgi.py` | `gunicorn <module>:app` |
246256 | The same, with FastAPI or Starlette | `uvicorn <module>:app` |
249259 | A `Gemfile` with Rails | `rails server`, after `assets:precompile`, on `ruby:3.3-slim` |
250260 | A `Gemfile` and a `config.ru` | `rackup` |
251261 | `composer.json`, and `artisan` with `public/index.php` (Laravel), or an `index.php` | Apache with PHP 8.3, after `composer install` |
262+| `Cargo.toml` with one program and `axum`, `actix-web`, `rocket`, `warp`, `poem`, `salvo` or `tide` | The program, built with `rust:1` into `debian:bookworm-slim` |
252263
253264 The Dockerfile g1t writes is printed whole in the build's log. To change
254265 how the app is built or run, commit it as `Dockerfile` and edit it. It
257268 What a container gets, and what it must do:
258269
259270 - **Listen on `0.0.0.0` at `PORT`.** `PORT` is the port its Dockerfile's
260− first `EXPOSE` names (in its last stage), else `8080`. The first request
271+ first `EXPOSE` names (in its last stage), else the `PORT` it sets with
272+ `ENV`, else `8080`. A Dockerfile g1t writes sets `HOST` and `HOSTNAME`
273+ to `0.0.0.0` too. The first request
261274 waits up to 90 seconds for it to answer there; one that never does gets
262275 a 503 page saying so.
263276 - **The project's [secrets and variables](#secrets-and-variables)** are
271284 - **Its size** is **Container size** under **Settings → Deployments**:
272285 `lite` (the default) to `standard-4`, as [What it costs](#what-it-costs)
273286 lists. The image may be as large as the size's disk, 2 GB for `lite`;
274− a larger image fails the build, saying how large it was.
287+ a larger image fails the build, saying how large it was. An app keeps
288+ the image it runs and the one before it; older ones are deleted once a
289+ deploy is live, and all of them when the app is taken down.
275290 - **Built for `linux/amd64`**, with Docker, in the build's sandbox (or the
276291 workflow job's Docker, for [`g1t-runner deploy`](#deploying-from-a-workflow)),
277292 with network access as any build has. **Build command** is not used:
864879 | A deployment **Skipped**, saying it reached its spend limit or that new compute is paused | The build was refused before it started. Follow the link in the message: raise the spend limit, prepay, or answer the spike, on Billing. |
865880 | "Stopped: unusual CPU use" | The build looked like it was mining. Contact support if it was a real build; see [abuse and mining](/guides/guardrails/#abuse-and-mining). |
866881 | "found nothing to serve" | Add a `Dockerfile`, a `build` script, an `index.html`, or a Workers config; or set **Output directory**. |
867−| "Docker deployments are not switched on for g1t.page yet" | The project is a container, which g1t.page does not run yet. Set **Build as** to Static site or Workers if it can be built as one. See [Docker deployments](#docker-deployments). |
882+| "Docker deployments are switched off on this g1t" | The project is a container, and this g1t (a self-hosted one) runs none. Set **Build as** to Static site or Workers if it can be built as one. See [Docker deployments](#docker-deployments). |
868883 | "**Build as** is Docker, but this project has no Dockerfile" | Add a `Dockerfile`, or set **Dockerfile** to its path. |
869884 | "The image is 2.4 GB, more than the 2.0 GB an app of its size (lite) can hold" | Make the image smaller (a slim base image, a multi-stage build), or choose a larger **Container size**. |
870885 | A container app says "The app did not start" | It did not answer on its port within 90 seconds. Make it listen on `0.0.0.0` at `PORT`, or `EXPOSE` the port it uses in its Dockerfile. Its output is in the build's log only while it builds; run the image locally with `docker run -e PORT=8080 -p 8080:8080` to see it start. |
894909 `npx wrangler secret put CLOUDFLARE_API_TOKEN` in `services/deployments`.
895910 4. Deploy `services/deployments`, `services/pages`, and the runner.
896911
897−Docker deployments also need the token to have **Containers: Edit**, a
898−Workers Paid plan with Containers, and `CONTAINERS` set to `on` in
899−`services/deployments/wrangler.jsonc`; see
912+Docker deployments also need the token to have **Containers: Edit** and
913+a Workers Paid plan with Containers; `CONTAINERS` in
914+`services/deployments/wrangler.jsonc` is `on`, and `off` turns them off
915+for an account without Containers. See
900916 [Docker deployments](/guides/deploy-to-cloudflare/#docker-deployments)
901−for what to check first.
917+for what to check on a new account.
902918
903919 Custom domains also need Cloudflare for SaaS on the apps' zone. Turn it on
904920 under the zone's **SSL/TLS → Custom Hostnames**, give the token **SSL and
+1−1
9292 | [Security](/guides/security/) | Secret push protection, history scanning and pull requests that upgrade vulnerable dependencies. | <Status is="live" /> |
9393 | [Deployments](/guides/deployments/) | A live preview of every pull request on g1t.page, production on merge, and custom domains. | <Status is="live" /> |
9494 | Preview data | Each preview gets its own copy of the database and bucket, deleted when the pull request closes. | <Status is="coming" /> |
95−| [Docker deployments](/guides/deployments/#docker-deployments) | Any app with a Dockerfile, or a Node.js, Python, Go, Ruby or PHP server, runs as a container that sleeps when no one visits. | <Status is="coming" /> |
95+| [Docker deployments](/guides/deployments/#docker-deployments) | Any app with a Dockerfile, or a Node.js, Python, Go, Ruby or PHP server, runs as a container that sleeps when no one visits. | <Status is="live" /> |
9696 | [Observability](/guides/observability/) | Requests, logs, traces, metrics and grouped errors, by deployment: from apps on g1t.page with nothing to set up, and from anywhere else over OpenTelemetry. | <Status is="live" /> |
9797 | Rollback and always on | One click back to any deploy, and container apps kept warm. | <Status is="coming" /> |
9898 | [GitHub](/guides/github/) | Import repositories with every branch and tag, and their issues. | <Status is="live" /> |
+2−2
110110 <p className="text-xs text-muted">
111111 Charged by the minute while awake, at what Cloudflare charges g1t plus 20%, with every vCPU counted as busy; data a
112112 container sends is {money(offer.egressGbMicros, { precise: true })} a GB.
113− {!offer.available && " Docker deployments are not switched on for g1t.page yet: until they are, a container build fails, or builds the site the project is without its Dockerfile."}
113+ {!offer.available && " Docker deployments are switched off on this g1t: a container build fails, or builds the site the project is without its Dockerfile."}
114114 </p>
115115 </div>
116116 );
172172 Build through a workflow g1t manages for this project, listed under Actions with its runs and logs. It runs on g1t's machines like any workflow, and a workflow named g1t in .g1t/workflows takes its place.
173173 </Check>
174174 <div className="grid gap-4 md:grid-cols-2">
175− <Field label="Build as" hint="Auto finds it from the project's files: a Wrangler config is Workers, a framework that builds a static site stays one, and a Dockerfile or a server makes it a container.">
175+ <Field label="Build as" hint="Auto finds it from the project's files: a Wrangler config is Workers; a Dockerfile that runs a server, or a server g1t recognises, is a container; anything else that builds a site stays one. The build's log says which it chose and why.">
176176 <SelectField name="buildAs" defaultValue={settings.buildAs ?? "auto"} aria-label="Build as" options={BUILD_AS_OPTIONS} />
177177 </Field>
178178 <Field label="Dockerfile" hint="For a container; Dockerfile or Containerfile is found by itself when empty.">
+7−5
5151 // The g1t.page zone: custom domains are Cloudflare for SaaS custom
5252 // hostnames on it (see src/domains.ts).
5353 "CUSTOM_HOSTNAMES_ZONE_ID": "45d1c969bdd9d593756e70d5f45c2cbb",
54− // Docker deployments (src/containers.ts): "on" runs container apps.
55− // Off until Cloudflare's container APIs are checked live against this
56− // account ("Docker deployments" in docs.g1t.sh/guides/deploy-to-cloudflare/);
57− // while off, a container build is refused at its registry step.
58− "CONTAINERS": "off",
54+ // Docker deployments (src/containers.ts): "on" runs container apps,
55+ // found from a project's files with nothing to set. "off" for an
56+ // account without Containers (a self-hosted g1t): a container build
57+ // is then refused at its registry step, or built as the site the
58+ // project is without its Dockerfile ("Docker deployments" in
59+ // docs.g1t.sh/guides/deploy-to-cloudflare/).
60+ "CONTAINERS": "on",
5961 // Where container apps' Workers report how long they ran.
6062 "G1T_API": "https://api.g1t.sh",
6163 // Cloudflare's own tracing of each app (a span for every fetch, KV,

Comments

Sign in to comment.