diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml index b09cb54b..8fcf8d39 100644 --- a/.devcontainer/docker-compose.yml +++ b/.devcontainer/docker-compose.yml @@ -1,6 +1,14 @@ -# Devcontainer services: dev environment + Postgres + Redis +# Devcontainer services: dev environment + Postgres + Redis. # Used by VS Code / Cursor "Reopen in Container". Root docker-compose.yml # provides the same Postgres/Redis stack for local (non-container) development. +# +# The `backend`, `frontend`, and `deps` services live behind the `app` profile +# so they are NOT started when the devcontainer opens (you run the dev servers +# yourself inside the container). Start the whole stack — Postgres, Redis, a +# one-time dependency install, backend, and frontend — with: +# +# scripts/devcontainer.sh up +# # or: docker compose -f .devcontainer/docker-compose.yml --profile app up services: devcontainer: @@ -46,6 +54,72 @@ services: timeout: 3s retries: 10 + # One-time dependency install shared by the backend/frontend services. + deps: + profiles: ['app'] + build: + context: .. + dockerfile: .devcontainer/Dockerfile + working_dir: /workspaces/agenticpay + command: sh -c "npm install --no-audit --no-fund" + volumes: + - ..:/workspaces/agenticpay:cached + - node-modules:/workspaces/agenticpay/node_modules + + backend: + profiles: ['app'] + build: + context: .. + dockerfile: .devcontainer/Dockerfile + working_dir: /workspaces/agenticpay + command: npm run dev --workspace=backend + volumes: + - ..:/workspaces/agenticpay:cached + - node-modules:/workspaces/agenticpay/node_modules + environment: + NODE_ENV: development + PORT: '3001' + DATABASE_URL: postgresql://postgres:postgres@postgres:5432/agenticpay + REDIS_URL: redis://redis:6379 + REDIS_ENABLED: 'true' + JOBS_ENABLED: 'false' + QUEUE_ENABLED: 'false' + OPENAI_API_KEY: sk-dev-placeholder-replace-me + CORS_ALLOWED_ORIGINS: 'http://localhost:3000,http://localhost:3001' + ports: + - '3001:3001' + depends_on: + deps: + condition: service_completed_successfully + postgres: + condition: service_healthy + redis: + condition: service_healthy + + frontend: + profiles: ['app'] + build: + context: .. + dockerfile: .devcontainer/Dockerfile + working_dir: /workspaces/agenticpay + command: npm run dev --workspace=frontend + volumes: + - ..:/workspaces/agenticpay:cached + - node-modules:/workspaces/agenticpay/node_modules + environment: + NODE_ENV: development + PORT: '3000' + NEXT_PUBLIC_API_URL: http://localhost:3001/api/v1 + NEXT_PUBLIC_BACKEND_URL: http://localhost:3001 + ports: + - '3000:3000' + depends_on: + deps: + condition: service_completed_successfully + backend: + condition: service_started + volumes: postgres-data: redis-data: + node-modules: diff --git a/Dockerfile.backend b/Dockerfile.backend index 42d21d9f..af04ddc7 100644 --- a/Dockerfile.backend +++ b/Dockerfile.backend @@ -11,19 +11,13 @@ WORKDIR /app/backend RUN npm run build FROM node:20-alpine AS runner - feat/print-onboarding-docker-ci-issues-836-837-839-838 RUN addgroup -S app && adduser -S app -G app - - main WORKDIR /app/backend ENV NODE_ENV=production COPY --from=builder /app/backend/package.json ./ COPY --from=builder /app/backend/dist ./dist COPY --from=deps /app/node_modules /app/node_modules - feat/print-onboarding-docker-ci-issues-836-837-839-838 RUN chown -R app:app /app USER app - - main -EXPOSE 4000 +EXPOSE 3001 CMD ["node", "dist/index.js"] diff --git a/Dockerfile.frontend b/Dockerfile.frontend index 2b151bfe..5e694e27 100644 --- a/Dockerfile.frontend +++ b/Dockerfile.frontend @@ -11,19 +11,14 @@ WORKDIR /app/frontend RUN npm run build FROM node:20-alpine AS runner - feat/print-onboarding-docker-ci-issues-836-837-839-838 RUN addgroup -S app && adduser -S app -G app - - main WORKDIR /app ENV NODE_ENV=production ENV HOSTNAME=0.0.0.0 COPY --from=builder /app/frontend/public ./frontend/public COPY --from=builder /app/frontend/.next/standalone ./ COPY --from=builder /app/frontend/.next/static ./frontend/.next/static - feat/print-onboarding-docker-ci-issues-836-837-839-838 RUN chown -R app:app /app USER app - main EXPOSE 3000 CMD ["node", "frontend/server.js"] diff --git a/README.md b/README.md index fc59b243..7d47f15d 100644 --- a/README.md +++ b/README.md @@ -75,7 +75,10 @@ Express.js API server providing: For one-click setup with Node.js, Rust, Soroban CLI, Postgres, and Redis, see [docs/DEVCONTAINER.md](docs/DEVCONTAINER.md). ```bash -# Or start only backend services on the host: +# One-command stack: Postgres, Redis, backend, and frontend +scripts/devcontainer.sh up + +# Or start only the infra (Postgres + Redis) on the host: docker compose up -d ``` diff --git a/docs/DEVCONTAINER.md b/docs/DEVCONTAINER.md index 506acbba..ea9c60f6 100644 --- a/docs/DEVCONTAINER.md +++ b/docs/DEVCONTAINER.md @@ -34,6 +34,34 @@ On the host machine (without devcontainer), start the same stack: docker compose up -d ``` +## One-command stack (no IDE required) + +To run Postgres, Redis, the backend, and the frontend together without opening +VS Code: + +```bash +scripts/devcontainer.sh up +``` + +Under the hood this starts the `backend`, `frontend`, and one-time `deps` install +services behind the `app` Compose profile, so they are **not** started when the +devcontainer opens (you run the dev servers yourself in that flow) — only when +you ask for them: + +```bash +docker compose -f .devcontainer/docker-compose.yml --profile app up -d --build +``` + +| Service | URL / address | +|---------|---------------| +| Frontend | http://localhost:3000 | +| Backend API | http://localhost:3001/api/v1 | +| Postgres | `localhost:5432` (postgres/postgres) | +| Redis | `localhost:6379` | + +`scripts/devcontainer.sh` also supports `down`, `logs [service]`, `ps`, +`restart [service]`, `shell`, and `config` (validate the Compose file). + ## Environment Variables The devcontainer sets safe defaults in `devcontainer.json`. Copy and customize for secrets: diff --git a/scripts/devcontainer.sh b/scripts/devcontainer.sh new file mode 100755 index 00000000..d2f1b4ec --- /dev/null +++ b/scripts/devcontainer.sh @@ -0,0 +1,74 @@ +#!/usr/bin/env bash +# Devcontainer orchestrator — Issue #794 +# +# Brings up the full local stack (Postgres, Redis, backend, frontend) with a +# single command, without opening VS Code. For the IDE-driven flow use +# "Dev Containers: Reopen in Container" and then run the dev servers inside. +set -euo pipefail + +ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +cd "$ROOT" + +COMPOSE_FILE=".devcontainer/docker-compose.yml" +PROFILE="app" + +compose() { + docker compose -f "$COMPOSE_FILE" --profile "$PROFILE" "$@" +} + +usage() { + cat <<'EOF' +Devcontainer stack orchestrator + +Usage: + scripts/devcontainer.sh up Build and start Postgres, Redis, backend, frontend + scripts/devcontainer.sh down Stop and remove the stack + scripts/devcontainer.sh logs [svc] Tail logs (optionally for one service) + scripts/devcontainer.sh ps Show service status + scripts/devcontainer.sh restart [svc] + scripts/devcontainer.sh shell Open a shell in the devcontainer service + scripts/devcontainer.sh config Validate the compose file + +After `up`: + Frontend : http://localhost:3000 + Backend : http://localhost:3001/api/v1 + Postgres : localhost:5432 (postgres/postgres) + Redis : localhost:6379 +EOF +} + +cmd="${1:-up}" +shift || true + +case "$cmd" in + up) + compose up -d --build + echo "Stack is up. Frontend: http://localhost:3000 Backend: http://localhost:3001/api/v1" + ;; + down) + compose down + ;; + logs) + compose logs -f "${1:-}" + ;; + ps) + compose ps + ;; + restart) + if [ -n "${1:-}" ]; then + compose restart "$1" + else + compose restart + fi + ;; + shell) + compose exec devcontainer bash + ;; + config) + compose config + ;; + *) + usage + exit 1 + ;; +esac