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
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
docker-compose down
Development
Backend (exam_server)
# 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)
# Shell access
docker-compose exec exam_web sh
# Install new dependencies
docker-compose exec exam_web npm install <package>
View Logs
# 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
- Place exam JSON file in
data/input/your-exam.json(see/docs/exam-format.mdfor format) - Update
data/manifest.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.jsonusersobject - Delete corresponding files in
data/attempts/{userId}/anddata/output/
Production
Environment Variables
Copy exam_server/env.example to exam_server/.env and update:
DEBUG=FalseSECRET_KEY=<strong-random-key>ALLOWED_HOSTS=yourdomain.comCORS_ALLOWED_ORIGINS=https://yourdomain.com
Production Build
For production, modify exam_web/Dockerfile to use production build:
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
# 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 overviewdjango-backend-spec.md- Backend API endpointsangular-frontend-spec.md- Frontend routes and behaviorjson-io-and-state.md- State machine and file structuredeploy-minimal.md- Deployment guide
Workflow
- Create exam JSON → place in
data/input/ - Publish exam → update
manifest.json - User starts exam → creates attempt in
data/attempts/ - Autosave progress → updates attempt JSON
- Submit exam → writes bundle to
data/output/
Troubleshooting
Port 80 already in use
# Edit docker-compose.yml
# Change "80:80" to "8080:80" under nginx ports
# Then access via http://localhost:8080
Permission errors
# Fix data folder permissions
chmod -R 755 data/
Container won't start
# Check logs
docker-compose logs exam_server
# Rebuild from scratch
docker-compose down -v
docker-compose up --build
Can't access from browser
# Verify all containers running
docker-compose ps
# Should show 3 services: exam_server, exam_web, nginx
License
MIT