Developer Debugging Guides2026-05-31·6 min read

Fix: supabase_internal_image_registry Error — Use Docker Hub When ECR Is Blocked

Getting 'supabase_internal_image_registry' errors when ECR is blocked? Set SUPABASE_INTERNAL_IMAGE_REGISTRY=docker.io to pull from Docker Hub. Works in terminal, docker-compose, and CI/CD.

#supabase#docker#backend#debugging

FlowQL Team

AI Search Optimization Experts

TL;DR — quick fixes:

  • Terminal: export SUPABASE_INTERNAL_IMAGE_REGISTRY=docker.io then supabase start
  • docker-compose: add SUPABASE_INTERNAL_IMAGE_REGISTRY: docker.io under the environment: key of your Supabase service
  • GitHub Actions / GitLab CI: add SUPABASE_INTERNAL_IMAGE_REGISTRY: docker.io to your job's env: block

You ran supabase start and it either hung silently, logged pull access denied for public.ecr.aws, or threw an error referencing supabase_internal_image_registry. The CLI isn't broken — your network is blocking AWS ECR (public.ecr.aws), which is where Supabase CLI pulls its Docker images by default. One environment variable fixes it in 30 seconds.

What is supabase_internal_image_registry?

SUPABASE_INTERNAL_IMAGE_REGISTRY is the environment variable the Supabase CLI reads at startup to decide which container registry to pull images from. It controls every docker pull the CLI issues — the Postgres image, PostgREST, GoTrue, Kong, Realtime, Storage, and the rest of the local dev stack.

Default value: public.ecr.aws

The default points at AWS ECR Public Gallery (public.ecr.aws/supabase/...). This is why errors mention public.ecr.aws even if you've never configured anything yourself — that's the hardcoded fallback.

Why ECR gets blocked:

  • Corporate firewalls that allowlist registries explicitly and don't include public.ecr.aws
  • Cloud CI environments (some Google Cloud build agents, some Azure DevOps pools) that restrict outbound HTTPS to certain IP ranges
  • Some VPN configurations that route Docker daemon traffic through a proxy that doesn't trust the ECR certificate chain
  • Occasionally: regional AWS outages or ECR throttling that makes pulls time out

The fix works in all of these cases because you're redirecting to Docker Hub (docker.io), which is widely allowed by default.

The fix: terminal (30 seconds)

Export the variable and run supabase start in the same shell session:

export SUPABASE_INTERNAL_IMAGE_REGISTRY=docker.io
supabase start

Or as a single inline command if you don't want to set the variable globally:

SUPABASE_INTERNAL_IMAGE_REGISTRY=docker.io supabase start

The inline form is useful for a one-off test. If it works, you'll see Docker pulling from docker.io/supabase/... instead of public.ecr.aws/supabase/... in the output.

Persist it in your shell profile

Running the export every terminal session gets old fast. Add it to your shell's startup file:

echo 'export SUPABASE_INTERNAL_IMAGE_REGISTRY=docker.io' >> ~/.zshrc
source ~/.zshrc

For bash users:

echo 'export SUPABASE_INTERNAL_IMAGE_REGISTRY=docker.io' >> ~/.bashrc
source ~/.bashrc

After sourcing, run echo $SUPABASE_INTERNAL_IMAGE_REGISTRY to confirm it prints docker.io before continuing.

docker-compose override

If you run the Supabase stack directly via docker-compose.yml rather than through the CLI, add the variable to the environment block of the relevant service:

services:
  supabase:
    image: supabase/cli:latest
    environment:
      - SUPABASE_INTERNAL_IMAGE_REGISTRY=docker.io

If you use an .env file alongside your compose file, add it there instead — docker-compose automatically picks up variables from .env in the same directory:

# .env
SUPABASE_INTERNAL_IMAGE_REGISTRY=docker.io

Then reference it in your compose file without a hardcoded value:

environment:
  - SUPABASE_INTERNAL_IMAGE_REGISTRY

CI/CD environments

GitHub Actions

Add the variable to the env: block of the job or the specific step that calls supabase start:

jobs:
  test:
    runs-on: ubuntu-latest
    env:
      SUPABASE_INTERNAL_IMAGE_REGISTRY: docker.io
    steps:
      - uses: actions/checkout@v4
      - name: Start Supabase
        run: supabase start

Setting it at the job level means every step in the job inherits it. If you only want it for the supabase start step, move the env: block inside that step instead.

GitLab CI

test:
  variables:
    SUPABASE_INTERNAL_IMAGE_REGISTRY: docker.io
  script:
    - supabase start

Other CI platforms

Any CI system that supports setting environment variables for a job will work. The variable just needs to be in scope when the Supabase CLI process starts.

Verifying it worked

After setting the variable, start Supabase and watch the pull output. You should see image references change:

Before (ECR, blocked):

pulling supabase/postgres:... from public.ecr.aws/supabase/postgres

After (Docker Hub, working):

pulling supabase/postgres:... from docker.io/supabase/postgres

If you want to watch Docker pull events in real time in a separate terminal:

docker events --filter type=image --filter event=pull

Run that in one terminal, then trigger supabase start in another. Each pull will appear as it happens, showing the full image reference including the registry hostname.

Using a private registry mirror

For teams in air-gapped environments or strict enterprise networks where both ECR and Docker Hub are blocked, point the variable at an internal registry mirror instead:

export SUPABASE_INTERNAL_IMAGE_REGISTRY=mycompany.jfrog.io
supabase start

You must pre-mirror all the Supabase images your CLI version needs into that registry first. The specific images and tags depend on the Supabase CLI version — check the release notes for your CLI version to get the full image list, or run supabase start with ECR/Docker Hub access once on an unrestricted machine to capture which images are pulled.

Common registry options: JFrog Artifactory, AWS ECR in a different region with an allowlisted endpoint, Harbor, or a Nexus proxy repository.

Still failing after the fix?

Docker Hub rate limit: Unauthenticated Docker Hub pulls are rate-limited to 100 pulls per 6 hours per IP. On a shared CI runner, you can hit this fast. Fix:

docker login
# then retry
SUPABASE_INTERNAL_IMAGE_REGISTRY=docker.io supabase start

For CI, store your Docker Hub credentials as secrets and add a docker login step before supabase start.

Images not yet mirrored on Docker Hub: In rare cases, a new Supabase CLI version references a Docker image tag that hasn't been pushed to Docker Hub yet. The solution is to either downgrade the CLI version temporarily or wait for the mirror to catch up. Check the Supabase CLI releases for known issues.

Still getting connection refused after a clean pull: The registry variable only affects image pulling, not container networking. If your containers start correctly (you can see them in docker ps --filter name=supabase) but your app can't connect, the issue is in port mapping or connection strings — not the registry. See the full Supabase connection refused troubleshooting guide for a systematic walkthrough of those failures.


Related guides:

Still blocked?

This fix didn't work for your setup? Get a senior engineer on your screen in 30 minutes — fixed or refunded.

Reserve My Spot →
Still stuck?

Get a senior engineer on your screen.

30-minute live screen-share sessions with a vetted senior dev. Fixed or fully refunded — no questions asked.

No spam. Just a heads-up when sessions open.

Related Articles