Skip to content

Commit 39044ec

Browse files
authored
Merge pull request #267 from unicef/improvement/docker-accessibility-fix
Fix Docker API crash on startup (jsdom bundling) + Docker CI + docs
2 parents 0ae52d2 + 2a40640 commit 39044ec

File tree

4 files changed

+52
-2
lines changed

4 files changed

+52
-2
lines changed

.github/workflows/ci.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,13 @@ jobs:
2222
- run: pnpm typecheck
2323
- run: pnpm test
2424

25+
docker:
26+
runs-on: ubuntu-latest
27+
steps:
28+
- uses: actions/checkout@v4
29+
- name: Build Docker api target
30+
run: docker build --target api .
31+
2532
i18n:
2633
runs-on: ubuntu-latest
2734
steps:

CLAUDE.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,48 @@ The `PIPELINE` constant in `@adt/types` defines all stages, their steps, labels,
6565

6666
**Never hardcode stage/step ordering, names, or groupings outside of `PIPELINE`.** If you need a new derived lookup, add it to `packages/types/src/pipeline.ts` alongside the existing ones (`STAGE_ORDER`, `STEP_TO_STAGE`, `STAGE_BY_NAME`, `ALL_STEP_NAMES`).
6767

68+
## Docker
69+
70+
Three build targets in `Dockerfile`:
71+
72+
| Target | Description | Used by |
73+
|--------|-------------|---------|
74+
| `api` | Node.js API server only | `docker-compose.yml` (multi-container) |
75+
| `studio` | nginx serving the built SPA | `docker-compose.yml` (multi-container) |
76+
| `app` | Combined single-image (API + nginx) | Release CI → `ghcr.io/unicef/adt-studio` |
77+
78+
```bash
79+
# Multi-container — local testing (two separate services)
80+
docker compose up --build
81+
82+
# Single-image — same image end users download
83+
docker build --target app -t adt-studio .
84+
docker run -p 8080:80 -v ./books:/app/books adt-studio
85+
```
86+
87+
**Runtime env vars and volumes:**
88+
89+
| Env var | Default | Override |
90+
|---------|---------|--------|
91+
| `BOOKS_DIR` | `/app/books` | `-v ./books:/app/books` |
92+
| `PROMPTS_DIR` | `/app/prompts` | `-v ./prompts:/app/prompts` |
93+
| `CONFIG_PATH` | `/app/config.yaml` | `-v ./config.yaml:/app/config.yaml:ro` |
94+
| `PORT` | `3001` | Internal only — nginx proxies to this |
95+
96+
**`TEMPLATES_DIR` trap:** The Dockerfile and `docker-compose.yml` set `TEMPLATES_DIR=/app/templates` but the application **never reads this env var**. Templates dir is always derived from `path.join(path.dirname(PROMPTS_DIR), "templates")`. To use a custom templates directory, mount it as a sibling of `prompts/` — i.e. override `PROMPTS_DIR` and keep `templates/` next to it.
97+
98+
**Release pipeline:** pushing a `v*` tag triggers `.github/workflows/release.yml` which builds the `app` target and pushes to `ghcr.io/unicef/adt-studio:latest` and `ghcr.io/unicef/adt-studio:<tag>`. A ready-to-use `docker-compose.yml` (generated from `docker/compose-release.yml.template`) is uploaded as a release asset.
99+
100+
**Key Docker files:**
101+
- `Dockerfile` — multi-stage build (base → deps → build → api / studio / app)
102+
- `docker-compose.yml` — local dev/testing (multi-container)
103+
- `docker/nginx.conf` — nginx config for the `studio` stage (proxies to `http://api:3001`)
104+
- `docker/nginx-single.conf` — nginx config for the `app` stage (proxies to `http://127.0.0.1:3001`)
105+
- `docker/entrypoint.sh` — starts API + nginx in the `app` stage, health-checks API before nginx starts
106+
- `docker/compose-release.yml.template` — template for the release asset
107+
108+
**External packages in Docker:** `jsdom`, `esbuild`, `tailwindcss`, `postcss`, and `playwright` cannot be bundled by esbuild because they read data files relative to their own `__dirname`. They are installed into `apps/api/dist/node_modules/` by the Dockerfile build stage via npm. If a new package exhibits the same pattern (ENOENT error pointing to a path under `/app/apps/`), add it to both the `external` array in `apps/api/scripts/bundle-server.mjs` and the npm install step in the Dockerfile.
109+
68110
## Commands
69111

70112
```bash

Dockerfile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,8 @@ RUN --mount=type=cache,target=/root/.npm \
6767
esbuild: p.devDependencies.esbuild, \
6868
tailwindcss: p.dependencies.tailwindcss, \
6969
postcss: p.dependencies.postcss, \
70-
playwright: p.dependencies.playwright \
70+
playwright: p.dependencies.playwright, \
71+
jsdom: p.dependencies.jsdom \
7172
} \
7273
})); \
7374
" && \

apps/api/scripts/bundle-server.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ await build({
3030
// bundle time. All four are installed into dist/node_modules/ by the Dockerfile
3131
// build stage. npm handles esbuild's platform binary (@esbuild/linux-x64)
3232
// as an optional dependency automatically.
33-
external: ["esbuild", "tailwindcss", "postcss", "playwright", "playwright-core"],
33+
external: ["esbuild", "tailwindcss", "postcss", "playwright", "playwright-core", "jsdom"],
3434
banner: {
3535
js: [
3636
// Polyfill __dirname, __filename, and require for ESM

0 commit comments

Comments
 (0)