build: tighten Docker setup for local-stack parity
- Dockerfile: npm ci (uses package-lock for reproducible installs) - CMD now: migrate → seed (idempotent) → start. Gated by SEED_ON_BOOT. - docker-compose: name: helix, healthcheck on /, OAuth env defaults to empty so `docker compose up` works without a .env (public pages render; sign-in fails until OAuth is configured). - README: explicit "Run it locally — two ways" section. Docker first (production-like), native Node second. Documents port-conflict workaround and Gitea OAuth setup. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -9,8 +9,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
python3 make g++ \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
COPY package.json package-lock.json* ./
|
||||
RUN npm install --include=dev
|
||||
COPY package.json package-lock.json ./
|
||||
RUN npm ci --include=dev
|
||||
|
||||
COPY . .
|
||||
RUN npm run build
|
||||
@@ -39,5 +39,6 @@ COPY --from=build --chown=node:node /app/scripts ./scripts
|
||||
USER node
|
||||
EXPOSE 3000
|
||||
|
||||
# Run migrations then start the SvelteKit Node server.
|
||||
CMD ["sh", "-c", "node scripts/migrate.js && node build"]
|
||||
# Run migrations + seed (idempotent INSERT OR IGNORE) then start the server.
|
||||
# Set SEED_ON_BOOT=false in production once you've added real content.
|
||||
CMD ["sh", "-c", "node scripts/migrate.js && { [ \"$SEED_ON_BOOT\" = \"false\" ] || node scripts/seed.js; } && node build"]
|
||||
|
||||
71
README.md
71
README.md
@@ -17,18 +17,57 @@ to the `RnD` Gitea organisation; viewing is open.
|
||||
- **Gitea OAuth2** for authoring (no passwords stored)
|
||||
- Pure **SVG + CSS** helix animation — no WebGL
|
||||
|
||||
## Local development
|
||||
## Run it locally — two ways
|
||||
|
||||
### 1. Docker (production-like, recommended for testing)
|
||||
|
||||
Mirrors how the EVOLV stack is exercised locally. One command, named volume
|
||||
for SQLite, healthcheck wired:
|
||||
|
||||
```bash
|
||||
nvm use # picks up .nvmrc → Node 20
|
||||
cp .env.example .env
|
||||
# Fill in GITEA_CLIENT_ID and GITEA_CLIENT_SECRET (see "Gitea OAuth setup" below)
|
||||
cd /path/to/helix
|
||||
docker compose up -d --build # build image + start container
|
||||
docker compose logs -f helix # tail logs
|
||||
# → http://localhost:3000
|
||||
```
|
||||
|
||||
If port 3000 is in use (Node-RED, another dev server, …) pick another:
|
||||
|
||||
```bash
|
||||
HELIX_PORT=3030 \
|
||||
ORIGIN=http://localhost:3030 \
|
||||
GITEA_REDIRECT_URI=http://localhost:3030/auth/gitea/callback \
|
||||
docker compose up -d --build
|
||||
# → http://localhost:3030
|
||||
```
|
||||
|
||||
Useful commands:
|
||||
|
||||
```bash
|
||||
docker compose ps # status + health
|
||||
docker inspect helix --format '{{.State.Health.Status}}'
|
||||
docker compose exec helix sh # shell into the container
|
||||
docker compose exec helix sqlite3 /data/helix.db # inspect the DB
|
||||
docker compose down # stop (keeps the volume)
|
||||
docker compose down -v # stop + DELETE all data
|
||||
```
|
||||
|
||||
The SQLite database lives in the **`helix_helix-data`** named volume at
|
||||
`/data/helix.db`. Migrations + the idempotent seed both run on every boot.
|
||||
Once you have real content, set `SEED_ON_BOOT=false` in your env to stop
|
||||
re-seeding the demo entries.
|
||||
|
||||
### 2. Native Node (faster dev loop, hot reload)
|
||||
|
||||
```bash
|
||||
nvm use # .nvmrc → Node 20 (Tailwind v3 also works on 18)
|
||||
cp .env.example .env # fill in Gitea OAuth — see below
|
||||
|
||||
npm install
|
||||
npm run db:generate # produces drizzle/0000_*.sql from the schema
|
||||
npm run db:migrate # applies migrations to ./helix.db
|
||||
npm run db:seed # adds example projects + posts so the landing page isn't empty
|
||||
npm run dev # http://localhost:3000
|
||||
npm run db:generate # generate drizzle/0000_*.sql from the schema
|
||||
npm run db:migrate # apply migrations to ./helix.db
|
||||
npm run db:seed # idempotent demo content
|
||||
npm run dev # http://localhost:5173
|
||||
```
|
||||
|
||||
## Gitea OAuth setup
|
||||
@@ -58,15 +97,23 @@ origins can be embedded inline on a project page. Add a hostname (no scheme,
|
||||
no path) and redeploy. Hosts not on the list render as a "Open in new tab" card
|
||||
instead — never blindly iframed.
|
||||
|
||||
## Production deploy (Docker)
|
||||
## Production deploy
|
||||
|
||||
Same compose file as local. On the production host:
|
||||
|
||||
```bash
|
||||
cp .env.example .env # fill in Gitea OAuth + ORIGIN
|
||||
cp .env.example .env
|
||||
# Set: ORIGIN=https://your-host, GITEA_REDIRECT_URI=https://your-host/auth/gitea/callback,
|
||||
# GITEA_CLIENT_ID, GITEA_CLIENT_SECRET (from a separate prod OAuth app)
|
||||
docker compose up -d --build
|
||||
```
|
||||
|
||||
The SQLite database lives in the `helix-data` named volume at `/data/helix.db`.
|
||||
Back it up with `docker compose exec helix sqlite3 /data/helix.db .dump`.
|
||||
Put a TLS-terminating reverse proxy (nginx/caddy/traefik) in front of port 3000.
|
||||
Back up the volume periodically:
|
||||
|
||||
```bash
|
||||
docker compose exec helix sqlite3 /data/helix.db .dump | gzip > helix-backup-$(date +%F).sql.gz
|
||||
```
|
||||
|
||||
## Project layout
|
||||
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
name: helix
|
||||
|
||||
services:
|
||||
helix:
|
||||
build: .
|
||||
build:
|
||||
context: .
|
||||
container_name: helix
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
@@ -11,12 +14,18 @@ services:
|
||||
ORIGIN: ${ORIGIN:-http://localhost:3000}
|
||||
DATABASE_URL: /data/helix.db
|
||||
GITEA_BASE_URL: ${GITEA_BASE_URL:-https://gitea.wbd-rd.nl}
|
||||
GITEA_CLIENT_ID: ${GITEA_CLIENT_ID}
|
||||
GITEA_CLIENT_SECRET: ${GITEA_CLIENT_SECRET}
|
||||
GITEA_CLIENT_ID: ${GITEA_CLIENT_ID:-}
|
||||
GITEA_CLIENT_SECRET: ${GITEA_CLIENT_SECRET:-}
|
||||
GITEA_REDIRECT_URI: ${GITEA_REDIRECT_URI:-http://localhost:3000/auth/gitea/callback}
|
||||
GITEA_ALLOWED_ORG: ${GITEA_ALLOWED_ORG:-RnD}
|
||||
volumes:
|
||||
- helix-data:/data
|
||||
healthcheck:
|
||||
test: ["CMD", "node", "-e", "fetch('http://127.0.0.1:3000/').then(r => process.exit(r.ok ? 0 : 1)).catch(() => process.exit(1))"]
|
||||
interval: 15s
|
||||
timeout: 5s
|
||||
retries: 4
|
||||
start_period: 10s
|
||||
|
||||
volumes:
|
||||
helix-data:
|
||||
|
||||
Reference in New Issue
Block a user