# Exam System (Single Docker Environment) ## Overview A minimal exam system using Django + Angular + Nginx in a unified Docker environment. Reads exam JSON files, renders online exams, autosaves progress, and outputs bundled results. ## Architecture - **exam_server**: Django REST API (port 8000 internal) - **exam_web**: Angular SPA (port 4200 internal) - **nginx**: Reverse proxy (port 80 external) - `/` → exam_web - `/api/` → exam_server ## Folder Structure ``` exam_system/ ├── exam_server/ # Django REST API │ ├── Dockerfile │ ├── requirements.txt │ └── env.example ├── exam_web/ # Angular SPA │ ├── Dockerfile │ └── package.json ├── data/ # File-based storage │ ├── input/ # Source exam JSON files │ ├── attempts/ # In-progress attempts │ ├── output/ # Final bundled results │ ├── progress/ # User progress snapshots │ └── manifest.json # Exam registry ├── nginx.conf # Nginx reverse proxy config ├── Dockerfile.nginx # Nginx container ├── docker-compose.yml # Orchestration └── README.md ``` ## Quick Start ### Prerequisites - Docker 20.10+ - Docker Compose 2.0+ ### 1. Build and Start ```bash cd exam_system docker-compose up --build ``` This starts all three services in one environment: - Nginx listening on http://localhost - Django backend (internal) - Angular frontend (internal) ### 2. Access - **Main app**: http://localhost (via Nginx) - Access logs: `docker-compose logs -f` ### 3. Stop ```bash docker-compose down ``` ## Development ### Backend (exam_server) ```bash # Shell access docker-compose exec exam_server bash # Run migrations (when Django app is initialized) docker-compose exec exam_server python manage.py migrate # Create superuser docker-compose exec exam_server python manage.py createsuperuser ``` ### Frontend (exam_web) ```bash # Shell access docker-compose exec exam_web sh # Install new dependencies docker-compose exec exam_web npm install ``` ### View Logs ```bash # All services docker-compose logs -f # Specific service docker-compose logs -f exam_server docker-compose logs -f exam_web docker-compose logs -f nginx ``` ## Data Management ### Add an Exam 1. Place exam JSON file in `data/input/your-exam.json` (see `/docs/exam-format.md` for format) 2. Update `data/manifest.json`: ```json { "exams": [ { "examId": "your-exam", "path": "input/your-exam.json", "published": true, "version": "1.0.0" } ], "users": {} } ``` ### View Results - Output bundles written to `data/output/{examId}_{attemptId}.json` - Contains `{ exam, attempt }` with all answers ### Reset User Progress - Remove user from `manifest.json` `users` object - Delete corresponding files in `data/attempts/{userId}/` and `data/output/` ## Production ### Environment Variables Copy `exam_server/env.example` to `exam_server/.env` and update: - `DEBUG=False` - `SECRET_KEY=` - `ALLOWED_HOSTS=yourdomain.com` - `CORS_ALLOWED_ORIGINS=https://yourdomain.com` ### Production Build For production, modify `exam_web/Dockerfile` to use production build: ```dockerfile FROM node:18-alpine AS builder WORKDIR /app COPY package*.json ./ RUN npm ci COPY . . RUN npm run build --prod FROM nginx:alpine COPY --from=builder /app/dist/exam-web /usr/share/nginx/html EXPOSE 80 CMD ["nginx", "-g", "daemon off;"] ``` ### Backup ```bash # Backup data folder tar -czf backup-$(date +%Y%m%d).tar.gz data/ ``` ## Documentation See `/docs` folder for detailed specifications: - `exam-format.md` - Exam JSON format (5 question types) - `stack-architecture.md` - System architecture overview - `django-backend-spec.md` - Backend API endpoints - `angular-frontend-spec.md` - Frontend routes and behavior - `json-io-and-state.md` - State machine and file structure - `deploy-minimal.md` - Deployment guide ## Workflow 1. Create exam JSON → place in `data/input/` 2. Publish exam → update `manifest.json` 3. User starts exam → creates attempt in `data/attempts/` 4. Autosave progress → updates attempt JSON 5. Submit exam → writes bundle to `data/output/` ## Troubleshooting ### Port 80 already in use ```bash # Edit docker-compose.yml # Change "80:80" to "8080:80" under nginx ports # Then access via http://localhost:8080 ``` ### Permission errors ```bash # Fix data folder permissions chmod -R 755 data/ ``` ### Container won't start ```bash # Check logs docker-compose logs exam_server # Rebuild from scratch docker-compose down -v docker-compose up --build ``` ### Can't access from browser ```bash # Verify all containers running docker-compose ps # Should show 3 services: exam_server, exam_web, nginx ``` ## License MIT