Skip to content

Prune removes containers kamal-proxy has put to sleep (scale-to-zero) #62

Description

@mhenrixon

kamal deploy runs prune on every deploy (lib/kamal/cli/main.rb, kamal:cli:prune:all). Kamal::Commands::Prune#app_containers selects containers to remove with:

docker ps -q -a --filter status=exited --filter label=service=<service> | tail -n +6 | xargs docker rm

A container that kamal-proxy has put to sleep is exited. So once a service accumulates more than five stopped containers — old releases plus the sleeping one — the sleeping container becomes a docker rm candidate.

After it is removed the proxy still holds its reference, so every wake gets a 404 from the daemon. With zoolutions/kamal-proxy#58's backoff that degrades to one failed start attempt per 30s and a service that returns 503 until someone redeploys, rather than a retry storm — but it is still a hard outage, and nothing on the proxy side can prevent it. The proxy's deploy-time preflight only proves the reference resolved at deploy time.

Why this can't be fixed proxy-side

The proxy learns its container reference from the --target string, which under Kamal is the container short id. It has no way to stop the gem removing that container, and no way to distinguish "pruned" from "never existed" after the fact.

Options, roughly in order of preference

  1. Exclude proxy-managed containers from the prune filter. Have the gem skip containers the proxy is responsible for — e.g. by a label the gem already sets when it deploys with an idle timeout configured.
  2. Have the gem pass a stable label selector to the proxy instead of a per-release container id, so the proxy resolves the container at wake time rather than holding a reference that prune can invalidate. This also fixes the redeploy-while-sleeping case for free.
  3. Raise the retention count when idle timeouts are configured. Cheapest, but only widens the window rather than closing it.

Option 2 is the most robust and is worth considering before the proxy side settles, because it changes what the proxy stores.

Release ordering

The proxy half is not merged yet (zoolutions/kamal-proxy#58 is a partial draft). This needs to land in the same release pair as the finished proxy feature — proxy image first, then the gem, per the usual MINIMUM_VERSION ordering.

Refs zoolutions/kamal-proxy#19, zoolutions/kamal-proxy#58

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions