README-dockerhub: clone-free quick start - self-contained compose, Ory config extracted from the image
This commit was merged in pull request #9.
This commit is contained in:
+134
-26
@@ -15,37 +15,144 @@ Pin the exact `X.Y.Z` you deploy.
|
||||
## Quick start
|
||||
|
||||
This image is the Plainpages web app plus its one-shot bootstrap seeder. It runs
|
||||
alongside Ory Kratos, Keto, Hydra and Postgres, all wired by the repo's compose files:
|
||||
alongside its Ory sidecars (Kratos, Keto) and Postgres — and it **ships their config**,
|
||||
so there is nothing to clone. In an empty directory, save this as `compose.yml`:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
web:
|
||||
image: larvit/plainpages:0.0.2
|
||||
ports:
|
||||
- "3000:3000"
|
||||
environment:
|
||||
APP_URL: http://localhost:3000
|
||||
depends_on:
|
||||
bootstrap:
|
||||
condition: service_completed_successfully
|
||||
kratos:
|
||||
condition: service_healthy
|
||||
keto:
|
||||
condition: service_healthy
|
||||
volumes:
|
||||
- ./ory/kratos/tokenizer:/etc/config/kratos/tokenizer:ro
|
||||
- ./plugins:/app/plugins
|
||||
restart: unless-stopped
|
||||
|
||||
# One-shot, idempotent seed: signing key if absent + the admin@plainpages.local / admin user.
|
||||
bootstrap:
|
||||
image: larvit/plainpages:0.0.2
|
||||
command: node src/auth/bootstrap.ts
|
||||
depends_on:
|
||||
kratos:
|
||||
condition: service_healthy
|
||||
keto:
|
||||
condition: service_healthy
|
||||
volumes:
|
||||
- ./ory/kratos/tokenizer:/etc/config/kratos/tokenizer
|
||||
- ./plugins:/app/plugins:ro
|
||||
restart: "on-failure:5"
|
||||
|
||||
postgres:
|
||||
image: postgres:18.4-alpine3.23
|
||||
environment:
|
||||
POSTGRES_DB: ory
|
||||
POSTGRES_PASSWORD: ory
|
||||
POSTGRES_USER: ory
|
||||
volumes:
|
||||
- ./ory/postgres/init:/docker-entrypoint-initdb.d:ro
|
||||
- pgdata:/var/lib/postgresql
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U ory -d ory"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 10
|
||||
restart: unless-stopped
|
||||
|
||||
kratos-migrate:
|
||||
image: oryd/kratos:v26.2.0
|
||||
command: -c /etc/config/kratos/kratos.yml migrate sql -e --yes
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
environment:
|
||||
DSN: postgres://ory:ory@postgres:5432/kratos?sslmode=disable
|
||||
volumes:
|
||||
- ./ory/kratos:/etc/config/kratos:ro
|
||||
restart: on-failure
|
||||
|
||||
kratos:
|
||||
image: oryd/kratos:v26.2.0
|
||||
command: serve -c /etc/config/kratos/kratos.yml --watch-courier
|
||||
ports:
|
||||
- "4433:4433" # the login form POSTs straight to Kratos from the browser
|
||||
depends_on:
|
||||
kratos-migrate:
|
||||
condition: service_completed_successfully
|
||||
environment:
|
||||
DSN: postgres://ory:ory@postgres:5432/kratos?sslmode=disable
|
||||
volumes:
|
||||
- ./ory/kratos:/etc/config/kratos:ro
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "-qO-", "http://127.0.0.1:4433/health/ready"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 20
|
||||
restart: unless-stopped
|
||||
|
||||
keto-migrate:
|
||||
image: oryd/keto:v26.2.0
|
||||
command: -c /etc/config/keto/keto.yml migrate up -y
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
environment:
|
||||
DSN: postgres://ory:ory@postgres:5432/keto?sslmode=disable
|
||||
volumes:
|
||||
- ./ory/keto:/etc/config/keto:ro
|
||||
restart: on-failure
|
||||
|
||||
keto:
|
||||
image: oryd/keto:v26.2.0
|
||||
command: serve -c /etc/config/keto/keto.yml
|
||||
depends_on:
|
||||
keto-migrate:
|
||||
condition: service_completed_successfully
|
||||
environment:
|
||||
DSN: postgres://ory:ory@postgres:5432/keto?sslmode=disable
|
||||
volumes:
|
||||
- ./ory/keto:/etc/config/keto:ro
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "-qO-", "http://127.0.0.1:4466/health/ready"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 20
|
||||
restart: unless-stopped
|
||||
|
||||
# Catches Kratos' recovery/verification emails — UI on http://localhost:8025
|
||||
mailpit:
|
||||
image: axllent/mailpit:v1.30.1
|
||||
ports:
|
||||
- "8025:8025"
|
||||
restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
pgdata:
|
||||
```
|
||||
|
||||
Extract the Ory config the image ships, then start:
|
||||
|
||||
```bash
|
||||
git clone https://gitea.larvit.se/larvit/plainpages.git
|
||||
cd plainpages
|
||||
docker run --rm larvit/plainpages:0.0.2 tar -cf - ory | tar -xf -
|
||||
mkdir -p plugins
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
Open <http://localhost:3000> and sign in as `admin@plainpages.local` / `admin`.
|
||||
(The dev stack builds the image locally and live-reloads.)
|
||||
|
||||
To deploy this published image instead of building, add an override and run the
|
||||
production stack:
|
||||
|
||||
```yaml
|
||||
# compose.image.yml
|
||||
services:
|
||||
bootstrap:
|
||||
image: larvit/plainpages:0.0.2
|
||||
pull_policy: missing
|
||||
web:
|
||||
image: larvit/plainpages:0.0.2
|
||||
pull_policy: missing
|
||||
```
|
||||
|
||||
```bash
|
||||
CSRF_SECRET=<long random> docker compose -f compose.yml -f compose.image.yml up -d
|
||||
```
|
||||
|
||||
Production expects https and real secrets (`CSRF_SECRET`, `POSTGRES_USER`/`PASSWORD`,
|
||||
a fresh JWT signing key) — see the repo README → Production & deployment.
|
||||
This quick start runs http-on-localhost with dev-throwaway secrets, and omits Hydra (the
|
||||
OAuth2 provider — only needed when other apps log in *through* Plainpages). For
|
||||
production — https, real secrets (`CSRF_SECRET`, Postgres credentials, a fresh JWT
|
||||
signing key), Hydra — see the repo README → Production & deployment.
|
||||
|
||||
## Configuration
|
||||
|
||||
@@ -67,7 +174,8 @@ Full list (JWT/JWKS, timeouts, instant revoke): repo README → Configuration.
|
||||
|
||||
## Your first plugin
|
||||
|
||||
Everything domain-specific is a plugin folder. Create `plugins/hello/plugin.ts`:
|
||||
Everything domain-specific is a plugin folder — the compose above mounts `./plugins`
|
||||
into the app. Create `plugins/hello/plugin.ts`:
|
||||
|
||||
```ts
|
||||
import { definePlugin } from "#plugin-api";
|
||||
@@ -76,7 +184,7 @@ export default definePlugin({
|
||||
apiVersion: "1.0.0",
|
||||
nav: [{ href: "/hello", id: "hello", label: "Hello", public: true }],
|
||||
routes: [
|
||||
{ method: "GET", path: "/", public: true, handler: () => ({ html: "<h1>Hello</h1>" }) },
|
||||
{ method: "GET", path: "/", public: true, handler: () => ({ html: "<h1>Hello from my plugin</h1>" }) },
|
||||
],
|
||||
});
|
||||
```
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
- [x] CI/CD - Build docker images as part of the requirements to be able to merge to main. Push them with the git commit hash as docker tag. Push to container registry at Gitea. (`ci.yml` builds + pushes `gitea.larvit.se/larvit/plainpages:<commit hash>` after a green gate — with ff-only merges that is the main commit's image; auth via the `DOCKER_REGISTRY_USER` variable + `DOCKER_REGISTRY_TOKEN` secret, retention via an org cleanup rule; documented in README → CI/CD.)
|
||||
- [x] CI/CD - Re-tag docker images from git hash to semver when a semver git tag is pushed. (`release.yml` on a `vX.Y.Z` tag pulls the commit-hash image and re-tags it `X.Y.Z`/`X.Y`/`X`/`latest`, failing loud if the gated image is missing; tag pushes also trigger the GitHub mirror; documented in README → CI/CD.)
|
||||
- [x] CI/CD - Sync docker images to docker hub after each re-tag to git tags. (`release.yml` pushes the same `X.Y.Z`/`X.Y`/`X`/`latest` tags to `docker.io/larvit/plainpages` after the Gitea re-tag — releases only, no hash tags; auth via the `DOCKERHUB_USER` variable + `DOCKERHUB_TOKEN` secret; documented in README → CI/CD.)
|
||||
- [x] Write a short text on how to use this docker image to publish on docker hub and save it to README-dockerhub.md (tagline, tags, compose quick start + published-image override, env table, first plugin; pasted into the Docker Hub overview by hand — noted in README → CI/CD.)
|
||||
- [x] Write a short text on how to use this docker image to publish on docker hub and save it to README-dockerhub.md (tagline, tags, clone-free quick start — the image ships the Ory config, extracted via `docker run … tar` + a self-contained compose.yml — env table, first plugin; pasted into the Docker Hub overview by hand — noted in README → CI/CD.)
|
||||
- [ ] CI/CD - Setup renovate bot. Check how other repos on this Gitea is setup you can get access to, there should be a number of renovate bot activated ones.
|
||||
- [ ] Add an e2e test for the admin plugin's OAuth2-clients (Hydra) screen. The full-flow e2e suite runs without Hydra (compose.full.yml), so /admin/clients register/detail/delete is only unit-covered (src/http/app.test.ts); wire Hydra into an e2e stack and drive the screen in the browser.
|
||||
- [ ] Build and publish docker image as CI/CD.
|
||||
|
||||
Reference in New Issue
Block a user