How to Roll Back to a Previous Image Tag in Python
A dataclass-based mock registry that tracks image tag history and rolls back to the previous tag, useful for deployment rollback logic.
Python code
40 lines"""Demonstrates a rollback pattern for a Docker-style image tag registry."""
from dataclasses import dataclass, field
@dataclass
class ImageRegistry:
"""A minimal mock registry tracking current tags per image."""
tags: dict[str, list[str]] = field(default_factory=dict)
def push(self, image: str, tag: str) -> None:
"""Add a tag to the image's history."""
self.tags.setdefault(image, []).append(tag)
def rollback(self, image: str) -> str | None:
"""Roll back to the previous tag (removes current, returns new current)."""
history = self.tags.get(image, [])
if len(history) <= 1:
return None
history.pop()
return history[-1]
def current(self, image: str) -> str | None:
"""Return the latest tag for an image, if any."""
return self.tags.get(image, [None])[-1]
if __name__ == "__main__":
registry = ImageRegistry()
registry.push("web/api", "v1.0.0")
registry.push("web/api", "v1.0.1")
registry.push("web/api", "v1.0.2")
print("Current before rollback:", registry.current("web/api"))
print("New current after rollback:", registry.rollback("web/api"))
print("Rollback result:", registry.rollback("web/api"))
print("Current after second rollback:", registry.current("web/api"))
print("Rollback on single tag returns:", registry.rollback("web/api"))
print("Current at end:", registry.current("web/api"))
Output
Current before rollback: v1.0.2
New current after rollback: v1.0.1
Rollback result: v1.0.0
Current after second rollback: v1.0.0
Rollback on single tag returns: None
Current at end: v1.0.0
How it works
The ImageRegistry dataclass stores each image's tag history as a list, using push to append the latest tag. rollback pops the current tag (if more than one exists) and returns the new latest, effectively reverting deployments. The current method simply returns the last item in the history, or None if empty. This pattern mimics a stack (LIFO) for tag management, preserving full history while supporting reversible updates. The string type hints (str | None) require Python 3.10+ for the union syntax, so use 3.10+ in modern environments.
Common mistakes
- Returning the popped tag instead of the new current tag after rollback
- Not handling the case where an image has only one tag, causing an IndexError
- Forgetting that `dict.setdefault` only initializes the key once, so history is preserved across pushes
- Assuming `rollback` restores a deleted tag; it only removes the latest, not an arbitrary one
Variations
- Use a `deque(maxlen=N)` to cap historical tags and limit memory usage
- Implement `rollback_to(tag)` to revert to a specific historical tag rather than just the previous one
Real-world use cases
- Automated deployment pipelines that revert a service to the previous image when health checks fail.
- A CI/CD control plane that maintains per-environment tag history for instant disaster recovery.
- A release management dashboard that lets operators undo a bad rollout in one click.
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.