Introduction
When working with microservice architecture based on Podman, you often need to dynamically manage auxiliary containers within a pod. One of the most common scenarios involves SSH tunnels to remote services: databases, APIs, and monitoring systems. In this article, I'll describe the "ephemeral sidecar container" pattern and its Python implementation.
Pod Architecture
Our Podman pod consists of three main components: Valkey (a Redis fork) for the task queue, an RQ worker for processing tasks, and an ephemeral SSH tunnel that starts on demand. All containers share a pod, which means a shared network namespace — a tunnel opened in the sidecar container is accessible to the worker via localhost.
# Create pod with forwarded ports
podman pod create --name jira-stack
-p 6379:6379
-p 8080:8080
# Start Valkey in the pod
podman run -d --pod jira-stack
–name valkey
docker.io/valkey/valkey:8
# Start the worker
podman run -d --pod jira-stack
–name worker
localhost/jira-worker:latest
Python Context Manager for Container Lifecycle
The key element of this pattern is a Python context manager that handles starting and stopping the sidecar container. This guarantees proper resource cleanup even when errors occur.
import subprocess
import logging
logger = logging.getLogger(name)
class EphemeralContainer:
def init(self, name, pod_name):
self.name = name
self.pod_name = pod_name
def enter(self):
logger.info(f"Starting container {self.name}")
subprocess.run(
[“podman”, “start”, self.name],
check=True,
capture_output=True
)
self._wait_healthy()
return self
def exit(self, *args):
logger.info(f"Stopping container {self.name}“)
subprocess.run(
[“podman”, “stop”, ”-t", “5”, self.name],
capture_output=True
)
def _wait_healthy(self):
for _ in range(30):
result = subprocess.run(
[“podman”, “healthcheck”, “run”, self.name],
capture_output=True
)
if result.returncode == 0:
return
time.sleep(1)
raise TimeoutError(“Container health check failed”)
Usage in RQ Tasks
Now we can use the context manager when processing tasks. The worker starts the SSH tunnel before executing a task and guarantees its shutdown after completion:
def process_jira_task(issue_key):
with EphemeralContainer(“ssh-tunnel”, “jira-stack”):
# Tunnel is active, connect to Jira via localhost
jira = JIRA(server=“http://localhost:8080”, …)
issue = jira.issue(issue_key)
# Process the issue
process_issue(issue)
# Tunnel is automatically stopped
Containerfile for the SSH Tunnel
The tunnel container includes an SSH client and a connection script with automatic reconnection:
FROM docker.io/library/alpine:3.19
RUN apk add --no-cache openssh-client
COPY tunnel.sh /tunnel.sh
RUN chmod +x /tunnel.sh
HEALTHCHECK --interval=5s --timeout=3s
CMD nc -z localhost 8080 || exit 1
ENTRYPOINT [“/tunnel.sh”]
Health Checks and Monitoring
It’s critical to configure health checks for sidecar containers. Podman supports built-in healthcheck directives in Containerfiles. Our context manager waits for the health check to pass before continuing — this prevents situations where the worker tries to use a connection that hasn’t been established yet.
Error Handling and Worker Restart
When a worker restarts, all ephemeral containers must be properly stopped. We add a signal handler and a startup cleanup procedure that stops any leftover sidecar containers from the previous session. The context manager’s exit method ensures cleanup on both normal completion and exceptions.
Conclusion
The ephemeral sidecar pattern lets you save resources by starting auxiliary services only when needed. Python’s context manager ensures reliable lifecycle management, and Podman pods provide a shared network namespace for container communication. This approach is especially effective for SSH tunnels, database connections, and other resource-intensive connections.