DocsAWS 101Blog
← Back to Blog

docker push, CloudFormation Custom Resources, Cognito nonce

May 11, 2026 · v1.3.34

Two new capabilities and one OIDC correctness fix.

ECR speaks Docker Registry V2

Real AWS ECR exposes the Docker Registry HTTP API V2 protocol on the same endpoint as the AWS API. MiniStack now does the same. docker push and docker pull against the gateway work end-to-end: GET /v2/ ping, /v2/_catalog, chunked and single-shot blob uploads, cross-repo blob mounts, blob HEAD/GET/DELETE, manifest PUT/GET/HEAD/DELETE by tag or digest, and /tags/list.

aws --endpoint-url=http://localhost:4566 ecr create-repository \
  --repository-name my-app

docker tag my-app:local localhost:4566/my-app:v1
docker push localhost:4566/my-app:v1

aws --endpoint-url=http://localhost:4566 ecr describe-images \
  --repository-name my-app
# Pushed image visible immediately

Pushed layers and manifests persist across warm-boot when PERSIST_STATE=1 is set. In-flight upload sessions are intentionally ephemeral; clients retry on 404 the way they would against any real registry.

The routing fix that ships with this is worth a note: /v2/<repo>/... paths used to fall through to S3 path-style addressing and return 405 Method Not Allowed to the Docker daemon. The new pre-empt detects registry shapes (/blobs/, /manifests/, /tags/list) and routes only those to ECR, so API Gateway v2, AppSync Events, and SES v2 keep working untouched. Reported by @LeTrungNguyen1703.

CloudFormation Custom Resources

Both Custom::* and AWS::CloudFormation::CustomResource now run the full Create / Update / Delete lifecycle. MiniStack mints a local intercept URL (/_ministack/cfn-response/{token}) in place of a pre-signed S3 ResponseURL, and the provisioner runs in asyncio.to_thread so the event loop stays free for the Lambda's PUT callback — required for CDK cr.Provider-backed Lambdas that invoke themselves through the same process.

Resources:
  Handler:
    Type: AWS::Lambda::Function
    Properties:
      FunctionName: my-handler
      # ... handler that does PUT to event.ResponseURL with
      # { Status: "SUCCESS", PhysicalResourceId, Data: {...} }
  Custom:
    Type: Custom::MyResource
    Properties:
      ServiceToken: !GetAtt Handler.Arn
      Foo: bar

Update forwards OldResourceProperties; Delete carries the PhysicalResourceId established during Create; if the Lambda omits PhysicalResourceId on a Create response, RequestId is used as the fallback (matching real CloudFormation). ServiceToken accepts bare function names or full Lambda ARNs (qualifier suffix stripped). A Status: FAILED response triggers stack rollback. Contributed by @hiddengearz.

Cognito OAuth2 nonce in id_token

The authorize endpoint already stored the client-supplied nonce on the auth code, but /oauth2/token never threaded it into the minted id_token. OIDC Core 1.0 §3.1.3.7 requires the echo, and strict OIDC libraries (oidc-client-ts, react-oidc-context, Auth0 / Microsoft client SDKs) silently discard tokens that omit an expected nonce. The id_token now carries the nonce claim when one was sent. Access and refresh tokens are unchanged. Contributed by @coezbek.

Upgrade

docker pull ministackorg/ministack:1.3.34
docker run -d -p 4566:4566 ministackorg/ministack:1.3.34

Or pin in compose.yaml:

services:
  ministack:
    image: ministackorg/ministack:1.3.34
    ports:
      - "4566:4566"

Ship together

Shipped by the MiniStack community. Contributions credited throughout. GitHub · r/ministack