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.

Easy Python 3.9+ Aug 9, 2026 Production deployment patterns 13 views 0 copies

Python code

40 lines
Python 3.9+
"""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

stdout
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

  1. Use a `deque(maxlen=N)` to cap historical tags and limit memory usage
  2. 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

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from Production deployment patterns

Related tutorials and quizzes for this topic.