Overcast is alpha — behaviour and APIs may change between releases. Pin your version and read the changelog before upgrading.

overcast

ECR limitations

How a repository URI is derived and why it says localhost, what survives a restart, and how the image inventory tracks the registry rather than accumulating.

How a repository URI is derived, what survives a restart, and what the image inventory tracks, behind ECR.

The repository URI

localhost:<registryPort>/<accountId>/<repositoryName>
QuestionAnswer
Which port?The registry container’s, not the API port — the URI is what a docker push targets
Where else does the same address appear?proxyEndpoint from GetAuthorizationToken, and Fn::GetAtt Repo.RepositoryUri — never an amazonaws.com one
Stored or derived?Re-minted on every read. Repositories persist and the registry does not
Read while the registry is down?The fallback address, and the registry again once there is one
Why localhost?docker push, pull and login are performed by the Docker daemon, and a daemon trusts plain HTTP to localhost without configuration
Why not OVERCAST_HOSTNAME?A hostname such as localhost.overcast.sh goes through any proxy the daemon has configured (proxyconnect tcp: dial tcp 192.168.65.1:3128: i/o timeout)
Remote daemon, which cannot reach localhost?OVERCAST_HOSTNAME stands instead, and that address is the one to add to the daemon’s insecure-registries

The startup reachability probe

Startup has the daemon itself contact the registry, through the Engine’s distribution-inspect endpoint, and warns once when it cannot rather than letting every later push and pull fail on its own. The probe carries this instance’s credentials, which is what tells this registry from a sibling’s — see A port answering as another instance’s registry.

When the fixed port is taken

If something else holds OVERCAST_ECR_REGISTRY_PORT (default 4510), the registry falls back to an ephemeral port and says so in the log. The daemon may then not reach it at all. Measured on Docker Desktop 29.6.2 for Windows, against the same registry image:

Publishdocker login
Fixed — localhost:5099Succeeds
Ephemeral — localhost:62154Times out

docker port reports both bindings as dual-stack. Overcast says so at startup (“the Docker daemon cannot reach the ECR registry it just published”). Free the fixed port, or point the variable at another fixed one, rather than working around the pull failures downstream.

Persistence

ThingBacked bySurvives a restart
Images pushed to the fixed portThe named volume overcast-ecr-registry-data-<port> on /var/lib/registry, labelled overcast.service=ecrYes
Images pushed to the ephemeral fallbackThe container’s own volume — its name is random and its port is whatever the daemon had spareNo
The registry containerNothing. It runs with AutoRemove, which reclaims only the anonymous volume it would otherwise have been givenNo
Repository metadataThe state backend, not the volumeOnly if OVERCAST_STATE does

OVERCAST_ECR_REGISTRY_PERSIST=false gives the fixed port the ephemeral behaviour too.

A run on OVERCAST_STATE=memory comes back with no repositories even though the images are still there. Re-creating the repository is enough for them to reappear: the first read reconciles it against the registry.

Keeping the volume is what stops cdk deploy re-uploading — cdk-assets asks DescribeImages for a container asset’s content-hash tag and skips both the build and the push when it resolves.

Asking whether an image is published

DescribeImages callAnswer
An imageIds entry that resolvesThe image
An imageIds entry it cannot resolveImageNotFoundException, as real ECR answers — not a 200 carrying a short list
No imageIds at allAn empty list

That decides whether anything is ever pushed: cdk-assets treats any non-throwing DescribeImages as “already published” and skips building and pushing the asset, so a 200 for an absent tag leaves an empty repository behind a clean deploy and a 404 at pull time.

The image inventory follows the registry rather than accumulating. On every repository read:

RecordWhat happens
A manifest the registry servesRecorded
A record the registry 404sDropped
A record written by PutImageLeft alone

So a restart that keeps the registry’s storage but loses the in-memory records rediscovers them, and one that keeps the records but loses the storage drops them.