A REST API built with Node.js + Express + TypeScript, containerised with Docker, and deployable on AWS EC2 via ECR.
This app demonstrates CPU-intensive image processing using Sharp — resizing, blurring, and sharpening images up to 8K resolution — to sustain >80% CPU load.
- REST API with endpoints for auth, jobs, and images.
- JWT Authentication (two hardcoded users:
alice+bob). - CPU-intensive image pipeline using Sharp (resize + blur + sharpen).
- Two data types:
- Unstructured → images (
.png) - Structured → job metadata (UUIDs in memory)
- Unstructured → images (
- Containerised with Docker and ready for AWS deployment.
- Includes a load test script to drive CPU >80%.
npm installnpx ts-node scripts/generate_seed.tsexport JWT_SECRET=changeme
npm run devAPI will be available at: http://localhost:3000
Login with hardcoded credentials:
curl -X POST http://localhost:3000/v1/auth/login -H "Content-Type: application/json" -d '{"username":"alice","password":"password1"}'Response:
{ "token": "<JWT_TOKEN>" }Use this token in all Authorization headers:
Authorization: Bearer <JWT_TOKEN>
Submit a CPU-heavy image job:
curl -X POST http://localhost:3000/v1/jobs -H "Authorization: Bearer <JWT_TOKEN>" -H "Content-Type: application/json" -d '{
"sourceId":"seed",
"ops":[
{"op":"resize","width":7680,"height":4320},
{"op":"blur","sigma":10},
{"op":"sharpen","sigma":2},
{"op":"resize","width":7680,"height":4320}
]
}'Response:
{
"id": "ea93a2fb-1984-42d9-a924-ff35f2955284",
"output": {
"imageId": "ea93a2fb-1984-42d9-a924-ff35f2955284",
"url": "/v1/images/ea93a2fb-1984-42d9-a924-ff35f2955284"
}
}View the result:
http://localhost:3000/v1/images/ea93a2fb-1984-42d9-a924-ff35f2955284
Hammer the API to prove >80% CPU:
export JWT=<YOUR_TOKEN>
npm run load:testOptional parameters:
C=12 D=300 npm run load:test # 12 workers for 5 minutesWatch CPU usage with Activity Monitor (Mac) or top.
docker buildx build --platform linux/amd64 -t imgproc-api:0.1.0 .docker run --rm --platform linux/amd64 -p 3000:3000 -e JWT_SECRET=$(openssl rand -hex 16) imgproc-api:0.1.0-
Build & tag the image.
-
Push to AWS ECR:
aws ecr create-repository --repository-name imgproc-api aws ecr get-login-password --region ap-southeast-2 | docker login --username AWS --password-stdin <ACCOUNT_ID>.dkr.ecr.ap-southeast-2.amazonaws.com docker tag imgproc-api:0.1.0 <ACCOUNT_ID>.dkr.ecr.ap-southeast-2.amazonaws.com/imgproc-api:0.1.0 docker push <ACCOUNT_ID>.dkr.ecr.ap-southeast-2.amazonaws.com/imgproc-api:0.1.0
-
On EC2 (Ubuntu 24.04), install Docker, then:
sudo docker pull <ACCOUNT_ID>.dkr.ecr.ap-southeast-2.amazonaws.com/imgproc-api:0.1.0 sudo docker run -d -p 80:3000 -e JWT_SECRET=$(openssl rand -hex 16) imgproc-api:0.1.0
-
Test via EC2 public DNS:
http://<ec2-public-dns>/v1/auth/login
src/
├── routes/ # Express routes (auth, jobs, images)
├── middleware/ # JWT auth, error handler
├── services/ # Sharp image pipeline
├── app.ts # App setup
└── server.ts # Entrypoint
scripts/
├── generate_seed.ts # Writes seed.png to originals/
└── load_test.ts # Load generator
storage/
├── originals/ # Input images (seed.png)
└── outputs/ # Job results
Dockerfile
.dockerignore
README.md
alice/password1bob/password2
For educational use (CAB432 assignment).