Caddy keeps managed certificates, account keys, and OCSP staples in its data directory, which resolves to $XDG_DATA_HOME/caddy or ~/.local/share/caddy on Linux and is /data in the official container image. Nothing else persists that state.
Running the container without mounting a volume at /data means every restart starts with an empty store and requests new certificates. Let's Encrypt enforces a rate limit of certificates per registered domain per week, so a crash loop or a frequently redeployed service exhausts it and then fails to obtain any certificate at all until the window rolls forward.
Mount a persistent volume at /data, and mount /config as well so the autosaved JSON configuration survives. During development, point acme_ca at the Let's Encrypt staging endpoint in the global options block so failed experiments do not consume the production limit; staging certificates are untrusted by browsers, which is the intended signal. Caddy's default issuer order tries ZeroSSL and Let's Encrypt, so a rate limit at one may be masked by success at the other, making the underlying problem intermittent.