chore: archive both OpenSpec changes and sync specs to main
This commit is contained in:
parent
a6e763c153
commit
50229e2ccf
25 changed files with 927 additions and 1 deletions
203
openspec/specs/docker-deployment/spec.md
Normal file
203
openspec/specs/docker-deployment/spec.md
Normal file
|
|
@ -0,0 +1,203 @@
|
|||
## ADDED Requirements
|
||||
|
||||
### Requirement: Multi-stage Dockerfile
|
||||
The project SHALL include a Dockerfile with multi-stage build for optimized production images.
|
||||
|
||||
#### Scenario: Build stage setup
|
||||
- **WHEN** Dockerfile build stage executes
|
||||
- **THEN** uses Node.js 18-alpine base image, copies package files, installs ALL dependencies including devDependencies, copies source code, and runs `npm run build`
|
||||
|
||||
#### Scenario: Runtime stage setup
|
||||
- **WHEN** Dockerfile runtime stage executes
|
||||
- **THEN** uses Node.js 18-alpine base image, creates non-root user 'appuser', copies only production dependencies and built files from build stage, and sets USER to appuser
|
||||
|
||||
#### Scenario: Working directory structure
|
||||
- **WHEN** container runs
|
||||
- **THEN** application files are in /app directory, database volume mounts to /app/data, and permissions allow appuser to write to /app/data
|
||||
|
||||
#### Scenario: Environment variables in Dockerfile
|
||||
- **WHEN** Dockerfile defines environment
|
||||
- **THEN** sets NODE_ENV=production, PORT=3000, and HOSTNAME=0.0.0.0 for Next.js standalone server
|
||||
|
||||
#### Scenario: Exposed ports
|
||||
- **WHEN** container is built
|
||||
- **THEN** Dockerfile exposes port 3000 for HTTP traffic
|
||||
|
||||
#### Scenario: Container startup
|
||||
- **WHEN** container starts
|
||||
- **THEN** executes `node server.js` (Next.js standalone output) as the CMD
|
||||
|
||||
### Requirement: Docker Compose configuration
|
||||
The project SHALL include docker-compose.yml for simplified deployment orchestration.
|
||||
|
||||
#### Scenario: Service definition
|
||||
- **WHEN** docker-compose.yml is parsed
|
||||
- **THEN** defines single service named 'candle-annotator' using Dockerfile from current directory
|
||||
|
||||
#### Scenario: Port mapping
|
||||
- **WHEN** docker-compose up runs
|
||||
- **THEN** maps host port 3000 to container port 3000 (configurable via PORT environment variable)
|
||||
|
||||
#### Scenario: Volume mounting for database
|
||||
- **WHEN** docker-compose up runs
|
||||
- **THEN** mounts named volume 'candle-data' to /app/data in container for SQLite database persistence
|
||||
|
||||
#### Scenario: Environment variable configuration
|
||||
- **WHEN** docker-compose.yml is used
|
||||
- **THEN** supports loading environment variables from .env file for NODE_ENV, PORT, and other configs
|
||||
|
||||
#### Scenario: Restart policy
|
||||
- **WHEN** container crashes or stops
|
||||
- **THEN** docker-compose automatically restarts container unless explicitly stopped (restart: unless-stopped)
|
||||
|
||||
#### Scenario: Volume declaration
|
||||
- **WHEN** docker-compose.yml is parsed
|
||||
- **THEN** declares 'candle-data' as named volume in volumes section
|
||||
|
||||
### Requirement: Environment variable configuration
|
||||
The project SHALL use environment variables for runtime configuration.
|
||||
|
||||
#### Scenario: .env.example file
|
||||
- **WHEN** repository is cloned
|
||||
- **THEN** includes .env.example file documenting all configurable environment variables with example values
|
||||
|
||||
#### Scenario: PORT configuration
|
||||
- **WHEN** PORT environment variable is set
|
||||
- **THEN** Next.js server listens on specified port (default: 3000)
|
||||
|
||||
#### Scenario: NODE_ENV configuration
|
||||
- **WHEN** NODE_ENV environment variable is set to 'production'
|
||||
- **THEN** Next.js runs in production mode with optimizations enabled
|
||||
|
||||
#### Scenario: Database path configuration
|
||||
- **WHEN** DATABASE_PATH environment variable is set (optional)
|
||||
- **THEN** SQLite database file is created at specified path (default: ./data/candles.db)
|
||||
|
||||
#### Scenario: HOSTNAME configuration
|
||||
- **WHEN** HOSTNAME environment variable is set
|
||||
- **THEN** Next.js server binds to specified hostname (default: 0.0.0.0 for containers)
|
||||
|
||||
### Requirement: Health check endpoint
|
||||
The API SHALL provide a health check endpoint for container orchestration.
|
||||
|
||||
#### Scenario: Health check endpoint responds
|
||||
- **WHEN** GET request sent to `/api/health`
|
||||
- **THEN** system returns 200 status with JSON `{ status: 'ok', timestamp: <unix_timestamp> }`
|
||||
|
||||
#### Scenario: Database connection check
|
||||
- **WHEN** GET request sent to `/api/health?check=db`
|
||||
- **THEN** system attempts simple database query and returns 200 if successful, 503 if database unavailable
|
||||
|
||||
#### Scenario: Health check in Dockerfile
|
||||
- **WHEN** Dockerfile defines HEALTHCHECK
|
||||
- **THEN** runs `curl -f http://localhost:3000/api/health || exit 1` every 30 seconds with 3 retries
|
||||
|
||||
### Requirement: .dockerignore file
|
||||
The project SHALL include .dockerignore to exclude unnecessary files from Docker context.
|
||||
|
||||
#### Scenario: Excluded files
|
||||
- **WHEN** Docker build context is created
|
||||
- **THEN** .dockerignore excludes node_modules, .next, .git, data/, *.md, .env*, and test files
|
||||
|
||||
#### Scenario: Included files
|
||||
- **WHEN** Docker build context is created
|
||||
- **THEN** includes package.json, package-lock.json, source code in src/, and required config files
|
||||
|
||||
### Requirement: Next.js standalone output
|
||||
The build SHALL use Next.js standalone output mode for minimal production bundle.
|
||||
|
||||
#### Scenario: next.config.js standalone setting
|
||||
- **WHEN** next.config.js is read
|
||||
- **THEN** output property is set to 'standalone'
|
||||
|
||||
#### Scenario: Standalone build output
|
||||
- **WHEN** npm run build executes
|
||||
- **THEN** Next.js creates .next/standalone directory with minimal runtime files and dependencies
|
||||
|
||||
#### Scenario: Copy standalone files to image
|
||||
- **WHEN** Dockerfile runtime stage executes
|
||||
- **THEN** copies .next/standalone/ contents to /app, copies .next/static to /app/.next/static, and copies public/ to /app/public
|
||||
|
||||
### Requirement: Production build optimization
|
||||
The Docker image SHALL be optimized for production use with minimal size.
|
||||
|
||||
#### Scenario: Use alpine base images
|
||||
- **WHEN** Dockerfile specifies base images
|
||||
- **THEN** uses node:18-alpine for both build and runtime stages
|
||||
|
||||
#### Scenario: Multi-stage build cleanup
|
||||
- **WHEN** Docker image is built
|
||||
- **THEN** build artifacts, devDependencies, and source files are not included in final image
|
||||
|
||||
#### Scenario: Layer caching optimization
|
||||
- **WHEN** Dockerfile is structured
|
||||
- **THEN** package.json and package-lock.json are copied and dependencies installed before source code copy for better layer caching
|
||||
|
||||
#### Scenario: Final image size
|
||||
- **WHEN** Docker image build completes
|
||||
- **THEN** final image size is under 200MB (excluding data volume)
|
||||
|
||||
### Requirement: Database persistence
|
||||
The deployment SHALL ensure SQLite database persists across container restarts.
|
||||
|
||||
#### Scenario: Volume mounting
|
||||
- **WHEN** container runs with volume mount
|
||||
- **THEN** /app/data directory is mounted from host or Docker volume
|
||||
|
||||
#### Scenario: Database file location
|
||||
- **WHEN** application initializes database
|
||||
- **THEN** SQLite file is created at /app/data/candles.db (inside mounted volume)
|
||||
|
||||
#### Scenario: Container restart preserves data
|
||||
- **WHEN** container is stopped and restarted
|
||||
- **THEN** existing database file is reused and all annotations and candles remain intact
|
||||
|
||||
#### Scenario: File permissions
|
||||
- **WHEN** container creates database file
|
||||
- **THEN** appuser has read/write permissions to /app/data directory
|
||||
|
||||
### Requirement: Deployment documentation
|
||||
DEPLOYMENT.md SHALL include comprehensive Docker deployment instructions.
|
||||
|
||||
#### Scenario: Docker deployment section
|
||||
- **WHEN** DEPLOYMENT.md is read
|
||||
- **THEN** includes dedicated "Docker Deployment" section with prerequisites, build steps, and run commands
|
||||
|
||||
#### Scenario: Quick start commands
|
||||
- **WHEN** following deployment docs
|
||||
- **THEN** provides complete commands: `docker-compose up -d` for production and `docker-compose up --build` for rebuilding
|
||||
|
||||
#### Scenario: Environment setup instructions
|
||||
- **WHEN** following deployment docs
|
||||
- **THEN** explains how to copy .env.example to .env and configure required variables
|
||||
|
||||
#### Scenario: Volume backup instructions
|
||||
- **WHEN** following deployment docs
|
||||
- **THEN** provides commands to backup database: `docker cp candle-annotator:/app/data/candles.db ./backup.db`
|
||||
|
||||
#### Scenario: Troubleshooting section
|
||||
- **WHEN** deployment issues occur
|
||||
- **THEN** DEPLOYMENT.md includes troubleshooting for common Docker issues: port conflicts, permission errors, build failures
|
||||
|
||||
#### Scenario: Update and maintenance
|
||||
- **WHEN** updating deployed application
|
||||
- **THEN** documentation provides steps: pull new code, rebuild image, restart containers with data preservation
|
||||
|
||||
### Requirement: Container security
|
||||
The Docker setup SHALL follow security best practices.
|
||||
|
||||
#### Scenario: Non-root user
|
||||
- **WHEN** container runs
|
||||
- **THEN** application process runs as non-root user 'appuser' (UID 1000)
|
||||
|
||||
#### Scenario: Read-only filesystem where possible
|
||||
- **WHEN** container runs
|
||||
- **THEN** only /app/data directory requires write permissions, all other files are read-only to appuser
|
||||
|
||||
#### Scenario: No sensitive data in image
|
||||
- **WHEN** Docker image is built
|
||||
- **THEN** .env files, secrets, and database files are not included in image layers
|
||||
|
||||
#### Scenario: Minimal attack surface
|
||||
- **WHEN** container runs
|
||||
- **THEN** only port 3000 is exposed, no SSH, no unnecessary services, alpine base reduces package vulnerabilities
|
||||
Loading…
Add table
Add a link
Reference in a new issue