Docker
Local Compose stand-ins for local (SQLite), development (Postgres), and test (DynamoDB Local + Lambda RIE). The optional admin Compose profile adds MinIO (local CDN) and @tgmc/admin on port 4400 — not AWS CloudFront.
Operations (commands, ports, troubleshooting): docker/README.md
CI/CD matrix: cicd.md
Host .output
Compose reads workspace .output/<sysEnv> and does not rebuild Nuxt inside the image on every up. scripts/docker-compose.mjs maps:
| Stack | SYS_ENV |
Compose file | Image copy |
|---|---|---|---|
| local | local |
docker/docker-compose.local.yml |
Dockerfile.app .output/local |
| dev | development |
docker/docker-compose.dev.yml |
Dockerfile.app .output/development (api + web) |
| test | test |
docker/docker-compose.test.yml |
Dockerfile.lambda .output/test/server |
On build / --build, ensureNitroOutput runs first (SYS_ENV=… npm run build only if server/index.mjs is missing, then prune sharp + .npmrc). Linux images install native deps. .dockerignore allows .output/local|development|test.
Stacks
| Stack | Compose file | SYS_ENV |
Data | App ports |
|---|---|---|---|---|
| Local | docker/docker-compose.local.yml |
local |
SQLite (./data volume) |
web 4200 |
| Development | docker/docker-compose.dev.yml |
development |
PostgreSQL | web 4200, api 4100 |
| Local Lambda test | docker/docker-compose.test.yml |
test |
DynamoDB Local :8000 |
lambda-proxy 4300 |
Port 4200 is shared by host npm run dev, docker:local, and docker:dev — run only one of those at a time.
Hostnames: local → tgmc-portfolio.local; docker:dev → tgmc-portfolio.test (avoid *.dev — HSTS-preloaded). Map both to 127.0.0.1. See ssl-setup.md.
Commands (repo root)
npm run docker:build:local
npm run docker:local # SQLite via ./data; exclusive with docker:dev on :4200
npm run docker:local:down
npm run docker:build:dev
npm run docker:dev
npm run docker:dev:down
npm run docker:build:test # ensureNitroOutput(test) then Lambda image
npm run docker:test
npm run docker:test:down
Docker-only admin (standalone stack)
Blog, contact messages, and a local MinIO CDN stand-in. One admin UI with a database selector (sqlite |
postgres |
dynamodb). Not part of the public @tgmc/web app. |
cp .env.admin.example .env.admin # set ADMIN_TOKEN
npm run docker:admin
npm run docker:admin:down
Open http://127.0.0.1:4400/admin. See docs/web/features/admin.md.
npm run sam:build is still required to stage infra/sam/.aws-sam/build-src for SAM deploys; Compose test images copy .output/test directly.
Docker ↔ AWS
| Concern | Compose local | Compose dev | Compose test | AWS SAM |
|---|---|---|---|---|
| Data | SQLite ./data |
Postgres | DynamoDB Local | DynamoDB tables |
| App | Nitro node-server |
Nitro node-server (web + api) |
Nitro aws_lambda + RIE |
Lambda + HTTP API |
| Assets | Served by web | Served by web | Staged only (infra/sam/.aws-sam/build-src/public) |
Private S3 + CloudFront |
Images: Node 24 bookworm. Local/dev web/api share docker/Dockerfile.app (COPY .output/${SYS_ENV} → /app/.output). HEALTHCHECK --start-period is a literal 30s (BuildKit does not expand ARG there). Compose healthchecks use HTTPS curl -fkS when HTTPS=1.