diff --git a/docs/deploy.md b/docs/deploy.md index 1146a8b..6524dbb 100644 --- a/docs/deploy.md +++ b/docs/deploy.md @@ -4,27 +4,51 @@ > container to follow a few consistent rules and deploying is mostly handing us a > `compose.yaml`. -!!! tip "What can run here" +!!! success "What can run here" APIs, websites, applets, bots, monitors. ## Preparing for Deploy -Get these three right and your repo is deployable — you don't run any deploy commands -yourself, the ops tooling takes it from git. Each tab is one piece. +!!! abstract "The whole flow" + You build and test locally — leaning on our libraries, AI, and this handbook — + then push a branch and merge to `main`. From there the ops tooling takes over: it + builds the Docker image and runs it on the fleet. **You don't run any deploy + commands** — your only job is the three pieces in the tabs below. + +```mermaid +flowchart LR + subgraph build ["you build"] + direction TB + local["local testing"] + libs["libs
(rethink-public, pip)"] + ai["AI-assisted
(Claude Code)"] + docs["reading the
handbook"] + local --- libs + libs --- ai + ai --- docs + docs --- local + end + + build -->|branch| git["git
(Gitea)"] + git --> main["main"] + main --> deploy["deployment
(ops tooling)"] + deploy --> docker["docker
(image built + run on the fleet)"] + + classDef ship fill:#061541,stroke:#569bcc,color:#eef1f6; + classDef work fill:#0e1530,stroke:#294274,color:#eef1f6; + class git,main,deploy,docker ship; + class local,libs,ai,docs work; +``` !!! danger "Your compose names nothing repo-specific" - **No `container_name`. No hardcoded names, workspace, or `/srv` paths.** The - deploy layer injects identity and host paths at deploy time — your compose stays - generic so it can't collide with any other service on the fleet. + **No `container_name`, no hardcoded names/paths.** The deploy layer injects + identity and host paths so your compose can't collide with any other service on + the fleet: - the service key is **always `svc`** — it never changes, in any repo - named volumes use **bare names** (`cache`, not `myapp_cache`) - host paths come from **`${LOGS_DIR}` / `${CONFIG_DIR}`** - Naming things after your repo used to cause **container-name collisions** at - fleet scale — two repos shipping the same name clashed. The generic compose in - the **Compose** tab fixes that. - === "Compose" The `compose.yaml` your repo ships. Copy it verbatim — it names nothing @@ -49,38 +73,22 @@ yourself, the ops tooling takes it from git. Each tab is one piece. cache: # bare name — deploy auto-prefixes it per service ``` - **The rules:** - - - **Service key is always `svc`** — never a repo-specific name, never a - `container_name`. The ops tooling keys off `svc`; this is what makes services - collision-proof on the fleet. - - **`user: "1337:1337"` and `restart: unless-stopped` are required** — the shared - `services` account (uid/gid 1337, fixed fleet-wide), and Docker's restart policy - recovering a crashed container (the host unit is oneshot). - - **Host paths come from `${...}` variables, never hardcoded.** Write to - `${LOGS_DIR}` and `${CONFIG_DIR}`; `${MOUNTS_DIR}` is optional. - - **Named volumes use bare names** (`cache`, not `myapp_cache`) — deploy - auto-prefixes them per service so they can't collide. - - !!! tip "The container path is where your code reads and writes" + !!! example "The container path is where your code reads and writes" `WORKDIR` is `/app`, so the **right-hand side** of each volume line is the path - your code targets. If your app writes to `./cache` (i.e. `/app/cache`), that's - the `cache` mount; logs go to `/app/logs`, config is read from `/app/config`. + your code targets. Write to `./cache` (i.e. `/app/cache`) → the `cache` volume; + logs go to `/app/logs`, config is read from `/app/config`. - **Three tiers of storage:** + **Storage, three tiers:** - - **`logs`** (output) and **`config`** (input you edit) — **we handle these**: - injected and managed at deploy time. - - **`mounts`** (optional) — a host dir for arbitrary read/write data. The deploy - layer **injects `MOUNTS_DIR` and auto-creates the dir**, but the mount line is - **opt-in**: uncomment it and choose the container path yourself (it's - app-specific, so it can't be auto-mounted). - - **Named volumes** (`cache`, …) — **yours**: anything else your service persists. - Docker owns them, no host paths to manage. + - **`logs` + `config`** — we inject and manage these at deploy time. + - **`mounts`** (optional) — host dir for arbitrary data. We inject `MOUNTS_DIR` and + create the dir; you **uncomment** the line and pick the container path. + - **Named volumes** (`cache`, …) — yours; Docker owns them, no host paths to manage. - Locally, `docker compose up` needs nothing set — the `${VAR:-./default}` fallbacks - use `./logs`, `./config` (and `./mounts` if you enable it). When deployed, the ops - tooling sets the real values, so the same file works both places. + !!! success "Same file, both places" + Locally, `docker compose up` needs nothing set — the `${VAR:-./default}` + fallbacks use `./logs` / `./config`. When deployed, the ops tooling sets the + real values. One `compose.yaml` works everywhere. **Subprocess and browser workloads** (bots that spawn Chrome, Xvfb, ffmpeg) need three extra knobs: @@ -173,35 +181,3 @@ yourself, the ops tooling takes it from git. Each tab is one piece. **Rotating a secret** is a host-side edit — update the file and the service picks it up on restart. No rebuild, and nothing you run: flag it and we handle the restart. - -## The path to deploy - -You build and test locally — leaning on our libraries, AI, and this handbook — then -push to git. From there it's staging (if you're running gitflow) and, once it's good, -deployment: the ops tooling builds the Docker image and starts it on the fleet. - -```mermaid -flowchart LR - subgraph build ["you build"] - direction TB - local["local testing"] - libs["our libraries
(rethink-public)"] - ai["AI-assisted
(Claude Code)"] - docs["reading the
handbook"] - local --- libs - libs --- ai - ai --- docs - docs --- local - end - - build -->|push| git["git
(Gitea)"] - git -.->|develop, if gitflow| stage["staging"] - git --> deploy["deployment
(ops tooling)"] - stage --> deploy - deploy --> docker["docker
(image built + run on the fleet)"] - - classDef ship fill:#061541,stroke:#569bcc,color:#eef1f6; - classDef work fill:#0e1530,stroke:#294274,color:#eef1f6; - class git,stage,deploy,docker ship; - class local,libs,ai,docs work; -```