{"id":50974886,"url":"https://github.com/eznix86/docker-registry-api-simulator","last_synced_at":"2026-06-19T06:33:03.200Z","repository":{"id":321204934,"uuid":"1084356834","full_name":"eznix86/docker-registry-api-simulator","owner":"eznix86","description":"A Docker Registry API Simulator","archived":false,"fork":false,"pushed_at":"2026-05-13T09:05:35.000Z","size":560,"stargazers_count":2,"open_issues_count":5,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-13T11:10:25.161Z","etag":null,"topics":["bun","distribution","docker","simulator"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/eznix86.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-10-27T15:15:08.000Z","updated_at":"2026-01-04T18:35:21.000Z","dependencies_parsed_at":null,"dependency_job_id":"2776ff52-4f89-4ff0-82bf-29e44508c9de","html_url":"https://github.com/eznix86/docker-registry-api-simulator","commit_stats":null,"previous_names":["eznix86/docker-registry-api-simulator"],"tags_count":11,"template":false,"template_full_name":null,"purl":"pkg:github/eznix86/docker-registry-api-simulator","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eznix86%2Fdocker-registry-api-simulator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eznix86%2Fdocker-registry-api-simulator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eznix86%2Fdocker-registry-api-simulator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eznix86%2Fdocker-registry-api-simulator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/eznix86","download_url":"https://codeload.github.com/eznix86/docker-registry-api-simulator/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eznix86%2Fdocker-registry-api-simulator/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34520431,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-19T02:00:06.005Z","response_time":61,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bun","distribution","docker","simulator"],"created_at":"2026-06-19T06:33:02.484Z","updated_at":"2026-06-19T06:33:03.194Z","avatar_url":"https://github.com/eznix86.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Docker Registry API v2 Simulator\n\nA Docker Registry HTTP API v2 simulator built with Bun, ElysiaJS, and lowdb. Implements the read-only subset of the Docker Registry spec for testing and development.\n\n![Demo](./docs/images/doc-image.png)\n\n## What it does ?\n\n- Docker Registry API v2 spec-compliant\n- Multi-configuration support via environment variable\n- Repository catalog with pagination (RFC5988 Link headers)\n- Tag listing with pagination\n- Manifest retrieval:\n  - Single-arch: OCI + Docker v2 manifests\n  - Multi-arch: OCI image index + Docker manifest list\n- ETag and If-None-Match support (304 responses)\n- Blob retrieval (config blobs only)\n- Basic authentication support\n- Swagger UI documentation\n- Test simulation using Hurl\n\n## Prerequisites\n\n- [Bun](https://bun.sh) v1.0+\n- [Hurl](https://hurl.dev) (for tests)\n- Docker/Podman (optional)\n\n## Quick start\n\n```sh\nnpx docker-api-simulator@latest --help\n\n# By default it looks in data/db.json\nnpx docker-api-simulator@latest serve -f data/db-full.json\n\n# Generate database based on a template\nnpx docker-api-simulator@latest generate templates/[name].[yaml|jsonc]\n\n# Validate database\nnpx docker-api-simulator@latest validate db.json\n\n# Global install\nnpm install -g docker-api-simulator@latest\n# You will get `registry-api-simulator`\n```\n\n## Installation on local\n\n```bash\nbun install\n```\n\n## Build\n\nBuild the JavaScript bundle (for npm/bunx distribution):\n\n```bash\nbun run build\n```\n\nThis creates a minified executable JavaScript file at `dist/index.js` that requires Bun to run.\n\n## Docker\n\nThe Containerfile uses a multi-stage build to create an optimized ~100MB image.\n\nBuild and run with Docker Compose:\n\n```bash\ndocker compose up -d\n```\n\nThree instances will start with 250ms simulated network throttle:\n- registry-full (port 5001) - 4 repositories (data/db-full.json)\n- registry-minimal (port 5002) - 1 repository (data/db-minimal.json)\n- registry-custom (port 5003) - 50 repositories (data/db-big.json)\n\nOr build a single image:\n\n```bash\ndocker build -f Containerfile -t registry-simulator .\ndocker run -p 5001:5001 -v ./data/db.json:/data/db.json:ro registry-simulator\n```\n\n## Usage\n\nThe simulator provides four commands:\n\n### Start the server\n\n```bash\nbun run serve                                    # uses data/db.json on port 5001\nbun run serve -f data/db-full.json               # use specific database\nbun run serve -p 3000                            # use custom port\nbun run serve -t 250                             # add 250ms to response delay\nbun run serve -f data/db-custom.json -p 3000 -t  # throttle with default 250ms\n```\n\nServer runs on http://localhost:5001 by default.\n\nEndpoints:\n- Health: http://localhost:5001/v2/\n- Swagger: http://localhost:5001/swagger\n\nOptions:\n- `-f, --db-file \u003cpath\u003e` - Path to the database JSON file (default: \"data/db.json\")\n- `-p, --port \u003cnumber\u003e` - Port to listen on (default: \"5001\")\n- `-t, --throttle [ms]` - Add response delay (default: 250ms if flag used without value)\n\n### Generate a database from template\n\n```bash\nbun run generate templates/example.yaml             # generates from YAML template\nbun run generate templates/example.jsonc            # or from JSONC template\nbun run generate templates/example.jsonc -o data/custom.json  # custom output path\n```\n\nThe generated database will be saved in the `data/` directory with a unique UUID filename, or at the specified output path.\n\nOptions:\n- `-o, --output \u003cfile\u003e` - Output database file path (default: data/[uuid].json)\n\n### Generate a template file\n\n```bash\nbun run generate-template                      # generates 100 repos, 1001 tags\nbun run generate-template -r 50 -t 200         # custom counts\nbun run generate-template -a                   # include authentication\nbun run generate-template -o templates/my.jsonc  # custom output path\n```\n\nOptions:\n- `-r, --repos \u003cnumber\u003e` - Number of repositories (default: \"100\")\n- `-t, --tags \u003cnumber\u003e` - Total number of tags (default: \"1001\")\n- `-o, --output \u003cpath\u003e` - Output file path (default: templates/[uuid].jsonc)\n- `-a, --auth` - Include authentication credentials\n\n### Validate a database file\n\n```bash\nbun run validate data/db.json              # validate database structure\nbun run validate data/db-custom.json       # validate any database file\n```\n\n### Run tests\n\n```bash\nhurl --test tests/*.hurl\n```\n\n## API Endpoints\n\n```\nGET  /v2/                          # Health check\nGET  /v2/_catalog                  # List repositories (supports ?n=10\u0026last=alpine)\nGET  /v2/:name/tags/list           # List tags (supports ?n=5\u0026last=v1.0)\nGET  /v2/:name/manifests/:ref      # Get manifest (supports Accept header, If-None-Match)\nHEAD /v2/:name/manifests/:ref      # Manifest headers\nGET  /v2/:name/blobs/:digest       # Get blob (config only)\nHEAD /v2/:name/blobs/:digest       # Blob headers\n```\n\n## Configuration\n\nThe simulator uses JSON files for data stored in the `data/` directory. Use the `-f` flag to specify which database to use.\n\nAvailable datasets:\n- `data/db.json` - 4 repositories (alpine, nginx, redis, postgres) with auth enabled (default)\n- `data/db-minimal.json` - 1 repository (alpine) with auth disabled\n- `data/db-full.json` - Full example with multiple repositories\n- `data/db-custom.json` - Examples of:\n  - Untagged repository (`untagged-repo`)\n  - Single-arch manifest (`single-arch`)\n  - Multi-arch manifest (`multi-arch` with amd64 and arm64)\n  - Auth disabled\n\nCreate custom datasets by:\n1. Using the `generate` command with a YAML/JSONC template\n2. Copying and modifying existing database files\n\n### Authentication\n\nBasic authentication is supported. Add users to the `auth` array in your JSON configuration:\n\n```json\n{\n\t\"auth\": [\n\t\t{ \"username\": \"admin\", \"password\": \"admin123\" },\n\t\t{ \"username\": \"user\", \"password\": \"user123\" }\n\t]\n}\n```\n\nIf `auth` is an empty array `[]`, authentication is disabled. The `/v2/` health endpoint is always accessible without authentication.\n\n## Examples\n\n```bash\n# Health check (no auth required)\ncurl http://localhost:5001/v2/\n\n# List repositories (with auth)\ncurl -u admin:admin123 http://localhost:5001/v2/_catalog\n\n# List tags (with auth)\ncurl -u admin:admin123 http://localhost:5001/v2/alpine/tags/list\n\n# Get manifest with auth (Docker v2)\ncurl -u admin:admin123 \\\n  -H \"Accept: application/vnd.docker.distribution.manifest.v2+json\" \\\n  http://localhost:5001/v2/alpine/manifests/latest\n\n# Get manifest with auth (OCI)\ncurl -u admin:admin123 \\\n  -H \"Accept: application/vnd.oci.image.manifest.v1+json\" \\\n  http://localhost:5001/v2/alpine/manifests/latest\n\n# Test ETag with auth (returns 304)\nETAG=$(curl -u admin:admin123 -sI http://localhost:5001/v2/alpine/manifests/latest | grep -i etag | cut -d' ' -f2)\ncurl -u admin:admin123 -H \"If-None-Match: $ETAG\" http://localhost:5001/v2/alpine/manifests/latest\n\n# Without auth (returns 401 if auth is enabled)\ncurl http://localhost:5001/v2/_catalog\n\n# Multi-arch manifest list (Docker)\ncurl -H \"Accept: application/vnd.docker.distribution.manifest.list.v2+json\" \\\n  http://localhost:5001/v2/multi-arch/manifests/latest\n\n# Multi-arch OCI index\ncurl -H \"Accept: application/vnd.oci.image.index.v1+json\" \\\n  http://localhost:5001/v2/multi-arch/manifests/latest\n```\n\n## Tech Stack\n\n- Bun - JavaScript runtime\n- ElysiaJS - Web framework\n- lowdb - JSON database\n- Hurl - HTTP testing\n\n## License\n\nMIT - See [LICENSE](LICENSE) file for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feznix86%2Fdocker-registry-api-simulator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Feznix86%2Fdocker-registry-api-simulator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feznix86%2Fdocker-registry-api-simulator/lists"}