How to Mock a Container Registry in Python
Build an in-memory container registry mock with push, tag listing, and manifest retrieval logic for testing deployment tooling.
Python code
29 linesimport json
from collections import defaultdict
class MockRegistry:
def __init__(self):
self.repositories = defaultdict(dict)
def push_image(self, repo: str, tag: str, layers: list[str]) -> None:
self.repositories[repo][tag] = {
"layers": layers,
"size": sum(len(layer) for layer in layers),
}
def list_tags(self, repo: str) -> list:
return sorted(self.repositories.get(repo, {}).keys())
def manifest(self, repo: str, tag: str) -> dict:
return self.repositories[repo].get(tag, {})
if __name__ == "__main__":
registry = MockRegistry()
registry.push_image("python-app", "v1.0", ["base", "deps", "app"])
registry.push_image("python-app", "v1.1", ["base", "deps", "app", "fixes"])
print("Tags:", registry.list_tags("python-app"))
print("Manifest v1.1:", json.dumps(registry.manifest("python-app", "v1.1"), indent=2))
print("Missing tag:", registry.manifest("python-app", "nope"))
Output
Tags: ['v1.0', 'v1.1']
Manifest v1.1: {
"layers": [
"base",
"deps",
"app",
"fixes"
],
"size": 16
}
Missing tag: {}
How it works
The MockRegistry class uses a defaultdict(dict) so every repository name automatically maps to an empty nested dictionary, avoiding KeyError on first push. push_image stores the tag as a key with a manifest containing layer names and a computed total size, simulating a real registry API. list_tags returns tags sorted for deterministic test assertions, matching how tools like docker tag list versions. manifest returns {} for missing tags, mirroring the 404-style empty response clients expect. The if __name__ == "__main__" guard lets you demo the behavior directly while keeping the class importable for unit tests.
Common mistakes
- Using a plain dict instead of defaultdict, which raises KeyError on first push to a new repo.
- Forgetting to sort tags, causing non-deterministic test output depending on insertion order.
- Returning None for missing manifests instead of an empty dict, breaking downstream code expecting a dict shape.
- Hardcoding layer sizes instead of computing them from actual layer data.
- Using threads without locks — this mock is not thread-safe for concurrent push operations.
Variations
- Use a real container registry API client like `docker` or `harborclient` with a local test registry container.
- Add `delete_image(repo, tag)` and `repo_exists(repo)` methods to expand test coverage of cleanup workflows.
Real-world use cases
- Unit-testing deployment scripts that push images and verify tag listings before triggering a rollout.
- Simulating a registry in CI/CD pipelines to test rollback logic without network access or external dependencies.
- Developing registry clients or debugging image push/pull code when a real registry is unavailable or too slow.
Sponsored
More from Production deployment patterns
- Auto Rollback on Error Rate Exceeded in Python medium
- Automate Semantic Versioning with Conventional Commits in Python medium
- Design a Data Helper for Beginners in Python easy
- Docker healthcheck CMD mock in Python easy
- Generate a Mock Artifact Version Tag in Python easy
- Generate a docker-compose.yml with mock services in Python easy
Keep learning
Related tutorials and quizzes for this topic.