json-server is a fantastic tool — get a full fake REST API with zero coding in less than 30 seconds.
The go-to Docker image has long been clue/json-server on Docker Hub, but it has some issues:
- 259 MB in size (Debian-based full Node image)
- 8 years stale — stuck on json-server v0.x from 2018
- No built-in healthcheck
- No
docker-composeexample
Time for a refresh.
The Alpine rebuild
By switching the base image from Debian to node:22-alpine, we get a much leaner result:
| Image | Size | Reduction |
|---|---|---|
clue/json-server (original) |
259 MB | — |
| this image (Alpine) | 174 MB | –85 MB (33%) |
The overhead beyond bare node:22-alpine (163 MB) is only 11 MB for the json-server package and its runtime dependencies. The Dockerfile is minimal:
FROM node:22-alpine
RUN npm install -g json-server@latest --production
RUN mkdir -p /data
WORKDIR /data
RUN echo '{"placeholder": [{"id": "1", "message": "Mount your own /data/db.json"}]}' > /data/db.json
EXPOSE 3000
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD wget --no-verbose --tries=1 --spider http://localhost:3000/ || exit 1
ENTRYPOINT ["json-server"]
CMD ["db.json", "--host", "0.0.0.0", "--port", "3000"]
Quick start
docker build -t json-server:alpine .
docker run -d -p 3000:3000 json-server:alpine
Or with your own data file:
docker run -d -p 3000:3000 \
-v /path/to/your/db.json:/data/db.json \
json-server:alpine
Docker Compose
services:
json-server:
build: .
ports:
- "3000:3000"
volumes:
- ./data/db.json:/data/db.json
restart: unless-stopped
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3000/"]
interval: 30s
timeout: 3s
retries: 3
start_period: 5s
Generating realistic test data
A reusable seed script generates random data across 4 collections:
node data/generate-data.js > data/db.json
docker compose up -d --build
This populates 4 REST endpoints:
| Endpoint | Description |
|---|---|
GET /articles |
15 articles with title, author, views, tags, status |
GET /comments |
30 comments tied to articles via postId |
GET /users |
10 users with name, email, department, role |
GET /products |
8 products with price, rating, stock status |
All CRUD operations work out of the box:
curl http://localhost:3000/articles/1
curl -X POST -H 'Content-Type: application/json' \
-d '{"title":"New Post","body":"Hello"}' \
http://localhost:3000/articles
curl http://localhost:3000/users?_sort=-points
curl "http://localhost:3000/articles?_page=1&_per_page=5"
curl http://localhost:3000/articles?_embed=comments
What’s in the seed script
The generate-data.js script creates realistic data using randomly sampled names, cities, categories, and tags:
const articles = [
{
id: "1",
title: "Education Insights 2026",
author: "Jack Rodriguez",
views: 9366,
status: "active",
tags: ["javascript", "react", "node"]
},
// ... 15 articles total
];
Key improvements over the upstream image
- Smaller — Alpine Linux saves 85 MB vs Debian
- Up-to-date — runs json-server v1.x (the latest) with all the new query features
- Healthcheck — Docker
HEALTHCHECKmonitors the server every 30s - Compose-ready — pre-configured
compose.yamlfor easy lifecycle management - Seed script — generates realistic test data with proper relations
Query capabilities (json-server v1.x)
The newer json-server includes advanced querying:
| Feature | Example |
|---|---|
| Filter conditions | GET /posts?views:gt=100 |
| Sort | GET /posts?_sort=-views |
| Pagination | GET /posts?_page=1&_per_page=25 |
| Embed relations | GET /posts?_embed=comments |
| Complex queries | GET /posts?_where={"or":[...]} |
Links
- GitHub repo with Dockerfile, seed script, and compose
- json-server on GitHub
- clue/json-server on Docker Hub