Files
lnet_tutor/exam_system/README.md
2025-10-22 20:14:31 +08:00

4.8 KiB

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

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

  1. Place exam JSON file in data/input/your-exam.json (see /docs/exam-format.md for format)
  2. 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.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=<strong-random-key>
  • ALLOWED_HOSTS=yourdomain.com
  • CORS_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 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

# 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